- 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节点,允许省略常见依赖的<version>
- 恰到好处的资源过滤
- 恰到好处的插件配置(exec插件,surefire,Git commit ID,shade)
- 恰到好处的对application.properties和application.yml进行筛选,包括特定profile(profile-specific)的文件,比如application-foo.properties和application-foo.yml
覆盖parent POM中(实际是spring-boot-dependencies中的)个别的依赖的属性,如版本
<!-- 修改个别依赖属性:如版本 -->
<properties>
<hibernate-validator.version>5.4.1.Final</hibernate-validator.version>
</properties>
使用parent POM时,打包插件pring-boot-maven-plugin只需引用,parent POM中已经做了配置
完成的POM如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.top.test.springboot</groupId>
<artifactId>test-springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- 修改个别依赖属性:如版本 -->
<properties>
<hibernate-validator.version>5.4.1.Final</hibernate-validator.version>
</properties>
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.7.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 1.2.2 不继承 spring-boot-starter-parent
- 仍可享受spring-boot-dependencies的dependencyManagement版本控制(使用scope=import方式引入);但不包括 plugin management
- spring-boot-starter-parent POM includes <executions> configuration to bind the repackage goal. 如果不用parent POM,就需要自己声明这个配置,参见Spring Boot Maven Plugin
- 如果不用spring-boot-maven-plugin,或用了但没加<executions> 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 ...<profiles>\n <profile>dd\n <i... @16:8) @ /usr/share/maven/conf/settings.xml, line 16, column 8
[WARNING]
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.top.test.springboot:test-springboot:jar:0.0.1-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.springframework.boot:spring-boot-maven-plugin is missing. @ line 76, column 12
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building test-springboot 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ test-springboot ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.2:compile (default-compile) @ test-springboot ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ test-springboot ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.2:testCompile (default-testCompile) @ test-springboot ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.17:test (default-test) @ test-springboot ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ test-springboot ---
[INFO] Building jar: /home/yuzhou/personalDev/workspace/test-springboot/target/test-springboot-0.0.1-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:13 min
[INFO] Finished at: 2017-10-13T15:05:48+08:00
[INFO] Final Memory: 20M/249M
[INFO] ------------------------------------------------------------------------
打成的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
<!-- parent POM中Spring Boot Maven Plugin的配置(repackage+mainClass) -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${start-class}</mainClass>
</configuration>
</plugin>
- 不使用parent POM时,完整的POM如下
- 使用scope=import解决单继承(scope只能放在dependencyManagement中)
- 这样既能使用spring-boot-dependencies中的依赖管理,又能继承别的parent
- 覆盖spring-boot-dependencies POM中版本也如下(e.g hibernate-validator)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.top.test.springboot</groupId>
<artifactId>test-springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<!-- 覆盖Override hibernate-validator train provided by Spring Boot -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.3.5.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 导入spring-boot-dependencies,使用其依赖管理 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.7.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>${start-class}</mainClass>
<!-- 写死也可以 -->
<!-- <mainClass>com.top.test.controller.HelloApplication</mainClass> -->
</configuration>
</plugin>
</plugins>
</build>
</project>
- 1.2.3
低版本的springboot在spring-boot-starter-parent中选择了保守的Java兼容策略(支持Java6),若要使用其他的Java版本:
<properties>
<java.version>1.8</java.version>
</properties>
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