42

Spring Boot 2.x基础教程:工程结构推荐

 5 years ago
source link: http://blog.didispace.com/spring-boot-learning-21-1-2/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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支持,您的关注是我坚持的动力!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK