本章节对应SpringBoot官方学习文档v3.2.1中第六和第十六章
如果你刚开始学习SpringBoot,建议先阅读SpringBoot新手入门-概述、安装及简单使用。
使用SpringBoot进行开发
1 构建系统
SpringBoot的每个版本都与Spring Framework的版本相关联,强烈建议不要指定其版本。
1.1 SpringBoot Maven插件
参考文档,API
相关文档中文翻译请参见SpringBoot专栏中第二部分《SpringBoot插件官网文档学习-v3.2.1》
1.2 启动器
启动器是一组方便的依赖标签,您可以将其包含在应用程序中。启动器包含许多依赖项,这些依赖项是您快速启动和运行项目所需的,并且具有一组一致的、受支持的托管可传递依赖项。
您可以获得所需的所有Spring和相关技术的一站式商店,而无需搜索样本代码和复制粘贴依赖标签,即SpringBoot提供了各种场景下的pom文件依赖,引入其中的一个启动器依赖就可以将该场景下用到的SpringBoot相关的依赖全部引入。例如,如果想使用Spring和JPA进行数据库访问,在项目中包含Spring-boot-starter-data-jpa依赖项即可,无需考虑其内部集成的Spring Data JPA,Spring Data Commons和Hibernate等技术。
所有官方启动器都遵循类似的命名模式;spring-boot-starter-,其中是一种特定类型的应用程序。此命名结构旨在帮助您在需要查找启动器时提供帮助。许多IDE中的Maven集成允许您按名称搜索依赖项。例如,安装了适当的Eclipse或SpringTools插件后,可以在POM编辑器中按ctrl空格键,然后键入“Spring-boot-starter”以获得完整的列表。
第三方启动程序通常以项目名称开头。例如,一个名为thirdpartyproject的第三方启动程序项目通常会被命名为thirdartyproject-spring-boot-starter。
以下应用程序启动器由Spring Boot在org.springframework.Boot组下提供:
表1 Spring Boot应用程序启动器
序号 | 名称 | 描述 |
---|---|---|
1 | spring-boot-starter | 核心启动器,包括自动配置支持、日志记录和YAML |
2 | spring-boot-starter-activemq | 使用Apache ActiveMQ的JMS消息传递的启动器 |
3 | spring-boot-starter-amqp | Spring AMQP和Rabbit MQ的启动器 |
4 | spring-boot-starter-aop | 使用Spring AOP和AspectJ进行面向方面编程的启动器 |
5 | spring-boot-starter-artemis | 使用Apache Artemis的JMS消息传递的启动器 |
6 | spring-boot-starter-batch | 使用Spring Batch的启动器 |
7 | spring-boot-starter-cache | 使用Spring Framework缓存支持的启动器 |
8 | spring-boot-starter-data-cassandra | 使用Cassandra分布式数据库和Spring Data Cassandra的启动器 |
9 | spring-boot-starter-data-cassandra-reactive | 使用Cassandra分布式数据库和Spring Data Cassandra Reactive的启动器 |
10 | spring-boot-starter-data-couchbase | 使用Couchbase面向文档数据库和Spring Data Couchbase的启动器 |
11 | spring-boot-starter-data-couchbase-reactive | 使用Couchbase面向文档的数据库和Spring Data Couchbase Reactive的启动器 |
12 | spring-boot-starter-data-elasticsearch | 使用Elasticsearch搜索和分析引擎以及Spring Data Elasticsearch的启动器 |
13 | spring-boot-starter-data-jdbc | 使用Spring Data JDBC的启动器 |
14 | spring-boot-starter-data-jpa | 将Spring Data JPA与Hibernate结合使用的启动器 |
15 | spring-boot-starter-data-ldap | 使用Spring Data LDAP的启动器 |
16 | spring-boot-starter-data-mongodb | 使用面向MongoDB文档的数据库和Spring Data MongoDB的启动器 |
17 | spring-boot-starter-data-mongodb-reactive | 使用面向MongoDB文档的数据库和Spring Data MongoDB Reactive的启动器 |
18 | spring-boot-starter-data-neo4j | 使用Neo4j图形数据库和Spring Data Neo4j的启动器 |
19 | spring-boot-starter-data-r2dbc | 使用Spring Data R2DBC的启动器 |
20 | spring-boot-starter-data-redis | 将Redis键值数据存储与Spring data Redis和Lettuce客户端一起使用的启动器 |
21 | spring-boot-starter-data-redis-reactive | 将Redis键值数据存储与Spring data Redis reactive和Lettuce客户端一起使用的启动器 |
22 | spring-boot-starter-data-rest | 使用Spring Data REST和Spring MVC通过REST公开Spring Data存储库的启动器 |
23 | spring-boot-starter-freemarker | 使用FreeMarker视图构建MVC web应用程序的启动器 |
24 | spring-boot-starter-graphql | 使用Spring GraphQL构建GraphQL应用程序的启动器 |
25 | spring-boot-starter-groovy-templates | 使用Groovy模板视图构建MVC web应用程序的启动器 |
26 | spring-boot-starter-hateoas | 使用Spring MVC和Spring HATEOS构建基于超媒体的RESTful web应用程序的启动器 |
27 | spring-boot-starter-integration | 使用Spring Integration的启动器 |
28 | spring-boot-starter-jdbc | 将JDBC与HikariCP连接池一起使用的启动器 |
29 | spring-boot-starter-jersey | 使用JAX-RS和Jersey构建RESTful web应用程序的启动器,spring-boot-starter-web的另一选择 |
30 | spring-boot-starter-jooq | 使用jOOQ通过JDBC访问SQL数据库的启动器, spring-bootstarter-data-jpa 和 spring-boot-starter-jdbc 另一选择 |
31 | spring-boot-starter-json | json读写相关的启动器 |
32 | spring-boot-starter-mail | 使用Java Mail和Spring Framework的电子邮件发送支持的启动器 |
33 | spring-boot-starter-mustache | 使用Mustache视图构建web应用程序的启动器 |
34 | spring-boot-starter-oauth2-authorizationserver | 使用Spring Authorization Server功能的启动器 |
35 | spring-boot-starter-oauth2-client | 使用Spring Security的OAuth2/OpenID Connect客户端功能的启动器 |
36 | spring-boot-starter-oauth2-resource-server | 使用Spring Security的OAuth2资源服务器功能的启动器 |
37 | spring-boot-starter-pulsar | 使用Apache Pulsar Spring的启动器 |
38 | spring-boot-starter-pulsar-reactive | 使用Apache Pulsar Reactive Spring的启动器 |
39 | spring-boot-starter-quartz | 使用Quartz调度器的启动器 |
40 | spring-boot-starter-rsocket | 用于构建RSocket客户端和服务器的启动器 |
41 | spring-boot-starter-security | 使用Spring Security的启动器 |
42 | spring-boot-starter-test | 使用JUnit Jupiter、Hamcrest和Mockito等库测试Spring Boot应用程序的启动器 |
43 | spring-boot-starter-thymeleaf | 使用Thymelaf视图构建MVC web应用程序的启动器 |
44 | spring-boot-starter-validation | 使用Hibernate Validator进行JavaBean验证的启动器 |
45 | spring-boot-starter-web | 使用Spring MVC构建web(包括RESTful)应用程序的启动器,使用Tomcat作为默认的嵌入式容器 |
46 | spring-boot-starter-web-services | 使用Spring Web Services的启动器 |
47 | spring-boot-starter-webflux | 使用Spring Framework的Reactive Web支持构建WebFlux应用程序的启动器 |
48 | spring-boot-starter-websocket | 使用Spring Framework的MVC WebSocket支持构建WebSocket应用程序的启动器 |
除了应用程序启动器之外,还可以使用以下启动器来使用生产相关特性:
表2 Spring Boot生产启动器
序号 | 名称 | 描述 |
---|---|---|
1 | spring-boot-starter-actuator | 使用Spring Boot的Actuator的启动器,该启动器提供可用于生产的功能,帮助您监控和管理应用程序 |
最后,Spring Boot还包括以下启动器,如果您想排除或交换特定的技术方面,可以使用这些启动器: |
表3 Spring Boot技术启动器
序号 | 名称 | 描述 |
---|---|---|
1 | spring-boot-starter-jetty | 使用Jetty作为嵌入式servlet容器的启动器, spring-bootstarter-tomcat启动器的替代选择 |
2 | spring-boot-starter-log4j2 | 使用Log4j2进行日志记录的启动器,spring-boot-starter-logging的替代选择 |
3 | spring-boot-starter-logging | 使用Logback进行日志记录的启动器。默认日志记录启动器 |
4 | spring-boot-starter-reactor-netty | 使用Reactor Netty作为嵌入相应式HTTP服务器的启动器 |
5 | spring-boot-starter-tomcat | 使用Tomcat作为嵌入式servlet容器的启动器。spring-boot-starter-web使用的默认servlet容器启动器 |
6 | spring-boot-starter-undertow | 使用Undertow作为嵌入式servlet容器的启动器, spring-bootstarter-tomcat的替代选择 |
2 最佳实践
2.1 代码结构
Spring Boot不需要任何特定的代码布局即可工作。然而,也有一些最佳实践可以提供帮助。
如果您希望实施基于域的结构,请查看Spring Modulith,相关文档中文翻译请参见SpringBoot专栏中第四部分《Spring Modulith官网文档学习-v1.1.0》。
2.1.1 包声明建议
当一个类不包括包声明时,它被认为在“默认包”中。
通常不鼓励使用“默认包”,应避免使用。它可能会给使用@ComponentScan、@ConfigurationPropertiesScan、@EntityScan或@SpringBootApplication注释的Spring Boot应用程序带来特殊问题,因为每个jar中的每个类都被读取。
建议遵循推荐的包命名规则:使用域名倒序作为包名(例如com.example.project)。
2.1.2 启动类位置建议
通常建议将主应用程序类定位在其他类之上的根包中。@SpringBootApplication注释通常放在主类上,它隐式地为某些项定义了一个基本的“搜索包”。例如,如果您正在编写JPA应用程序,那么@SpringBootApplication注释类的包将用于搜索@Entity项。使用根包还允许组件扫描仅应用于您的项目
注:如果不想使用@SpringBootApplication注解,可以使用@EnableAutoConfiguration和@ComponentScan注解代替。
以下列表显示了一个典型的布局:
com
+- example
+- myapplication
+- MyApplication.java
|
+- customer
| +- Customer.java
| +- CustomerController.java
| +- CustomerService.java
| +- CustomerRepository.java
|
+- order
+- Order.java
+- OrderController.java
+- OrderService.java
+- OrderRepository.java
MyApplication.java文件将声明主方法以及基本的@SpringBootApplication,如下所示:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
2.2 配置类
Spring Boot支持基于Java的配置。尽管可以将SpringApplication与XML源代码一起使用,但我们通常建议您的主要源代码是单个@Configuration类。
通常,定义主方法的类是主要@Configuration的使用方法。
互联网上已经发布了许多使用XML配置的Spring配置示例。如果可能,请始终尝试使用等效的基于Java的配置。搜索Enable*注释是一个很好的起点。
2.2.1 导入其他配置类
您不需要将所有的@Configuration都放在一个类中。@Import注解可用于导入其他配置类。或者可以使用@ComponentScan自动抓取所有Spring组件,包括@Configuration类。
2.2.2 导入XML配置
如果您必须使用基于XML的配置,我们建议您仍然从@configuration类开始。然后,您可以使用@ImportResource注解来加载XML配置文件。
2.3 自动配置
Spring Boot自动配置尝试根据您添加的jar依赖项自动配置您的Spring应用程序。例如,如果HSQLDB在类路径上,并且您没有手动配置任何数据库连接bean,那么Spring Boot会自动配置内存中的数据库。
您需要通过将@EnableAutoConfiguration或@SpringBootApplication注解添加到您的一个@configuration类中来选择自动配置。
您应该只添加一个@SpringBootApplication或@EnableAutoConfiguration注解。我们通常建议您仅将其中一个添加到主@Configuration类中
2.3.1 逐渐更换自动配置
自动配置是非侵入性的。在任何时候,您都可以开始定义自己的配置,以替换自动配置的特定部分。例如,如果您添加了自己的DataSourcebean,则默认的嵌入式数据库支持会不生效。
如果您需要了解当前正在应用的自动配置以及原因,请使用–debug开关启动您的应用程序。这样做可以为选定的核心记录器启用调试日志,并将条件报告记录到控制台。
2.3.2 禁用特定的自动配置类
如果发现不希望应用的特定自动配置类,可以使用@SpringBootApplication的exclude属性禁用它们,如以下示例所示:
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MyApplication {
}
如果类不在类路径上,则可以使用注解的excludeName属性并指定完全限定的名称替代。如果您更喜欢使用@EnableAutoConfiguration而不是@SpringBootApplication,exclude和excludeName也是可以使用的。最后,您还可以使用spring.autoconfig.exclude属性来控制要排除的自动配置类的列表。
可以在注解层级或者使用属性来定义要排除的设置
尽管自动配置类是公共的,但该类被视为公共API的唯一方面是可用于禁用自动配置的类的名称。这些类的实际内容,如嵌套的配置类或bean方法,仅供内部使用,我们不建议直接使用这些内容。
2.3.3 自动配置包
自动配置包是各种自动配置功能在扫描实体和Spring数据存储库时默认查找的包。@EnableAutoConfiguration注解(直接或通过其在@SpringBootApplication上的存在)确定默认的自动配置包。可以使用@AutoConfigurationPackage注解配置其他包。
2.4 Spring Beans和依赖注入
您可以自由使用任何标准的Spring Framework技术来定义您的bean及其注入的依赖项。我们通常建议使用构造函数注入来连接依赖项,并使用@ComponentScan来查找bean。
如果您按照上面的建议构建代码(在顶部包中定位应用程序类),则可以添加不带任何参数的@ComponentScan,或者使用隐式包含它的@SpringBootApplication注解。所有应用程序组件(@Component、@Service、@Repository、@Controller等)都会自动注册为Spring Beans。
以下示例显示了一个@ServiceBean,它使用构造函数注入来获得所需的RiskAssessor bean:
import org.springframework.stereotype.Service;
@Service
public class MyAccountService implements AccountService {
private final RiskAssessor riskAssessor;
public MyAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
// ...
}
如果一个bean有多个构造函数,则需要标记希望Spring与@Autowired一起使用的构造函数:
import java.io.PrintStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyAccountService implements AccountService {
private final RiskAssessor riskAssessor;
private final PrintStream out;
@Autowired
public MyAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
this.out = System.out;
}
public MyAccountService(RiskAssessor riskAssessor, PrintStream out) {
this.riskAssessor = riskAssessor;
this.out = out;
}
// ...
}
请注意,使用构造函数注入可以将riskAssessor字段标记为final,这表明它随后无法更改。
2.5 使用@SpringBootApplication注解
许多Spring Boot开发人员喜欢他们的应用程序使用自动配置、组件扫描,并能够在他们的“应用程序类”上定义额外的配置。一个@SpringBootApplication注解可以用于启用这三个功能,即:
- @EnableAutoConfiguration:启用Spring Boot的自动配置机制
- @ComponentScan:在应用程序所在的包上启用@Component扫描(请参阅最佳实践)
- @SpringBootConfiguration:启用上下文中额外bean的注册或其他配置类的导入。Spring的标准@Configuration的替代方案,有助于集成测试中的配置检测。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// Same as @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
@SpringBootApplication还提供别名来自定义@EnableAutoConfiguration和@ComponentScan的属性。这些功能都不是强制性的,您可以选择用它所启用的任何功能来替换此单个注解。例如,您可能不想在应用程序中使用组件扫描或配置属性扫描:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Import;
@SpringBootConfiguration(proxyBeanMethods = false)
@EnableAutoConfiguration
@Import({ SomeConfiguration.class, AnotherConfiguration.class })
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
在本例中,MyApplication与任何其他Spring Boot应用程序一样,不同之处在于@Component和@ConfigurationProperties注解声明的类不会自动检测到,并且用户定义的bean会显式导入(请参见@Import)。
3 运行代码
将应用程序打为jar包并使用嵌入式HTTP服务器的最大优势之一是,您可以像运行其他应用程序一样运行应用程序。该示例适用于调试Spring Boot应用程序。您不需要任何特殊的IDE插件或扩展。
本节仅涵盖基于jar包的打包。如果您选择将应用程序打包为war文件,请参阅服务器和IDE文档。
3.1 在IDE上运行
您可以将Spring Boot应用程序作为Java应用程序从IDE中运行。但是,您首先需要导入您的项目。导入步骤因IDE和构建系统而异。大多数IDE可以直接导入Maven项目。例如,Eclipse用户可以选择Import…→ 文件菜单中的现有Maven项目。
如果不能直接将项目导入IDE,则可以使用构建插件生成IDE元数据。Maven包括Eclipse和IDEA的插件。
如果您不小心运行了两次web应用程序,您会看到一个“端口已在使用”错误。
Spring Tools用户可以使用“重新启动”按钮而不是“运行”按钮来确保关闭任何现有实例。
3.2 作为Jar包运行
如果您使用Spring Boot Maven插件来创建一个可执行的jar,那么您可以使用java-jar运行您的应用程序,如下例所示:
$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar
还可以运行启用了远程调试支持的打包应用程序。这样做可以将调试器附加到打包的应用程序,如以下示例所示
$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
-jar target/myapplication-0.0.1-SNAPSHOT.jar
3.3 使用SpringBoot Maven插件运行
Spring Boot Maven插件包含一个可用于快速编译和运行应用程序的运行目标。应用程序以分解形式运行,就像它们在IDE中一样。以下示例显示了运行Spring Boot应用程序的典型Maven命令:
$ mvn spring-boot:run
您可能还想使用MAVEN_OPTS操作系统环境变量,如以下示例所示:
$ export MAVEN_OPTS=-Xmx1024m
3.4 开发者工具
Spring Boot包括一组额外的工具,可以使应用程序开发体验更加愉快。spring-boot devtools模块可以包含在任何项目中,以提供额外的开发时功能。要包含devtools支持,请将模块依赖项添加到您的构建中,如以下Maven的列表所示:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
注意:
1、开发工具可能会导致类加载问题,尤其是在多模块项目中。下一小节《诊断类加载问题》解释了如何诊断和解决这些问题。
2、运行完全打包的应用程序时,开发人员工具会自动禁用。如果您的应用程序是从java-jar启动的,或者是从一个特殊的类加载器启动的,那么它就被视为“生产应用程序”。您可以使用spring.devtools.restart.enabled系统属性来控制这种行为。要启用devtools,不管用于启动应用程序的类加载器是什么,请设置-Dspring.devtools.restart.enabled=true系统属性。在运行devtools存在安全风险的生产环境中,决不能这样做。要禁用devtools,请排除依赖项或设置-Dspring.devtools.restart.enabled=false系统属性。
3、在Maven中将依赖项标记为可选(如上所示),可以防止devtools被转换应用到使用您的项目的其他模块。
4、默认情况下,重新打包的归档文件不包含devtools。如果你想使用某个远程开发工具功能,你需要包括它。当使用Maven插件时,将excludeDevtools属性设置为false。
3.4.1 类加载问题排除方法
如《重新启动与重新加载》部分所述,重新启动功能是通过使用两个类加载器来实现的。对于大多数应用程序,这种方法效果良好。然而,它有时会导致类加载问题,尤其是在多模块项目中。
要诊断类加载问题是否确实是由devtools及其两个类加载程序引起的,请尝试禁用重新启动。如果这解决了您的问题,请自定义重新启动类加载器以包括整个项目。
3.4.2 属性默认值
Spring Boot支持的几个库使用缓存来提高性能。例如,模板引擎缓存已编译的模板,以避免重复解析模板文件。此外,SpringMVC可以在提供静态资源时向响应添加HTTP缓存头。
虽然缓存在生产中非常有益,但在开发过程中可能会适得其反,使您无法看到刚刚在应用程序中所做的更改。因此,springboot-devtools默认情况下会禁用缓存选项。
缓存选项通常由application.properties文件中的设置进行配置。例如,Thymeleaf提供spring.Thymeleaf.cache属性。spring-boot-devtools模块不需要手动设置这些属性,而是自动应用合理的开发时配置。
下表列出了所有应用的特性:
序号 | 名称 | 默认值 |
---|---|---|
1 | server.error.include-binding-errors | always |
2 | server.error.include-message | always |
3 | server.error.include-stacktrace | always |
4 | server.servlet.jsp.init-parameters.development | true |
5 | server.servlet.session.persistent | true |
6 | spring.docker.compose.readiness.wait | only-if-started |
7 | spring.freemarker.cache | false |
8 | spring.graphql.graphiql.enabled | true |
9 | spring.groovy.template.cache | false |
10 | spring.h2.console.enabled | true |
11 | spring.mustache.servlet.cache | false |
12 | spring.mvc.log-resolved-exception | true |
13 | spring.reactor.netty.shutdown-quiet-period | 0s |
14 | spring.template.provider.cache | false |
15 | spring.thymeleaf.cache | false |
16 | spring.web.resources.cache.period | 0 |
17 | spring.web.resources.chain.cache | false |
如果不希望应用属性默认值,可以在application.properties中将spring.devtools.addproperties设置为false。
因为在开发SpringMVC和SpringWebFlux应用程序时需要更多关于web请求的信息,所以开发人员工具建议您为web日志记录组启用DEBUG日志记录。这将为您提供有关传入请求、处理该请求的处理程序、响应结果和其他详细信息。如果您希望记录所有请求详细信息(包括潜在的敏感信息),可以打开spring.mvc.log-request-details或spring.codec.lograquest-detail配置属性。
3.4.3 自动重新启动
每当类路径上的文件发生更改时,使用spring boot devtools的应用程序就会自动重新启动。当在IDE中工作时,这可能是一个有用的功能,因为它为代码更改提供了一个非常快速的反馈循环。默认情况下,类路径上指向某个目录的任何条目都会被监视是否有更改。请注意,某些资源(如静态资产和视图模板)不需要重新启动应用程序。
3.4.3.1 触发重新启动
由于DevTools监视类路径资源,触发重新启动的唯一方法是更新类路径。无论您使用的是IDE还是某个构建插件,修改后的文件都必须重新编译才能触发重新启动。更新类路径的方式取决于所使用的工具:
- 在Eclipse中,保存修改后的文件会导致类路径更新并触发重新启动。
- 在IntelliJ IDEA中,构建项目(构建+→+ Build Project)具有相同的效果。
- 如果使用构建插件,运行mvn compile for Maven将触发重新启动
z注意:
1、如果您使用构建插件重新启动Maven,则必须将分叉集保留为启用状态。如果禁用forking,将不会创建devtools使用的独立应用程序类加载器,并且重新启动将无法正常运行。
2、与LiveReload一起使用时,自动重新启动效果非常好。有关详细信息,请参阅LiveReload部分。如果使用JRebel,则会禁用自动重新启动,以支持动态类重新加载。其他开发工具功能(如LiveReload和属性重写)仍然可以使用。
3、DevTools依赖于应用程序上下文的关闭挂钩来在重新启动时关闭它。如果您禁用了关闭挂钩(SpringApplication.setRegisterShutdownHook(false)),它将无法正常工作。
4、DevTools需要自定义ApplicationContext使用的ResourceLoader。如果您的应用程序已经提供了一个,那么它将被打包。不支持直接重写ApplicationContext上的getResource方法。
5、使用AspectJ编织时不支持自动重新启动。
3.4.3.2 重新启动与重新加载
Spring Boot提供的重启技术通过使用两个类加载器来工作。不变的类(例如,来自第三方jar的类)被加载到基类加载程序中。您正在积极开发的类被加载到重新启动类加载程序中。当应用程序重新启动时,重新启动的类加载器将被丢弃,并创建一个新的类加载器。这种方法意味着应用程序重新启动通常比“冷启动”快得多,因为基类加载器已经可用并已填充。
如果您发现应用程序的重新启动速度不够快,或者遇到类加载问题,可以考虑重新加载ZeroTurnaround的JRebel等技术。这些工作原理是在加载类时重写类,使其更易于重新加载。
3.4.3.3 条件评价中的日志变化
默认情况下,每次应用程序重新启动时,都会记录一个显示条件评估增量的报告。该报告显示在您进行更改(如添加或删除bean以及设置配置属性)时对应用程序的自动配置所做的更改
要禁用报告的日志记录,请设置以下属性:
properties
spring.devtools.restart.log-condition-evaluation-delta=false
yaml
spring:
devtools:
restart:
log-condition-evaluation-delta: false
3.4.3.4 排除资源
某些资源在更改时不一定需要触发重新启动。例如,Thymeleaf 模板可以就地编辑。默认情况下,更改/META-INF/maven、/META-IINF/resources、/resources和/static、/public或/templates中的资源不会触发重新启动,但会触发实时重新加载。如果要自定义这些排除项,可以使用spring.devtools.restart.exclude属性。例如,要仅排除/static和/public,您需要设置以下属性:
properties
spring.devtools.restart.exclude=static/**,public/**
yaml
spring:
devtools:
restart:
exclude: "static/**,public/**"
如果要保留这些默认值并添加其他排除项,请改用spring.devtools.restart.additional-exclude属性。
3.4.3.5 监视其他路径
当您对类路径之外的文件进行更改时,您可能希望重新启动或重新加载应用程序。为此,请使用spring.devtools.restart.additional-paths属性配置其他路径以监视更改。您可以使用前面描述的spring.devtools.restart.exclude属性来控制附加路径下的更改是触发完全重新启动还是实时重新加载。
3.4.3.6 禁用重新启动
如果不想使用重新启动功能,可以使用spring.devtools.restart.enabled属性禁用它。在大多数情况下,您可以在application.properties中设置此属性(这样做仍然会初始化重新启动类加载器,但它不会监视文件更改)。
如果您需要完全禁用重新启动支持(例如,因为它不适用于特定的库),则需要在调用SpringApplication.run(…)之前将spring.devtools.restart.enabled System属性设置为false,如下例所示:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApplication.class, args);
}
}
3.4.3.7 使用触发器文件
如果您使用的IDE连续编译更改的文件,您可能更喜欢只在特定时间触发重新启动。为此,您可以使用“触发器文件”,这是一个特殊的文件,当您想要实际触发重新启动检查时,必须对其进行修改。
对文件的任何更新都会触发检查,但只有当Devtools检测到有事情要做时,才会真正重新启动。
要使用触发器文件,请将spring.devtools.restart.trigger-file属性设置为触发器文件的名称(不包括任何路径)。触发器文件必须出现在类路径的某个位置。
例如,如果您有一个具有以下结构的项目:
src
+- main
+- resources
+- .reloadtrigger
那么您的触发器文件属性将是:
properties
spring.devtools.restart.trigger-file=.reloadtrigger
yaml
spring:
devtools:
restart:
trigger-file: ".reloadtrigger"
现在,只有当src/main/resources/.reloadtrigger更新时,才会重新启动。
您可能希望将spring.devtools.restart.trigger-file设置为全局设置,以便所有项目都以相同的方式运行
有些IDE具有一些功能,可以使您不需要手动更新触发器文件。Spring Tools for Eclipse和IntelliJ IDEA(Ultimate Edition)都有这样的支持。使用Spring Tools,您可以从控制台视图中使用“reload”按钮(只要您的触发器文件名为.reloadtrigger)。对于IntelliJ IDEA,您可以按照其文档中的说明进行操作。
3.4.3.8 自定义重启类加载器
如前面《重新启动与重新加载》部分所述,重新启动功能是通过使用两个类加载器来实现的。如果这会导致问题,您可能需要自定义由哪个类加载器加载的内容。
默认情况下,IDE中任何打开的项目都使用“重新启动”类加载器加载,任何常规.jar文件都使用“基本”类加载器来加载。如果您使用mvn-spring-boot:run情况也是如此:包含@SpringBootApplication的项目使用“restart”类加载器加载,其他所有内容都使用“base”类加载器。
您可以通过创建META-INF/Spring-devtools.properties文件,指示Spring Boot使用不同的类加载器加载项目的部分内容。spring-devtools.properties文件可以包含以restart.exclude和restart.include为前缀的属性。include元素是应上送到“restart”类加载器中的项,exclude元素是应该下送到“base”类加载器的项。该属性的值是应用于类路径的正则表达式,如以下示例所示:
properties
restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\\.]+\\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\\.]+\\.jar
yaml
restart:
exclude:
companycommonlibs: "/mycorp-common-[\\w\\d-\\.]+\\.jar"
include:
projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
注意:
1、所有属性键都必须是唯一的。只要一个属性以restart.include开头,或restart.exclude。这需要思考。
2、将加载类路径中的所有META-INF/spring-devtools.properties。您可以将文件打包到项目中,也可以打包到项目使用的库中。
3.4.3.9 已知限制
对于使用标准ObjectInputStream反序列化的对象,重新启动功能不能很好地工作。如果需要反序列化数据,则可能需要将Spring的ConfigurationObjectInputStream与Thread.currentThread().getContextClassLoader()结合使用。
另外,一些第三方库在不考虑上下文类加载器的情况下进行反序列化。
3.4.4 即时刷新——LiveReload
spring-boot devtools模块包括一个嵌入式LiveReload服务器,可用于在资源更改时触发浏览器刷新。LiveReload浏览器扩展可免费用于Chrome、Firefox和Safari。您可以通过在所选浏览器的市场或商店中搜索“LiveReload”来找到这些扩展。
如果您不想在应用程序运行时启动LiveReload服务器,可以将spring.devtools.LiveReload.enabled属性设置为false。
1、一次只能运行一台LiveReload服务器。在启动应用程序之前,请确保没有其他LiveReload服务器正在运行。如果您从IDE启动多个应用程序,则只有第一个应用程序支持LiveReload。
2、若要在文件更改时触发LiveReload,必须启用“自动重新启动”。
3.4.5 全局设置
您可以通过将以下任何文件添加到$HOME/.config/spring引导目录来配置全局devtools设置:
- spring-boot-devtools.properties
- spring-boot-devtools.yaml
- spring-boot-devtools.yml
添加到这些文件中的任何属性都适用于您机器上使用devtools的所有Spring Boot应用程序。例如,要将重新启动配置为始终使用触发器文件,您需要将以下属性添加到spring boot devtools文件中:
properties
spring.devtools.restart.trigger-file=.reloadtrigger
yaml
spring:
devtools:
restart:
trigger-file: ".reloadtrigger"
默认情况下,$HOME是用户的主目录。若要自定义此位置,请设置SPRING_DEVTOOLS_HOME环境变量或SPRING.DEVTOOLS.HOME系统属性。
1、如果在$HOME/.config/spring-boot中找不到devtools配置文件,则会在$HOME目录的根目录中搜索.spring-bootdevtools.properties文件。这允许您与不支持$HOME/.config/Spring-Boot位置的旧版本Spring Boot上的应用程序共享devtools全局配置。
2、devtools属性或yaml文件中不支持配置文件。
3、在.spring-boot-devtools.properties中激活的任何配置文件都不会影响特定配置文件的加载。不支持YAML和properties文件中的配置文件特定文件名(形式为spring-boot-devtools-<Profile>.properties)和spring.config.activate.on-Profile文档。
3.4.6 配置文件系统监视程序
FileSystemWatcher的工作方式是以一定的时间间隔轮询类更改,然后等待预定义的静默期以确保不再有更改。由于Spring Boot完全依赖IDE来编译文件并将其复制到Spring Boot可以读取文件的位置,因此您可能会发现,当devtools重新启动应用程序时,有时某些更改不会得到反映。如果您经常观察到此类问题,请尝试将spring.devtools.restart.poll-interval和spring.devtools.restart.quiet-period参数增加到适合您的开发环境的值:
properties
spring.devtools.restart.poll-interval=2s
spring.devtools.restart.quiet-period=1s
yaml
spring:
devtools:
restart:
poll-interval: "2s"
quiet-period: "1s"
现在,监视的类路径目录每2秒轮询一次以获取更改,并保持1秒的静默期以确保没有其他类更改。
3.4.7 远程应用程序
Spring Boot开发工具并不局限于本地开发。远程运行应用程序时,还可以使用几个功能。远程支持是选择加入的,因为启用它可能会带来安全风险。仅当在受信任的网络上运行或使用SSL进行安全保护时才应启用它。如果这两个选项都不可用,则不应使用DevTools的远程支持。您永远不应该在生产部署上启用支持。
要启用它,您需要确保重新打包的归档文件中包括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属性。像任何重要的密码或秘密一样,该值应该是唯一的和强的,这样就不会被猜测或暴力强制。
远程开发工具支持分为两部分:一个是接受连接的服务器端端点,另一个是在IDE中运行的客户端应用程序。当设置spring.devtools.remote.secret属性时,服务器组件将自动启用。客户端组件必须手动启动。
Spring WebFlux应用程序不支持远程开发工具。
3.4.7.1 运行远程客户端应用程序
远程客户端应用程序设计为从IDE中运行。您需要使用与所连接的远程项目相同的类路径来运行org.springframework.boot.devtools.RemoteSpringApplication。该应用程序的唯一必需参数是它所连接到的远程URL。
例如,如果您正在使用Eclipse或Spring Tools,并且您有一个名为my-app的项目已部署到云端,您将执行以下操作:
- 从Run菜单中选择Run Configurations。
- 创建一个新的Java应用程序“启动配置”。
- 浏览我的应用程序项目。
- 使用org.springframework.boot.devtools.RemoteSpringApplication作为主类。
- 添加https://myapp.cfapps.io到程序参数(或任何远程URL)。
正在运行的远程客户端可能类似于以下列表:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/
:: Spring Boot Remote :: (v3.2.1)
2023-12-21T12:10:15.411Z INFO 35951 --- [ main]
o.s.b.devtools.RemoteSpringApplication : Starting RemoteSpringApplication v3.2.1
using Java 17.0.9 with PID 35951
(/Users/myuser/.m2/repository/org/springframework/boot/spring-bootdevtools/3.2.1/spring-boot-devtools-3.2.1.jar started by myuser in /opt/apps/)
2023-12-21T12:10:15.416Z INFO 35951 --- [ main]
o.s.b.devtools.RemoteSpringApplication : No active profile set, falling back to 1
default profile: "default"
2023-12-21T12:10:15.758Z INFO 35951 --- [ main]
o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2023-12-21T12:10:15.795Z INFO 35951 --- [ main]
o.s.b.devtools.RemoteSpringApplication : Started RemoteSpringApplication in 0.809
seconds (process running for 1.188)
1、因为远程客户端使用与实际应用程序相同的类路径,所以它可以直接读取应用程序属性。这就是读取spring.devtools.remote.secret属性并将其传递给服务器进行身份验证的方式。
2、建议始终使用https://作为连接协议,以便对流量进行加密,并且不会截获密码。
3、如果需要使用代理访问远程应用程序,请配置spring.devtools.remote.proxy.host和spring.devtools.remote.proxy.port属性。
3.4.7.2 远程更新
远程客户端以与本地重新启动相同的方式监视应用程序类路径的更改。任何更新的资源都会被推送到远程应用程序,并(如果需要)触发重新启动。如果您迭代使用本地没有的云服务的功能,这会很有帮助。一般来说,远程更新和重新启动要比完整的重建和部署周期快得多。
在较慢的开发环境中,可能会出现安静期不够的情况,并且类中的更改可能会被拆分为批处理。上传第一批类更改后,服务器将重新启动。由于服务器正在重新启动,下一批无法发送到应用程序。
这通常表现为RemoteSpringApplication日志中关于无法上传某些类的警告,以及随后的重试。但这也可能导致应用程序代码不一致,以及在上传第一批更改后无法重新启动。如果您经常观察到此类问题,请尝试将spring.devtools.restart.poll-interval和spring.devtools.restart.quiet-period参数增加到适合您的开发环境的值。有关配置这些属性的信息,请参阅配置文件系统监视程序部分。
只有当远程客户端正在运行时,才会监视文件。如果在启动远程客户端之前更改了文件,则不会将其推送到远程服务器。
4 打包
可执行jar可用于生产部署。由于它们是自包含的,因此也非常适合基于云的部署。
对于其他生产相关功能,如健康、审计和度量REST或JMX端点,可以考虑添加 spring-boot-actuator。有关详细信息,请参阅生产环境特性章节。
5 命令行工具
Spring Boot CLI是一个命令行工具,可用于从start.Spring.io引导新项目或编码密码。
5.1 安装CLI
Spring Boot CLI(命令行界面)可以使用SDKMAN手动安装!(SDK Manager),有关全面的安装说明,请参阅《SpringBoot新手入门-概述、安装及简单使用》部分中的Spring Boot安装部分。
5.2 使用CLI
安装CLI后,可以通过在命令行中键入spring并按Enter键来运行它。如果在没有任何参数的情况下运行spring,将显示一个帮助屏幕,如下所示:
$ spring
usage: spring [--help] [--version]
<command> [<args>]
Available commands are:
init [options] [location]
Initialize a new project using Spring Initializr (start.spring.io)
encodepassword [options] <password to encode>
Encode a password for use with Spring Security
shell
Start a nested shell
Common options:
--debug Verbose mode
Print additional status information for the command you are running
See 'spring help <command>' for more information on a specific command.
您可以键入spring-help以获取有关任何支持的命令的更多详细信息,如以下示例所示:
$ spring help init
spring init - Initialize a new project using Spring Initializr (start.spring.io)
usage: spring init [options] [location]
Option Description
------ -----------
-a, --artifact-id <String> Project coordinates; infer archive name (for
example 'test')
-b, --boot-version <String> Spring Boot version (for example '1.2.0.RELEASE')
--build <String> Build system to use (for example 'maven' or
'gradle') (default: maven)
-d, --dependencies <String> Comma-separated list of dependency identifiers to
include in the generated project
--description <String> Project description
-f, --force Force overwrite of existing files
--format <String> Format of the generated content (for example
'build' for a build file, 'project' for a
project archive) (default: project)
-g, --group-id <String> Project coordinates (for example 'org.test')
-j, --java-version <String> Language level (for example '1.8')
-l, --language <String> Programming language (for example 'java')
--list List the capabilities of the service. Use it to
discover the dependencies and the types that are
available
-n, --name <String> Project name; infer application name
-p, --packaging <String> Project packaging (for example 'jar')
--package-name <String> Package name
-t, --type <String> Project type. Not normally needed if you use --
build and/or --format. Check the capabilities of
the service (--list) for more details
--target <String> URL of the service to use (default: https://start.
spring.io)
-v, --version <String> Project version (for example '0.0.1-SNAPSHOT')
-x, --extract Extract the project archive. Inferred if a
location is specified without an extension
examples:
To list all the capabilities of the service:
$ spring init --list
To creates a default project:
$ spring init
To create a web my-app.zip:
$ spring init -d=web my-app.zip
To create a web/data-jpa gradle project unpacked:
$ spring init -d=web,jpa --build=gradle my-dir
version命令提供了一种快速的方法来检查您正在使用的Spring Boot版本,如下所示:
$ spring version
Spring CLI v3.2.1
5.3 初始化新项目
init命令允许您在不离开shell的情况下使用start.spring.io创建一个新项目,如以下示例所示:
$ spring init --dependencies=web,data-jpa my-project
Using service at https://start.spring.io
Project extracted to '/Users/developer/example/my-project'
前面的示例使用基于Maven的项目创建了一个my-project目录,该项目使用spring-boot-starter-web和spring-boot-starter-data-jpa。您可以使用–list标志列出服务的功能,如以下示例所示:
$ spring init --list
=======================================
Capabilities of https://start.spring.io
=======================================
Available dependencies:
-----------------------
actuator - Actuator: Production ready features to help you monitor and manage your
application
...
web - Web: Support for full-stack web development, including Tomcat and spring-webmvc
websocket - Websocket: Support for WebSocket development
ws - WS: Support for Spring Web Services
Available project types:
------------------------
gradle-build - Gradle Config [format:build, build:gradle]
gradle-project - Gradle Project [format:project, build:gradle]
maven-build - Maven POM [format:build, build:maven]
maven-project - Maven Project [format:project, build:maven] (default)
...
init命令支持许多选项。有关更多详细信息,请参阅帮助输出。例如,以下命令创建一个使用Java 17和war包的Gradle项目:
$ spring init --build=gradle --java-version=17 --dependencies=websocket
--packaging=war sample-app.zip
Using service at https://start.spring.io
Content saved to 'sample-app.zip'
5.4 使用嵌入式Shell
Spring Boot包括BASH和zsh shell的命令行完成脚本。如果您不使用这两个shell中的任何一个(可能您是Windows用户),则可以使用shell命令启动集成shell,如以下示例所示:
$ spring shell
Spring Boot (v3.2.1)
Hit TAB to complete. Type \'help' and hit RETURN for help, and \'exit' to quit.
从嵌入式shell内部,您可以直接运行其他命令:
$ version
Spring CLI v3.2.1
嵌入式shell支持ANSI颜色输出以及制表符完成。如果需要运行本机命令,可以使用!前缀。要退出嵌入的外壳,请按ctrl-c。