相关文章spring boot官方文档 2.2.6 Getting Started.
Using Spring Boot
- 1. Build Systems,构建项目
- 1.1. Dependency Management 依赖管理
- 1.2. Maven
- 1.2.1. Inheriting the Starter Parent
- 1.2.2. Using Spring Boot without the Parent POM
- 1.2.3. Using the Spring Boot Maven Plugin 使用 Spring Boot 的maven插件
- 1.3. Gradle
- 1.4. Ant
- 1.5. Starters
- 2.1. Using the “default” Package
- 2.2. Locating the Main Application Class(定位主应用类)
- 3. Configuration Classes(配置类)
- 4. Auto-configuration
- 4.1. Gradually Replacing Auto-configuration(逐步替换自动配置)
- 4.2. Disabling Specific Auto-configuration Classes(禁用某个具体的自动配置)
- 5. Spring Beans and Dependency Injection
- 6. Using the @SpringBootApplication Annotation
- 7. Running Your Application
- 7.1. Running from an IDE
- 7.2. Running as a Packaged Application
- 7.3. Using the Maven Plugin
- 7.4. Using the Gradle Plugin
- 7.5. Hot Swapping(热插拔)
- 8. Developer Tools
- 8.1. Property Defaults
- 8.2. Automatic Restart
- Restart vs Reload
- 8.2.1. Logging changes in condition evaluation
- 8.2.2. Excluding Resources
- 8.2.3. Watching Additional Paths
- 8.2.4. Disabling Restart
- 8.2.5. Using a Trigger File
- 8.2.6. Customizing the Restart Classloader
- 8.2.7. Known Limitations
- 8.3. LiveReload
- 8.4. Global Settings
- 8.5. Remote Applications
- 9. Packaging Your Application for Production
这部分讲解更多的关于使用springboot的细节,它包括:构建项目(build systems),自动配置( auto-configuration)以及如何运行应用。也包含一些练习,这个相当于一个工具文档,用于查阅
1. Build Systems,构建项目
强烈建议选择一个支持依赖管理( dependency management )的项目构建工具,可以发布到maven 中心仓库 ,推荐选择 maven或者Gradle 也可以选择Ant,但是支持性没有maven或者Gradle 好
1.1. Dependency Management 依赖管理
每一版的springboot 都提供了它支持的依赖列表,在配置依赖的时候,不需要提供版本设置,因为springboot 已经为你管理了,升级springboot版本的时候,依赖管理也会对应的升级
TIP:如果需要,也可以指定一个版本,覆盖springboot推荐的版本;
依赖列表几乎包括了所有可能使用的spring 模板,和一些第三方的库,可以通过maven或者 Gradle 方式添加
Note:每个版本的Spring Boot 都是关联一个基本版本的Spring 框架,极度推荐不要覆盖Spring的版本
1.2. Maven
使用maven的方式,可以先查看 spring-boot-starter-parent 里面包含的内容
java 1.8 以及默认的编译级别
UTF-8 的编码格式
在pom文件中包含管理常见依赖版本的依赖管理片段,这个依赖管理使得在引入依赖额时候,可以省略版本信息
一个带有 id 的打包执行器
智能的 资源过滤
合理的插件管理
合理的资源过滤,例如(application.properties and application.yml)特定 的配置文件
注意:自从 Spring 的 application.properties 和 application.yml 能使用占位符 ${} ,Maven的过滤就变成了 @…@ 的方式,(可以设置 resource.delimiter 这个参数,来设置自己想要的值)
1.2.1. Inheriting the Starter Parent
为了让项目继承自 spring-boot-starter-parent 需要引入下面的starter
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
</parent>
注意:在这个依赖中,需要注意的是 Spring Boot 的版本,在引入其他的starter 的时候,最后省略版本号
上面配置之后,也可以指定单个依赖的版本
<properties>
<spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>
1.2.2. Using Spring Boot without the Parent POM
如果不想使用 spring-boot-starter-parent ,但是还是想用依赖管理(但是没有插件管理),可以使用 scope=import dependency,像下面这样
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
上面的示例不可以通过 property 覆盖单独的依赖,所以,为了设置版本,需要在依赖管理里面加一个实体,例如
<dependencyManagement>
<dependencies>
<!-- Override Spring Data release train provided by Spring Boot -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>Fowler-SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
1.2.3. Using the Spring Boot Maven Plugin 使用 Spring Boot 的maven插件
SpringBoot提供了一个 Maven插件,可以把项目打包成一个可执行的jar文件,添加插件到里面
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
如果想用 Spring Boot starter 的父类的pom,只需要添加插件即可,不需要配置,除非你需要改变原来父类定义的配置
1.3. Gradle
1.4. Ant
1.5. Starters
Starter 是一系列依赖的集合,可以一站式的直接使用 所有的Spring及其相关的技术,不需要关注示例代码,也不需要复制粘贴许多其他的依赖(简而言之就是引入starter就够了),例如,如果想用 Spring 和JPA来连接数据库,只要引入一个 spring-boot-starter-jpa 的依赖到项目即可。
starter包含了构建项目的一系列依赖
starter 命名
spring-boot-starter-*
第三方的starter命名:是以第三方的项目名称开头的,如:一个第三方的starter project 项目叫做 thirdpartyproject 那么对应的 starter 命名应该是 thirdpartyproject -spring-boot-starter
下面是springboot提供的starter列表
In addition to the application starters, the following starters can be used to add production ready features:
Finally, Spring Boot also includes the following starters that can be used if you want to exclude or swap specific technical facets:
- Structuring Your Code
spring boot不要求特定的代码格式,但是下面有一些经验
2.1. Using the “default” Package
当一个类没有写在某一个包里面的时候,应该包含在 “default package” 里面,不推荐使用默认的包,这样可能会引起一些问题,当使用 @ComponentScan, @ConfigurationPropertiesScan, @EntityScan, or @SpringBootApplication 这些注解的时候,因为每个jar包下面的每个class 都会被扫描。
推荐使用 com.example.project 的包结构
2.2. Locating the Main Application Class(定位主应用类)
就是标识应用的入口
推荐在 root package 下面放置 主类,而非其他的包,@SpringBootApplication注解需要放在主类上,这个注解含蓄的定义了一个基本的包扫描机制,扫描特定的项,(大致意思就是说,加了这个注解的类,会自动的扫描这个包及其子包下面的所有的加了注解的类,让spring管理)
TIP:如果不想使用 @SpringBootApplication这个注解,可以使用 @EnableAutoConfiguration 和@ComponentScan注解,也包含了包扫描的效果
下面是一种常规的结构
com
± example
± myapplication
± Application.java
|
± customer
| ± Customer.java
| ± CustomerController.java
| ± CustomerService.java
| ± CustomerRepository.java
|
± order
± Order.java
± OrderController.java
± OrderService.java
± OrderRepository.java
Application.java 会使用 @SpringBootApplication 注解,声明 主方法
package com.example.myapplication;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3. Configuration Classes(配置类)
Spring Boot支持基于Java的配置,虽然极有可能使用SpringApplication 和 xml 的方式来配置资源,但是还是推荐把主要的资源整合成为一个 单独的带有 @Configuration 注解的配置类。通常有 main 方法的类是比较好的加 @Configuration 的选择
这里有疑问?????????????????
这里的意思是推荐在有SpringApplication 的地方加一个 @Configuration ,让它作为配置类吗???
2020年4月17日11:13:01
TIP
在想配置什么的时候,想到 Enable* 注解
3.1. Importing Additional Configuration Classes
你不需要把所有的配置(@Configuration)都放在一个类里面,@Import注解可以注入其他的配置类,也可以通过 @ComponentScan 在自主的扫描所有的Spring组件(包括@Configuration类)
3.2. Importing XML Configuration
如果必须使用xml配置,还是推荐写一个 配置类(@Configuration),可以使用 @ImportResource注解加载 xml 配置文件
4. Auto-configuration
Spring Boot尝试基于添加的依赖自动的配置Spring应用。例如,如果classpath下有一个HSQLDB,就不需要手动配置数据库连接的bean,Spring Boot会自动配置一个内存中的数据库(in-memory database)。
为了能够让Spring Boot 自动配置,需要在其中一个配置类(带有@Configuration注解的类)上添加@EnableAutoConfiguration 或者 @SpringBootApplication 注解
TIP:只能添加一个 @SpringBootApplication 或者 @EnableAutoConfiguration 注解,推荐只添加一个在主配置类上
4.1. Gradually Replacing Auto-configuration(逐步替换自动配置)
自动配置是非侵入式的,在任意的点上,都可以用自定义配置取代自动配置的某一具体部分,例如,如果你添加了自己的 DataSource Bean,默认嵌入的数据库支持就会作为备份使用
如果需要查看自动配置已经应用了哪些,选择 debug启动应用,这样会打印日志到控制台
(Doing so enables debug logs for a selection of core loggers and logs a conditions report to the console.)
4.2. Disabling Specific Auto-configuration Classes(禁用某个具体的自动配置)
如果你不想应用某个具体的自动配置,可以在 @SpringBootApplication 注解里面添加 exclude属性来禁用,示例如下
import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
public class MyApplication {
}
如果需要禁用的类不在classpath,可以使用 @SpringBootApplication 注解的属性 excludeName ,用全类名来定位,如果用的是 @EnableAutoConfiguration 而不是 @SpringBootApplication,也是可以使用 exclude 和 excludeName 这两个属性的。也可以使用 spring.autoconfigure.exclude 属性
TIP:
虽然自动配置类是 public,但是只是能够通过API的类名来禁用自动配置,类内部的内容比如嵌套的配置类或者是bean内部的方法只能是内部使用,不推荐直接使用
5. Spring Beans and Dependency Injection
一般使用 @ComponentScan 来扫描bean,使用 @Autowired 做构造注入
如果把代码放在 应用的root package下面,可以添加@ComponentScan 注解,不需要加参数,那么所有的组件(@Component,@Service,@Repository,@Controller 等),就会自动的注册为Spring的bean
下面的示例展示了一个 @Service 的 bean使用构造注入的方式,获得了一个需要的 RiskAssessor bean的过程:
package com.example.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DatabaseAccountService implements AccountService {
private final RiskAssessor riskAssessor;
@Autowired
public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
// ...
}
注:DatabaseAccountService 加了@Service注解,就是本身是一个 Service bean,然后里面通过构造注入的方式(@Autowired 加在了构造函数上)注入了一个RiskAssessor bean
如果一个bean有一个构造函数,也可以省略 @Autowired注解:
@Service
public class DatabaseAccountService implements AccountService {
private final RiskAssessor riskAssessor;
public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
// ...
}
Note:请注意,使用构造函数注入可以将riskAssessor字段标记为final,表示它不能随后更改。
6. Using the @SpringBootApplication Annotation
一个单独的@SpringBootApplication注解,使用之后具有以下三个特性
@EnableAutoConfiguration 开启springboot的自动配置
@ComponentScan 扫描位于主包下面的组件
@Configuration 允许注册额外的bean,或者注入额外的配置类
package com.example.myapplication;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
笔者的理解:上面的的大致意思就是说,一个@SpringBootApplication注解,相当于三个注解(@Configuration @EnableAutoConfiguration @ComponentScan)的作用之和
TIP:@SpringBootApplication注解提供别名可以定制 @EnableAutoConfiguration 和@ComponentScan 的属性
TIP:没有一个注解的特性是强制性的,可以选择替换任意一个注解已经开启的特性,比如:如果不想使用组件扫描或者配置属性扫描,可以像下面这样做
(就是说可以通过某中组合,来避免使用某个注解自带的某个功能)
package com.example.myapplication;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@Import({ MyConfig.class, MyAnotherConfig.class })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
在本例中,Application与任何其他Spring Boot应用程序一样,只是@Component annotated classes和@ConfigurationProperties annotated classes不会自动检测,并且用户定义的bean会显式导入(请参见@Import)。
7. Running Your Application
7.1. Running from an IDE
如果偶然间运行了web应用两次,会出现 “Port already in use” 的错误,选择 此时应选择 rerun 而不是 run,来保证已经运行 的实例先被关闭
7.2. Running as a Packaged Application
如果使用spring boot 的maven插件 生成了一个可执行的jar,可以使用java -jar命令 运行应用
$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar
注:打开cmd,进入对应的目录,执行命令
$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar
即可
也可以通过debug的方式启动应用
$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
-jar target/myapplication-0.0.1-SNAPSHOT.jar
7.3. Using the Maven Plugin
SpringBoot maven 插件也含有一个run命令,可以快速的运行应用,$ mvn spring-boot:run
可以通过maven选项控制系统的环境变量
$ export MAVEN_OPTS=-Xmx1024m
7.4. Using the Gradle Plugin
7.5. Hot Swapping(热插拔)
JVM热插拔,在某种程度上受到字节码的限制,spring-boot-devtools也提供了快速重启应用的支持
详情查阅 Hot swapping “How-to”
8. Developer Tools
引入的方式
Maven
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
Gradle
configurations {
developmentOnly
runtimeClasspath {
extendsFrom developmentOnly
}
}
dependencies {
developmentOnly("org.springframework.boot:spring-boot-devtools")
}
NOTE:
打包好的应用默认是禁止这个 Developer tools 的,或者是以 java -jar 形式启动的应用,会默认是生产环境的应用,禁止这个Developer tools ,如果有必要使用Developer tools ,需要配置 -Dspring.devtools.restart.enabled=false
如果想使用远程的 devtools,需要禁用 excludeDevtools
8.1. Property Defaults
一些springboot支持的库使用缓存来改善性能,例如 模板引擎缓存通过编译模板来避免重复的编译模板文件,SpringMVC 可以添加HTTP缓存头文件,来快速的响应服务器请求的一些静态资源。
虽然缓存在生产环境的益处很大,但是在开发的时候会有适得其反的作用,会导致看不到最新的修改的东西,所以,spring-boot-devtools默认禁止了缓存
缓存选项的设置通常是在 application.properties文件中的,例如,Thymeleaf 提供的 spring.thymeleaf.cache 参数。spring-boot-devtools 在开发期间智能的应用了这些参数
因为开发Spring MVC and Spring WebFlux 应用的时候需要更多的web request 信息,需要为web logging group开启DEBUG 日志,可以看到关于请求的更多的信息,如:处理请求的 handler,response。如果需要看到更过的细节,可以配置
spring.http.log-request-details 这个配置
TIP:如果不行使用 上面的配置,可以选择 在application.properties配置 spring.devtools.add-properties 为 false
查看devtools 已经应用的参数列表 DevToolsPropertyDefaultsPostProcessor.
8.2. Automatic Restart
使用了spring-boot-devtools 之后,当classpath下面的文件发生改变时,应用就好自动的重启,这是一个很有用的特性,它提供了快速的针对于代码改变的反馈,默认情况下,static 和templates 的改变,不会重启。
触发重启
因为devtools 镜像了classpath下的资源,所以触发重启的唯一方式就是改变classpath下面的文件,在idea中,编译项目就可以触发
TIP:开发工具重启依赖于 关闭的钩子(the shutdown hook),如果禁用了 shutdown hook,重启就不会正确的启动 (SpringApplication.setRegisterShutdownHook(false)
当判断是否触发重启的时候,devtools会忽略名称是以下项目的变化: spring-boot, spring-boot-devtools, spring-boot-autoconfigure, spring-boot-actuator, and spring-boot-starter.
DevTools需要自定义ApplicationContext使用的ResourceLoader。如果您的应用程序已经提供了一个,它将被包装。不支持直接重写ApplicationContext上的getResource方法。
Restart vs Reload
重新启动用到了SpringBoot的两个类加载器,没有变化的类,(例如一些第三方的jar)会被加载到 一个基本加载器( base classloader)中,改变的类会被加载到 重启加载器( the restart classloade)中,重启加载器会被抛弃,并产生一个新的。这个方式表明应用重启会比冷启动(cold starts”)快,因为基本的类加载器没有变化,是可用,可迁移的
当重启没有那么快时,可以使用别的重新加载的技术 如 JRebel ,它是通过重新覆盖 类来实现的,这样更容易控制
8.2.1. Logging changes in condition evaluation
每次重启的时候,都会产生一个记录当前环境的评估报告,显示关于应用的 变化,如自动配置的变化,加载的bean 的变化,配置的参数的变化
禁用的方式:spring.devtools.restart.log-condition-evaluation-delta=false
8.2.2. Excluding Resources
指定某些资源变化的时候,不触发重启,例如:Thymeleaf templates。默认情况下:/META-INF/maven, /META-INF/resources, /resources, /static, /public, or /templates 下面的资源的变化不会触发重启,但是会触发实时重新加载( live reload)如果需要自定义这些位置,可以使用 spring.devtools.restart.exclude 参数。例如:只排除 /static and /public
spring.devtools.restart.exclude=static/,public/
如果需要保持默认的设置,添加额外的设置,使用 spring.devtools.restart.additional-exclude
8.2.3. Watching Additional Paths
如果需要不在classpath 下面的文件的变化也触发 重启,使用 spring.devtools.restart.additional-paths 来指定检测额外的路径。 可以使用 spring.devtools.restart.exclude 参数 额外路径下的触发的是 一个完全的重启还是一个 live reload
8.2.4. Disabling Restart
如果不想使用重启的特性,可以使用 spring.devtools.restart.enabled 属性来禁用,通常这一项可以在application.properties 里面配置(这样配置仍然会初始化重启的加载器,但是不会检测变化,也就无法重启)
如果需要完全的禁用重启(例如,和某个具体的库不兼容),可以设置 spring.devtools.restart.enabled System 值为false 在调用 SpringApplication.run(…) 之前,示例如下
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApp.class, args);
}
8.2.5. Using a Trigger File
如果IDE 一直在编译 变化的文件,可以使用 trigger filer ,只有这个文件改变的时候,才会触发重启
TIP:那个指定的文件的任何变化都会触发重启,但是重启只会发生在 devtools 确实检测到了变化的时候。
为了使用一个触发文件,需要设置 spring.devtools.restart.trigger-file 来指定文件的路径,这个文件必须要在classpath下面
示例的文件结构
src
± main
± resources
± .reloadtrigger
按照上面的文件结构,对应的配置是
spring.devtools.restart.trigger-file=.reloadtrigger
配置之后,只有在 src/main/resources/.reloadtrigger 文件变化的时候才会重启
可以指定spring.devtools.restart.trigger-file 是一个全局的文件,这样所有的项目就会同步的变化
8.2.6. Customizing the Restart Classloader
自定义重启的类加载器
默认情况下,每一个project 都会带有一个 重启加载器,通常的一些jar文件会用 基本的加载器加载,但是如果是多 module ( multi-module)的项目,不是每一个 module都被加载到项目中,此时需要一些自定义配置。一般来说:创建一个META-INF/spring-devtools.properties 文件
这个文件包含一些 前缀是 restart.exclude and restart.include 的配置。include 元素就是需要装进 重启加载器的项,exclude 是需要装进基本加载器的,属性的值是指定classpath的正则表达式:
restart.exclude.companycommonlibs=/mycorp-common-[\w\d-.]+.jar
restart.include.projectcommon=/mycorp-myproj-[\w\d-.]+.jar
每一个restart.include. or restart.exclude 开头的属性的键必须是唯一的
8.2.7. Known Limitations
重启这个特性和 ObjectInputStream 结合的不好,如果需要知道冲突的详情,需要使用 ConfigurableObjectInputStream和Thread.currentThread().getContextClassLoader().联合查看,一些第三方的库没有考虑这个情况,需要联系这个第三方库的作者
8.3. LiveReload
spring-boot-devtools 模块包含一个嵌入的 LiveReload server,在资源发生改变的时候可以触发浏览器的刷新,支持 Chrome, Firefox and Safari
如果不想启动这个 LiveReload server 可以使用配置 spring.devtools.livereload.enabled为 false
一次只能启动一个 LiveReload server,如果启动了多个应用,只有第一个应用会有 LiveReload server
8.4. Global Settings
如果需要配置 devtools 的全局参数
可以在 $HOME/.config/spring-boot 路径下使用下面的三种中的一个文件进行配置
spring-boot-devtools.properties
spring-boot-devtools.yaml
spring-boot-devtools.yml
例如,为了配置重启的触发文件 可以在对应的文件添加如下配置
文件路径:
~/.config/spring-boot/spring-boot-devtools.properties
配置项
spring.devtools.restart.trigger-file=.reloadtrigger
8.5. Remote Applications
在开发远程应用的时候,需要确定网络环境是安全的,否则不可以使用 devtools的远程支持
在重新打包的时候需要有下面的配置
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>false</excludeDevtools>
</configuration>
</plugin>
</plugins>
</build>
还需要设置 spring.devtools.remote.secret 这个参数