- 1.系统构建
- 2.代码构建
- 3.配置类和相关注解
- 4.运行
基于版本:Spring Boot 1.5.7.RELEASE
1.系统构建(POM.xml)
1.1 依赖管理说明
- Spring Boot依赖使用的groupId都是org.springframework.boot
- spring boot每个版本都提供了该版本支持的依赖列表,包括它们的版本,所以构建POM时不必指定这些依赖的版本(列表包括spring模块和精选的第三方库)
☞ spring boot依赖列表- 也可以自己指定版本覆盖spring boot中默认的版本,但不推荐。因为每版Spring Boot都会关联一个Spring框架的基础版本,所以不建议自己指定这些Spring Framework版本
- spring boot建议使用Maven/Gradle进行依赖管理
1.2 使用Maven管理依赖
两种方式:继承/不继承spring-boot-starter-parent
- 1.2.1 继承 spring-boot-starter-parent
实际上spring-boot-starter-parent POM继承了顶层父POM:spring-boot-dependencies
在spring-boot-dependencies中进行dependencyManagement和pluginManagement
spring-boot-starter-parent提供了一些sensible defaults:
- 默认编译级别为Java 1.6
- 源码编码为UTF-8
- 继承spring-boot-dependenciesPOM的Dependency management节点,允许省略常见依赖的
- 恰到好处的资源过滤
- 恰到好处的插件配置(exec插件,surefire,Git commit ID,shade)
- 恰到好处的对application.properties和application.yml进行筛选,包括特定profile(profile-specific)的文件,比如application-foo.properties和application-foo.yml
覆盖parent POM中(实际是spring-boot-dependencies中的)个别的依赖的属性,如版本
5.4.1.Final
使用parent POM时,打包插件pring-boot-maven-plugin只需引用,parent POM中已经做了配置
完成的POM如下:
4.0.0
com.top.test.springboot
test-springboot
0.0.1-SNAPSHOT
5.4.1.Final
org.springframework.boot
spring-boot-starter-parent
1.5.7.RELEASE
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-maven-plugin
- 1.2.2 不继承 spring-boot-starter-parent
- 仍可享受spring-boot-dependencies的dependencyManagement版本控制(使用scope=import方式引入);但不包括 plugin management
- spring-boot-starter-parent POM includes
configuration to bind the repackage goal. 如果不用parent POM,就需要自己声明这个配置,参见Spring Boot Maven Plugin
- 如果不用spring-boot-maven-plugin,或用了但没加
configuration,就不能打成fat/uber jars(项目里引用的jar就没打进去)。如下,打包过程就没用到spring-boot-maven-plugin来repackage:
$ mvn package
[WARNING]
[WARNING] Some problems were encountered while building the effective settings
[WARNING] expected START_TAG or END_TAG not TEXT (position: TEXT seen ...\n dd\n
打成的jar内文件也不包括项目引用的nested jar
$ jar tvf target/test-springboot-0.0.1-SNAPSHOT.jar
0 Fri Oct 13 15:05:50 CST 2017 META-INF/
132 Fri Oct 13 15:05:48 CST 2017 META-INF/MANIFEST.MF
0 Fri Oct 13 14:36:26 CST 2017 com/
0 Fri Oct 13 14:36:26 CST 2017 com/top/
0 Fri Oct 13 14:36:26 CST 2017 com/top/test/
0 Fri Oct 13 14:37:00 CST 2017 com/top/test/controller/
0 Fri Oct 13 14:36:26 CST 2017 com/top/test/springboot/
1326 Fri Oct 13 14:39:18 CST 2017 com/top/test/controller/HelloApplication$1.class
1432 Fri Oct 13 14:39:18 CST 2017 com/top/test/controller/HelloApplication.class
626 Fri Oct 13 14:36:26 CST 2017 com/top/test/springboot/HelloController.class
0 Fri Oct 13 15:05:50 CST 2017 META-INF/maven/
0 Fri Oct 13 15:05:50 CST 2017 META-INF/maven/com.top.test.springboot/
0 Fri Oct 13 15:05:50 CST 2017 META-INF/maven/com.top.test.springboot/test-springboot/
2316 Fri Oct 13 15:03:46 CST 2017 META-INF/maven/com.top.test.springboot/test-springboot/pom.xml
139 Thu Oct 12 17:52:08 CST 2017 META-INF/maven/com.top.test.springboot/test-springboot/pom.properties
所以无法启动
$ java -jar target/test-springboot-0.0.1-SNAPSHOT.jar
target/test-springboot-0.0.1-SNAPSHOT.jar中没有主清单属性
- parent POM中Maven Plugin的配置,需要将此打包配置添加到自己的POM
org.springframework.boot
spring-boot-maven-plugin
repackage
${start-class}
- 不使用parent POM时,完整的POM如下
- 使用scope=import解决单继承(scope只能放在dependencyManagement中)
- 这样既能使用spring-boot-dependencies中的依赖管理,又能继承别的parent
- 覆盖spring-boot-dependencies POM中版本也如下(e.g hibernate-validator)
4.0.0
com.top.test.springboot
test-springboot
0.0.1-SNAPSHOT
org.hibernate
hibernate-validator
5.3.5.Final
pom
import
org.springframework.boot
spring-boot-dependencies
1.5.7.RELEASE
pom
import
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-maven-plugin
repackage
${start-class}
- 1.2.3
低版本的springboot在spring-boot-starter-parent中选择了保守的Java兼容策略(支持Java6),若要使用其他的Java版本:
1.8
1.3 starter POM
starters中包含了很多搭建&快速运行项目所需的依赖,并提供一致的,可管理传递性的依赖集:
spring boot starters reference
官方starters遵循相似的命名模式: spring-boot-starter-*
第三方starter(acme)通常命名:acme-spring-boot-starter
2.代码构建
两点最佳实践
2.1 default package的影响
- 当类没有声明package时,它被认为处于default package下;
- 不推荐使用default package,因为对使用@ComponentScan、@EntityScan或@SpringBootApplication注解的Spring Boot应用来说,它会扫描每个jar中的类,这会造成一定的问题;
- 建议遵循Java推荐的包命名规范,使用反转的域名。
2.2 main application class的位置
com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
+- CustomerController.java
- 1.建议将main application class放到其他包的顶层(root package),并将在该main类添加@EnableAutoConfiguration,这样就隐式地定义了一个基础的包搜索路径,(@ComponentScan)以搜索某些特定的注解实体(比如@Service,@Component等)
- 2.@EnableAutoConfiguration一般只有一个,加在main application class上,开启自动配置
- 3.这种root package方式,就可以直接使用@ComponentScan而不需要指定basePackage属性;或者也可以使用@SpringBootApplication注解。
- 4.@SpringBootApplication=@EnableAutoConfiguration+@ComponentScan+@Configuration
- 5.@ComponentScan收集所有Spring组件,如@Configuration/@Controller等
3.配置类和相关注解
@Configuration
@EnableAutoConfiguration
@ComponentScan
@SpringBootApplication
3.1 @Configuration:
- 不需要:当该类已经作为参数传递到SpringApplication.run()中
注:虽然SpringApplication.run(HelloApplication.class, args); 中已经把main application class传进了run(),一般还是在main类=HelloApplication.class加上@Configuration,作为主配置类候补
Usually the class that defines the main method is also a good candidate as the primary @Configuration.
----------测试类(不加@Configuration)----------
public class test1 {
@Bean
public String haha() {
return new String("haha");
}
}
----------main类(把test1.class也作为参数传递给run())----------
@EnableAutoConfiguration
@ComponentScan
public class HelloApplication {
public static void main(String[] args) {
Object[] classes = new Object[]{HelloApplication.class,test1.class};
SpringApplication.run(classes, args);
}
}
----------启动结果:创建了test1和haha实例----------
Let's inspect the beans provided by Spring Boot:
...
commandLineRunner(就在HelloApplication.class中,作为参数传给了run())
haha
helloApplication
helloController(有@Controller注解&&@ComponentScan能扫描到)
test1
...
- 需要:当该类没有作为参数传递到run()中,就需要加@Configuration,并且@ComponentScan(main configuration class上)要能扫描到该配置类
----------测试类(需要加@Configuration)----------
@Configuration
public class test1 {
@Bean
public String haha() {
return new String("haha");
}
}
----------main类(test1.class没有传递给run())----------
@EnableAutoConfiguration
@ComponentScan
public class HelloApplication {
public static void main(String[] args) {
//Object[] classes = new Object[]{HelloApplication.class,test1.class};
//SpringApplication.run(classes, args);
SpringApplication.run(HelloApplication.class, args);
}
}
----------启动结果:创建了test1和haha实例----------
Let's inspect the beans provided by Spring Boot:
...
commandLineRunner(就在HelloApplication.class中,作为参数传给了run())
haha
helloApplication
helloController(有@Controller注解&&@ComponentScan能扫描到)
test1
...
- 如果必须使用XML配置,建议从一个标记@Configuration的类开始。与@Import、@ImportResource配合使用。用来引入其他类中的@Bean或XML配置文件(用@Import导入的Bean,即使它们所在的类有@Configuration注解,也不会创建它们所在的类的实例,相当于都在一个配置文件中)
3.2 @EnableAutoConfiguration
Spring Boot的自动配置,尝试根据添加的jar依赖自动配置Spring应用
- 实现自动配置:添加@EnableAutoConfiguration或@SpringBootApplication注解到其中一个@Configuration类上
- 应该只添加一个@EnableAutoConfiguration注解,通常建议添加到主配置类(primary @Configuration)上(一般用main入口类作为主配置类)
- 替换:Auto-configuration是非侵入性的,可定义自己的配置类来替换
- 禁用:可以从annotation || properties 禁用:
@EnableAutoConfiguration注解的exclude/excludeName属性禁用自动配置
也可以在配置文件中指定:spring.autoconfigure.exclude- 查看使用了哪些自动配置:java -jar xxx.jar --debug
3.3 @ComponentScan
spring框架的注解,自动收集spring组件:@Service/@Component/@Configuration等
3.4 @SpringBootApplication
@SpringBootApplication=@Configuration+@EnableAutoConfiguration+@ComponentScan
3.5 Spring Beans和依赖注入
SpringBoot的Beans注解和@Autowired的用法跟Spring Framework一样
4.运行
- 1.在project目录下,命令行执行mvn spring-boot:run
- 2.借助IDE:执行main方法Run as Java Application || 配置maven build(原理同1)
- 3.打包成jar(内嵌了HTTP服务器), java -jar xxx.jar