Spring Boot框架本身并没有对工程结构有特别的要求,但是按照最佳实践的工程结构可以帮助我们减少可能会遇见的坑,尤其是Spring包扫描机制的存在,如果您使用最佳实践的工程结构,可以免去不少特殊的配置工作。

典型示例

以下结构是比较推荐的package组织方式:

com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
| +- CustomerController.java
|
  • root packagecom.example.myproject,所有的类和其他package都在root package之下。
  • 应用主类:Application.java,该类直接位于root package下。通常我们会在应用主类中做一些框架配置扫描等配置,我们放在root package下可以帮助程序减少手工配置来加载到我们希望被Spring加载的内容
  • com.example.myproject.domain包:用于定义实体映射关系与数据访问相关的接口和实现
  • com.example.myproject.service包:用于编写业务逻辑相关的接口与实现
  • com.example.myproject.web:用于编写Web层相关的实现,比如:Spring MVC的Controller等

上面的结构中,root package与应用主类的位置是整个结构的关键。由于应用主类在root package中,所以按照上面的规则定义的所有其他类都处于root package下的其他子包之后。默认情况下,Spring Boot的应用主类会自动扫描root package以及所有子包下的所有类来进行初始化。

什么意思呢?举个例子,假设我们将com.example.myproject.web包与上面所述的root packagecom.example.myproject放在同一级,像下面这样:

com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
| +- CustomerController.java
|

这个时候,应用主类Application.java在默认情况下就无法扫描到com.example.myproject.web中的Controller定义,就无法初始化Controller中定义的接口。

非典型结构下的初始化

那么如果,我们一定要加载非root package下的内容怎么办呢?

方法一:使用@ComponentScan注解指定具体的加载包,比如:

@SpringBootApplication
@ComponentScan(basePackages="com.example")
public class Bootstrap { public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
} }

这种方法通过注解直接指定要扫描的包,比较直观。如果有这样的需求也是可以用的,但是原则上还是推荐以上面的典型结构来定义,这样也可以少写一些注解,代码更加简洁。

方法二:使用@Bean注解来初始化,比如:

@SpringBootApplication
public class Bootstrap { public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
} @Bean
public CustomerController customerController() {
return new CustomerController();
} }

这种方法在业务开发的时候并不是特别推荐,更适合用于框架封装等场景,关于更多封装上的技巧,后面我们在进阶教程中详细讲解。

如果读者觉得自己团队使用的工程结构不错,欢迎留言分享~

代码示例

本教程配套仓库:

如果您觉得本文不错,欢迎Star支持,您的关注是我坚持的动力!

Spring Boot 2.x基础教程:工程结构推荐的更多相关文章

  1. Spring Boot 2.x基础教程:事务管理入门

    什么是事务? 我们在开发企业应用时,通常业务人员的一个操作实际上是对数据库读写的多步操作的结合.由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻 ...

  2. Spring Boot 2.x基础教程:使用JTA实现多数据源的事务管理

    在一个Spring Boot项目中,连接多个数据源还是比较常见的.之前也介绍了如何在几种常用框架的场景下配置多数据源,具体可见: Spring Boot 2.x基础教程:JdbcTemplate的多数 ...

  3. Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档

    随着前后端分离架构和微服务架构的流行,我们使用Spring Boot来构建RESTful API项目的场景越来越多.通常我们的一个RESTful API就有可能要服务于多个不同的开发人员或开发团队:I ...

  4. Spring Boot 2.x基础教程:JSR-303实现请求参数校验

    请求参数的校验是很多新手开发非常容易犯错,或存在较多改进点的常见场景.比较常见的问题主要表现在以下几个方面: 仅依靠前端框架解决参数校验,缺失服务端的校验.这种情况常见于需要同时开发前后端的时候,虽然 ...

  5. Spring Boot 2.x基础教程:Swagger接口分类与各元素排序问题详解

    之前通过Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档一文,我们学习了如何使用Swagger为Spring Boot项目自动生成API文档,有不少用户留言问了关于文档 ...

  6. Spring Boot 2.x基础教程:Swagger静态文档的生成

    前言 通过之前的两篇关于Swagger入门以及具体使用细节的介绍之后,我们已经能够轻松地为Spring MVC的Web项目自动构建出API文档了.如果您还不熟悉这块,可以先阅读: Spring Boo ...

  7. Spring Boot 2.x基础教程:使用国产数据库连接池Druid

    上一节,我们介绍了Spring Boot在JDBC模块中自动化配置使用的默认数据源HikariCP.接下来这一节,我们将介绍另外一个被广泛应用的开源数据源:Druid. Druid是由阿里巴巴数据库事 ...

  8. Spring Boot 2.x基础教程:找回启动日志中的请求路径列表

    如果您看过之前的Spring Boot 1.x教程,或者自己原本就对Spring Boot有一些经验,或者对Spring MVC很熟悉.那么对于Spring构建的Web应用在启动的时候,都会输出当前应 ...

  9. Spring Boot 2.x基础教程:使用MyBatis的XML配置方式

    上一篇我们介绍了如何在Spring Boot中整合我们国人最常用的MyBatis来实现对关系型数据库的访问.但是上一篇中使用了注解方式来实现,而对于很多MyBatis老用户还是习惯于XML的开发方式, ...

  10. Spring Boot 2.x基础教程:Spring Data JPA的多数据源配置

    上一篇我们介绍了在使用JdbcTemplate来做数据访问时候的多数据源配置实现.接下来我们继续学习如何在使用Spring Data JPA的时候,完成多数据源的配置和使用. 添加多数据源的配置 先在 ...

随机推荐

  1. Error【0002】:YUM本地源配置问题

    1.1 问题背景 通过VMware workstation创建虚拟机,在虚拟机的CDROM设备中,装载操作系统镜像.然后通过mount -o loop的方式,将CDROM设备挂载到系统的/mnt/cd ...

  2. Charles模拟网络请求页面的网络超时测试

    正常情况下网络连接超时可能的原因有以下几点: 1.网络断开,手动的关掉了网络的连接 2.网络阻塞,导致你不能在程序默认等待时间内得到回复数据包. 3.网络不稳定,网络无法完整传送服务器信息. 4.系统 ...

  3. shell脚本中cd命令无效

    对于一段包含cd 命令的shell脚本(test.sh): #!/bin/bash cd .. mkdir ./test 运行: sh ./test.sh 脚本运行时无法在上级目录建立test文件 此 ...

  4. 从壹开始前后端分离 42 ║支持多种数据库 & 快速数据库生成

    缘起 哈喽大家周三好,休息了一段时间,打算准备找工作了

  5. Vue 进阶之路(三)

    之前的文章我们已经对 vue 有了初步认识,这篇文章我们通过一个例子说一下 vue 的方法 methods,计算属性 computed 和监听器 watch. 现在我们有一个需求,变量 firstNa ...

  6. Mybatis之旅第五篇-动态SQL

    一.引言 在之前的CRUD例子中,都是一些很简单的SQL,然而实际的业务开发中会有一些复杂的SQL,我们经常需要拼接SQL,拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号.Myba ...

  7. 关于MQ,你必须知道的

    我走过最长的路是你的套路 女:二号男嘉宾,假如我们牵手成功后,你会买名牌包包给我吗? 男:那你会听话吗? 女:会 听话. 男:听话 咱不买! OK那么消息队列MQ有什么套路呢?(这个话题转换生硬度连我 ...

  8. 一段简单的显示当前页面FPS的代码

    写前端代码,尤其是做一个前端框架的时候,经常需要及时知道代码的大致性能,这时候如果能有个好的办法能一直看到当前页面的fps就好了. 整体思路是一秒有一千毫秒,先记录当前时间作为最后一次记录fps的时间 ...

  9. 使用Springboot + Gradle快速整合Mybatis-Plus

    使用Springboot + Gradle快速整合Mybatis-Plus 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] MyBatis-Plus(简称 MP)是一个 MyBatis ...

  10. 入门rocketmq从浅到深

    目录 一.引言 二.介绍 三.Rocketmq关键概念 1.主题与标签 2.发送与订阅群组 3.Broker与NameServer 4.广播消费与集群消费 5.消息队列 6.集群方式 7.顺序消息 8 ...