Appearance
6. 使用 Spring Boot 进行开发
本节将更详细地介绍如何使用 Spring Boot。 它涵盖了构建系统、自动配置以及如何运行应用程序等主题。 我们还介绍了一些 Spring Boot 最佳实践。 尽管 Spring Boot 没有什么特别之处(它只是您可以使用的另一个库),但遵循一些建议后,您的开发过程会更加轻松。
如果您刚开始使用 Spring Boot,那么在深入研究本节之前,您可能应该阅读入门指南。
6.1 构建系统
强烈建议您选择支持依赖项管理并且可以使用发布到 “Maven Central” 存储库的工件的构建系统。 我们建议您选择 Maven 或 Gradle。 可以让 Spring Boot 与其他构建系统(例如 Ant)一起使用,但它们没有得到特别好的支持。
6.1.1 依赖管理
Spring Boot 的每个版本都提供了它支持的依赖项的精选列表。 实际上,你不需要在构建配置中为这些依赖项中的任何一个提供版本,因为 Spring Boot 会为你管理。 当您升级 Spring Boot 本身时,这些依赖项也会以一致的方式升级。
TIP
如果需要,您仍然可以指定版本并覆盖 Spring Boot 的建议。
精选列表包含可与 Spring Boot 一起使用的所有 Spring 模块,以及第三方库的精炼列表。 该列表作为标准的物料清单 (spring-boot-dependencies
) 提供,可与 Maven 和 Gradle 一起使用。
WARNING
Spring Boot 的每个版本都与 Spring Framework 的基本版本相关联。 我们**强烈建议*8您不要指定其版本。
6.1.2 Maven
要了解如何将 Spring Boot 与 Maven 一起使用,请参阅 Spring Boot 的 Maven 插件的文档:
6.1.3 Gradle
要了解如何将 Spring Boot 与 Gradle 一起使用,请参阅 Spring Boot 的 Gradle 插件的文档:
6.1.4 Ant
可以使用 Apache Ant+Ivy 构建 Spring Boot 项目。 spring-boot-antlib
“AntLib” 模块也可用于帮助 Ant 创建可执行的 jar.
要声明依赖项,一个典型的ivy.xml
文件类似于以下示例:
xml
<ivy-module version="2.0">
<info organisation="org.springframework.boot" module="spring-boot-sample-ant" />
<configurations>
<conf name="compile" description="everything needed to compile this module" />
<conf name="runtime" extends="compile" description="everything needed to run this module" />
</configurations>
<dependencies>
<dependency org="org.springframework.boot" name="spring-boot-starter"
rev="${spring-boot.version}" conf="compile" />
</dependencies>
</ivy-module>
典型的build.xml
情况如以下示例所示
xml
<project
xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:spring-boot="antlib:org.springframework.boot.ant"
name="myapp" default="build">
<property name="spring-boot.version" value="2.7.18" />
<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve pattern="lib/[conf]/[artifact]-[type]-[revision].[ext]" />
</target>
<target name="classpaths" depends="resolve">
<path id="compile.classpath">
<fileset dir="lib/compile" includes="*.jar" />
</path>
</target>
<target name="init" depends="classpaths">
<mkdir dir="build/classes" />
</target>
<target name="compile" depends="init" description="compile">
<javac srcdir="src/main/java" destdir="build/classes" classpathref="compile.classpath" />
</target>
<target name="build" depends="compile">
<spring-boot:exejar destfile="build/myapp.jar" classes="build/classes">
<spring-boot:lib>
<fileset dir="lib/runtime" />
</spring-boot:lib>
</spring-boot:exejar>
</target>
</project>
TIP
如果您不想使用spring-boot-antlib
模块,请参阅 Build an Executable Archive From Ant without Using spring-boot-antlib “How-to” 。
6.1.5 Starters
Starters 是一组方便的依赖项描述符,您可以将其包含在应用程序中。 您可以获得所需的所有 Spring 和相关技术的一站式商店,而无需搜索示例代码和复制粘贴依赖项描述符。 例如,如果您想开始使用 Spring 和 JPA 进行数据库访问,请在项目中包含依赖项spring-boot-starter-data-jpa
。
Starter 包含许多依赖项,您需要这些依赖项才能快速启动和运行项目,并具有一组一致、受支持的托管传递依赖项。
TIP
名称中的内容
所有官方启动器都遵循类似的命名模式;spring-boot-starter-*
,其中*
是特定类型的应用程序。 此命名结构旨在在您需要查找启动器时提供帮助。 许多 IDE 中的 Maven 集成允许您按名称搜索依赖项。 例如,安装了适当的 Eclipse 或 Spring Tools 插件后,您可以在 POM 编辑器中按ctrl-space
,并键入 “spring-boot-starter” 以获取完整列表.
如“创建自己的 Starter”部分所述,第三方 Starters 不应以spring-boot
开头,因为它是为官方 Spring Boot 工件保留的。 相反,第三方启动器通常以项目名称开头。 例如,名为thirdpartyproject
的第三方初学者项目通常命名为thirdpartyproject-spring-boot-starter
Spring Boot 在org.springframework.boot
组下提供了以下应用程序启动器
表 1.Spring Boot application启动器
名字 | 描述 |
---|---|
spring-boot-starter | 核心启动器,包括自动配置支持、日志记录和 YAML |
spring-boot-starter-activemq | 使用 Apache ActiveMQ 的 Starter for JMS 消息传递 |
spring-boot-starter-amqp | 使用 Spring AMQP 和 Rabbit MQ 的入门 |
spring-boot-starter-aop | 使用 Spring AOP 和 AspectJ 进行面向方面编程的入门 |
spring-boot-starter-artemis | 使用 Apache Artemis 的 Starter for JMS 消息传递 |
spring-boot-starter-batch | 使用 Spring Batch 的 Starter |
spring-boot-starter-cache | 使用 Spring Framework 的缓存支持的 Starter |
spring-boot-starter-data-cassandra | 使用 Cassandra 分布式数据库和 Spring Data Cassandra 的入门 |
spring-boot-starter-data-cassandra-reactive | 使用 Cassandra 分布式数据库和 Spring Data Cassandra Reactive 的入门 |
spring-boot-starter-data-couchbase | 使用 Couchbase 面向文档的数据库和 Spring Data Couchbase 的入门 |
spring-boot-starter-data-couchbase-reactive | 使用 Couchbase 面向文档的数据库和 Spring Data Couchbase Reactive 的入门 |
spring-boot-starter-data-elasticsearch | 使用 Elasticsearch 搜索和分析引擎和 Spring Data Elasticsearch 的入门版 |
spring-boot-starter-data-jdbc | 使用 Spring Data JDBC 的初学者 |
spring-boot-starter-data-jpa | 将 Spring Data JPA 与 Hibernate 结合使用的入门 |
spring-boot-starter-data-ldap | 使用 Spring Data LDAP 的入门 |
spring-boot-starter-data-mongodb | 使用 MongoDB 面向文档的数据库和 Spring Data MongoDB 的入门 |
spring-boot-starter-data-mongodb-reactive | 使用 MongoDB 面向文档的数据库和 Spring Data MongoDB Reactive 的入门 |
spring-boot-starter-data-neo4j | 使用 Neo4j 图形数据库和 Spring Data Neo4j 的入门 |
spring-boot-starter-data-r2dbc | 使用 Spring Data R2DBC 的启动器 |
spring-boot-starter-data-redis | 将 Redis 键值数据存储与 Spring Data Redis 和 Lettuce 客户端结合使用的入门 |
spring-boot-starter-data-redis-reactive | 将 Redis 键值数据存储与 Spring Data Redis 反应式和 Lettuce 客户端一起使用的入门 |
spring-boot-starter-data-rest | 使用 Spring Data REST 和 Spring MVC 通过 REST 公开 Spring Data 存储库的入门 |
spring-boot-starter-freemarker | 使用 FreeMarker 视图构建 MVC Web 应用程序的入门 |
spring-boot-starter-graphql | 使用 Spring GraphQL 构建 GraphQL 应用程序的入门 |
spring-boot-starter-groovy-templates | 使用 Groovy Templates 视图构建 MVC Web 应用程序的 Starter |
spring-boot-starter-hateoas | 使用 Spring MVC 和 Spring HATEOAS 构建基于超媒体的 RESTful Web 应用程序的入门 |
spring-boot-starter-integration | 使用 Spring 集成的 Starter |
spring-boot-starter-jdbc | 将 JDBC 与 HikariCP 连接池一起使用的入门 |
spring-boot-starter-jersey | 使用 JAX-RS 和 Jersey 构建 RESTful Web 应用程序的入门工具。spring-boot-starter-web 的替代方案 |
spring-boot-starter-jooq | 使用 jOOQ 通过 JDBC 访问 SQL 数据库的入门工具。spring-boot-starter-data-jpa 或 spring-boot-starter-jdbc 的替代方案 |
spring-boot-starter-json | 用于读取和写入 json 的 Starter |
spring-boot-starter-jta-atomikos | 使用 Atomikos 进行 JTA 交易的 Starter |
spring-boot-starter-mail | 使用 Java Mail 和 Spring Framework 的电子邮件发送支持的入门 |
spring-boot-starter-mustache | 使用 Mustache 视图构建 Web 应用程序的入门 |
spring-boot-starter-oauth2-client | 使用 Spring Security 的 OAuth2/OpenID Connect 客户端功能的入门 |
spring-boot-starter-oauth2-resource-server | 使用 Spring Security 的 OAuth2 资源服务器功能的入门 |
spring-boot-starter-quartz | 使用 Quartz 调度程序的入门 |
spring-boot-starter-rsocket | 用于构建 RSocket 客户端和服务器的 Starter |
spring-boot-starter-security | 使用 Spring Security 的 Starter |
spring-boot-starter-test | 用于使用 JUnit Jupiter、Hamcrest 和 Mockito 等库测试 Spring Boot 应用程序的 Starter |
spring-boot-starter-thymeleaf | 使用 Thymeleaf 视图构建 MVC Web 应用程序的入门 |
spring-boot-starter-validation | 将 Java Bean 验证与 Hibernate 验证器结合使用的入门 |
spring-boot-starter-web | 使用 Spring MVC 构建 Web(包括 RESTful)应用程序的入门工具。使用 Tomcat 作为默认嵌入式容器 |
spring-boot-starter-web-services | 使用 Spring Web 服务的入门 |
spring-boot-starter-webflux | 使用 Spring Framework 的反应式 Web 支持构建 WebFlux 应用程序的入门 |
spring-boot-starter-websocket | 使用 Spring Framework 的 MVC WebSocket 支持构建 WebSocket 应用程序的入门工具 |
除了应用程序启动器之外,以下启动器还可用于添加生产就绪功能:
表 2.Spring Boot production启动器
名字 | 描述 |
---|---|
spring-boot-starter-actuator | 使用 Spring Boot 的 Actuator 的 Starter,它提供生产就绪功能来帮助您监控和管理应用程序 |
最后,Spring Boot 还包括以下启动器,如果你想排除或交换特定的技术方面,可以使用这些启动器:
表 3.Spring Boot technical启动器
名字 | 描述 |
---|---|
spring-boot-starter-jetty | 使用 Jetty 作为嵌入式 servlet 容器的入门工具。spring-boot-starter-tomcat 的替代方案 |
spring-boot-starter-log4j2 | 使用 Log4j2 进行日志记录的入门。spring-boot-starter-logging 的替代方案 |
spring-boot-starter-logging | 使用 Logback 进行日志记录的启动器。默认日志记录启动器 |
spring-boot-starter-reactor-netty | 使用 Reactor Netty 作为嵌入式反应式 HTTP 服务器的启动器。 |
spring-boot-starter-tomcat | 使用 Tomcat 作为嵌入式 servlet 容器的入门工具。spring-boot-starter-web 使用的默认 servlet 容器启动器 |
spring-boot-starter-undertow | 使用 Undertow 作为嵌入式 servlet 容器的入门工具。spring-boot-starter-tomcat 的替代方案 |
要了解如何交换技术方面,请参阅交换 Web 服务器和日志记录系统的操作文档。
TIP
有关其他社区贡献的启动程序的列表,请参阅 GitHub 上spring-boot-starters
模块中的 README 文件
6.2 构建代码
Spring Boot 不需要任何特定的代码布局即可工作。 但是,有一些最佳实践会有所帮助。
6.2.1 使用“default”包
当一个类不包含package
声明时,它被视为位于 “default package” 中。 通常不建议使用 “default package” 并且应该避免使用。 对于使用 @ComponentScan
、@ConfigurationPropertiesScan
、@EntityScan
或 @SpringBootApplication
注解 的 Spring Boot 应用程序,它可能会导致特定问题,因为每个 jar 中的每个类都会被读取。
TIP
我们建议您遵循 Java 建议的包命名约定,并使用反向域名(例如com.example.project
)
6.2.2 找到 Main Application 类
我们通常建议您将主应用程序类放在其他类上方的根包中。 @SpringBootApplication 注解通常放在你的主类上,它隐式地定义了某些项目的基本 “搜索包”。 例如,如果您正在编写 JPA 应用程序,则使用带注释@SpringBootApplication
的类的包来搜索项目@Entity
。 使用根包还允许组件扫描仅应用于您的项目.
TIP
如果您不想使用@SpringBootApplication
,则它导入的@EnableAutoConfiguration
和@ComponentScan
注释定义了该行为,因此您也可以改用这些
下面的清单显示了一个典型的布局:
txt
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
,如下所示:
java
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);
}
}
kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args)
}
6.3 配置类
Spring Boot 支持基于 Java 的配置。 尽管可以与 XML 源一起使用SpringApplication
,但我们通常建议主源为单个@Configuration
类。 通常,定义main
方法的类是主类@Configuration
良好候选者。
Internet 上已经发布了许多使用 XML 配置的 Spring 配置示例。 如果可能,请始终尝试使用等效的基于 Java 的配置。 搜索Enable*
注解是一个很好的起点。
6.3.1 导入其他配置类
你不需要把所有的@Configuration
都放在一个类中。 @Import
可用于导入其他 configuration classes。 或者,你可以使用@ComponentScan
自动获取所有 Spring 组件,包括 @Configuration
类。
6.3.2 导入 XML 配置
如果您绝对必须使用基于 XML 的配置,我们建议您仍然从@Configuration
开始。 然后,您可以使用@ImportResource
来加载 XML 配置文件。
6.4 自动配置
Spring Boot 自动配置会尝试根据您添加的 jar 依赖项自动配置 Spring 应用程序。 例如,如果HSQLDB
在你的 Classpath 上,并且你没有手动配置任何数据库连接 bean,那么 Spring Boot 会自动配置内存数据库。
您需要通过向其中一个类添加@EnableAutoConfiguration
或者@SpringBootApplication
到配置类@Configuration
TIP
您应该只添加一个@SpringBootApplication
或@EnableAutoConfiguration
注解。 我们通常建议您仅将其中一个添加到主类@Configuration
中。
6.4.1 逐步替换自动配置
自动配置是非侵入性的。 您可以随时开始定义自己的配置以替换自动配置的特定部分。 例如,如果您添加自己的DataSource
Bean,则默认的嵌入式数据库支持将退出。
如果您需要了解当前正在应用的自动配置以及原因,请使用--debug
开关启动您的应用程序。 这样做会为选定的核心记录器启用调试日志,并将条件报告记录到控制台。
6.4.2 禁用特定的自动配置
如果您发现正在应用不需要的特定自动配置类,则可以使用@SpringBootApplication
的exclude 属性来禁用它们,如以下示例所示:
java
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MyApplication {
}
kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
@SpringBootApplication(exclude = [DataSourceAutoConfiguration::class])
class MyApplication
如果类不在 Classpath 上,则可以使用注解的属性excludeName
并指定完全限定名称。 如果您更喜欢使用@EnableAutoConfiguration
而不是@SpringBootApplication
,exclude
和excludeName
都可以使用。 最后,您还可以使用spring.autoconfigure.exclude
属性控制要排除的自动配置类的列表。
TIP
您可以在注释级别定义排除项,也可以使用 property 定义排除项。
TIP
即使自动配置类是public
,类中被视为公共 API 的唯一方面是可用于禁用自动配置的类的名称。 这些类的实际内容(例如嵌套配置类或 bean 方法)仅供内部使用,我们不建议直接使用它们。
6.4.3 自动配置 Package
自动配置包是各种自动配置的功能在扫描实体和 Spring Data 存储库等内容时默认查找的包。 EnableAutoConfiguration
(直接或通过@SpringBootApplication
存在)确定默认的自动配置包。 可以使用@AutoConfigurationPackage
配置其他软件包。
6.5 Spring Bean 和依赖注入
您可以自由使用任何标准的 Spring Framework 技术来定义 bean 及其注入的依赖项。 我们通常建议使用构造函数注入来连接依赖项并查找@ComponentScan
bean
如果按照上述建议构建代码(将应用程序类放在 top 包中),则可以在没有任何参数的情况下添加@ComponentScan
,也可以使用隐式包含它的@SpringBootApplication
。 您的所有应用程序组件(@Component
, @Service
, @Repository
, @Controller
和其他组件)都将自动注册为 Spring Bean。
下面的示例展示了一个使用构造函数注入来获取必需的RiskAssessor
Bean的 @Service
Bean。
java
import org.springframework.stereotype.Service;
@Service
public class MyAccountService implements AccountService {
private final RiskAssessor riskAssessor;
public MyAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}
// ...
}
kotlin
import org.springframework.stereotype.Service
@Service
class MyAccountService(private val riskAssessor: RiskAssessor) : AccountService
如果一个 bean 有多个构造函数,则需要标记你希望 Spring 使用@Autowired
的构造函数
java
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;
}
// ...
}
kotlin
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.io.PrintStream
@Service
class MyAccountService : AccountService {
private val riskAssessor: RiskAssessor
private val out: PrintStream
@Autowired
constructor(riskAssessor: RiskAssessor) {
this.riskAssessor = riskAssessor
out = System.out
}
constructor(riskAssessor: RiskAssessor, out: PrintStream) {
this.riskAssessor = riskAssessor
this.out = out
}
// ...
}
TIP
请注意,使用构造函数注入如何让字段riskAssessor
被标记为final
,这表示它随后无法更改
6.6 使用 @SpringBootApplication 注解
许多 Spring Boot 开发人员喜欢他们的应用程序使用自动配置、组件扫描,并能够在他们的“应用程序类”上定义额外的配置。 单个@SpringBootApplication
可用于启用这三个功能,即:
@EnableAutoConfiguration
:启用 Spring Boot 的自动配置机制@ComponentScan
:在应用程序所在的包上启用@Component
(请参阅最佳实践@Component)@SpringBootConfiguration
:启用在上下文中注册额外的 bean 或导入额外的配置类。 Spring 标准的@Configuration
替代方案,有助于在集成测试中进行配置检测。
java
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);
}
}
kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
// same as @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan
@SpringBootApplication
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args)
}
TIP
@SpringBootApplication
还提供了别名来自定义@EnableAutoConfiguration
和@ComponentScan
的属性
TIP
这些功能都不是必需的,您可以选择用它启用的任何功能替换此单个注释。 例如,您可能不想在应用程序中使用 component scan 或 configuration properties scan:
java
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);
}
}
kotlin
import org.springframework.boot.SpringBootConfiguration
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.docs.using.structuringyourcode.locatingthemainclass.MyApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Import
@SpringBootConfiguration(proxyBeanMethods = false)
@EnableAutoConfiguration
@Import(SomeConfiguration::class, AnotherConfiguration::class)
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args)
}
TIP
在此示例中,与任何其他 Spring Boot 应用程序一样,MyApplication
只是不会自动检测 @Component
注解类和@ConfigurationProperties
注解类,并且显式导入用户定义的 bean(请参阅 @Import
)。
6.7 运行应用程序
将应用程序打包为 jar 并使用嵌入式 HTTP 服务器的最大优势之一是,您可以像运行任何其他应用程序一样运行应用程序。 该示例适用于调试 Spring Boot 应用程序。 您不需要任何特殊的 IDE 插件或扩展。
TIP
本节仅介绍基于 jar 的打包。 如果您选择将应用程序打包为 war 文件,请参阅您的服务器和 IDE 文档。
6.7.1 从 IDE 运行
您可以从 IDE 将 Spring Boot 应用程序作为 Java 应用程序运行。 但是,您首先需要导入您的项目。 导入步骤因 IDE 和生成系统而异。 大多数 IDE 可以直接导入 Maven 项目。 例如,Eclipse 用户可以从菜单File
中选择Import…
→Existing Maven Projects
.
如果您无法直接将项目导入 IDE,则可以使用构建插件生成 IDE 元数据。 Maven 包括用于 Eclipse 和 IDEA 的插件。 Gradle 为各种 IDE提供插件。
6.7.2 作为打包应用程序运行
如果使用 Spring Boot Maven 或 Gradle 插件创建可执行 jar,则可以使java -jar
运行应用程序,如以下示例所示:
shell
$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar
还可以在启用远程调试支持的情况下运行打包的应用程序。 这样做可以将调试器附加到打包的应用程序,如以下示例所示:
shell
$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
-jar target/myapplication-0.0.1-SNAPSHOT.jar
6.7.3 使用 Maven 插件
Spring Boot Maven 插件包括一个可用于快速编译和运行应用程序的目标run
。 应用程序以松散形式运行,就像它们在 IDE 中一样。 以下示例显示了用于运行 Spring Boot 应用程序的典型 Maven 命令:
shell
$ mvn spring-boot:run
您可能还希望使用MAVEN_OPTS
系统环境变量,如以下示例所示:
shell
$ export MAVEN_OPTS=-Xmx1024m
6.7.4 使用 Gradle 插件
Spring Boot Gradle 插件还包括一个任务bootRun
,可用于以爆炸形式运行应用程序。 每当您应用 org.springframework.boot
和 java
插件时,都会添加bootRun
任务,如以下示例所示:
shell
$ gradle bootRun
您可能还希望使用JAVA_OPTS
系统环境变量,如以下示例所示:
shell
$ export JAVA_OPTS=-Xmx1024m
6.7.5 热插拔
由于 Spring Boot 应用程序是普通的 Java 应用程序,因此 JVM 热交换应该开箱即用。 JVM 热插拔在某种程度上受到它可以替换的字节码的限制。 对于更完整的解决方案,可以使用 JRebel。
spring-boot-devtools
模块还包括对应用程序快速重启的支持。 有关详细信息,请参阅热插拔 “How-to”。
6.8 开发者工具
Spring Boot 包含一组额外的工具,这些工具可以使应用程序开发体验更加愉快。 spring-boot-devtools
模块可以包含在任何项目中,以提供其他开发时功能。 要包含 devtools 支持,请将模块依赖项添加到您的构建中,如以下 Maven 和 Gradle 清单所示:
Maven
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
Gradle
xml
dependencies {
developmentOnly("org.springframework.boot:spring-boot-devtools")
}
提示
Devtools 可能会导致类加载问题,尤其是在多模块项目中。诊断类加载问题 介绍了如何诊断和解决这些问题。
提示
在运行完全打包的应用程序时,会自动禁用开发人员工具。 如果您的应用程序是从java -jar
启动的,或者它是从特殊类加载器启动的,则它被视为“生产应用程序”。 您可以使用spring.devtools.restart.enabled
系统属性控制此行为。 要启用 devtools,而不考虑用于启动应用程序的类加载器,请设置-Dspring.devtools.restart.enabled=true
系统属性。 在运行 devtools 存在安全风险的生产环境中,不得执行此操作。 要禁用 devtools,请排除依赖项或设置-Dspring.devtools.restart.enabled=false
系统属性。
提示
在 Maven 中将依赖项标记为可选或在 Gradle 中使用developmentOnly
配置(如上所示)可以防止 devtools 被传递到使用您项目的其他模块。
提示
默认情况下,重新打包的存档不包含 devtools。 如果你想使用某个远程 devtools 功能,你需要包含它。 使用 Maven 插件时,请将属性excludeDevtools
设置为false
。 使用 Gradle 插件时,请配置任务的 Classpath 以包含 developmentOnly
配置。
6.8.1 诊断类加载问题
如 Restart vs Reload 部分所述,重新启动功能是使用两个类加载器实现的。 对于大多数应用程序,此方法效果很好。 但是,它有时会导致类加载问题,尤其是在多模块项目中。
要诊断类加载问题是否确实是由 devtools 及其两个类加载器引起的,请尝试禁用 restart。 如果这解决了您的问题,请自定义重新启动类加载器以包含整个项目。
6.8.2 属性默认值
Spring Boot 支持的几个库使用缓存来提高性能。 例如,模板引擎会缓存已编译的模板,以避免重复解析模板文件。 此外,Spring MVC 可以在提供静态资源时将 HTTP 缓存头添加到响应中
虽然缓存在生产中非常有益,但在开发过程中可能会适得其反,阻止您看到刚刚在应用程序中所做的更改。 因此,spring-boot-devtools默认禁用缓存选项。
缓存选项通常由文件application.properties
中的设置配置。 例如,Thymeleaf 提供了 spring.thymeleaf.cache
。 无需手动设置这些属性,spring-boot-devtools
模块会自动应用合理的开发时配置。
下表列出了应用的所有属性:
名字 | 默认值 |
---|---|
server.error.include-binding-errors | always |
server.error.include-message | always |
server.error.include-stacktrace | always |
server.servlet.jsp.init-parameters.development | true |
server.servlet.session.persistent | true |
spring.freemarker.cache | false |
spring.graphql.graphiql.enabled | true |
spring.groovy.template.cache | false |
spring.h2.console.enabled | true |
spring.mustache.servlet.cache | false |
spring.mvc.log-resolved-exception | true |
spring.reactor.netty.shutdown-quiet-period | 0s |
spring.template.provider.cache | false |
spring.thymeleaf.cache | false |
spring.web.resources.cache.period | 0 |
spring.web.resources.chain.cache | false |
提示
如果不希望应用属性默认值,则可以在application.properties
中设置spring.devtools.add-properties
为false
由于在开发 Spring MVC 和 Spring WebFlux 应用程序时需要有关 Web 请求的更多信息,因此开发人员工具建议您为web
日志记录组启用DEBUG
日志记录。 这将为您提供有关传入请求、哪个处理程序正在处理该请求、响应结果和其他详细信息的信息。 如果您希望记录所有请求详细信息(包括潜在的敏感信息),则可以打开spring.mvc.log-request-details
或者spring.codec.log-request-details
配置属性。
6.8.3 自动重启
每当 Classpath 上的文件发生更改时,使用spring-boot-devtools
的应用程序都会自动重新启动。 在 IDE 中工作时,这可能是一个有用的功能,因为它为代码更改提供了一个非常快速的反馈循环。 默认情况下,将监视 Classpath 上指向目录的任何条目的更改。 请注意,某些资源(如静态资产和视图模板)不需要重新启动应用程序。
TIP
触发重启
当 DevTools 监控 Classpath 资源时,触发重启的唯一方法是更新 Classpath。 无论您使用的是 IDE 还是其中一个构建插件,都必须重新编译修改后的文件以触发重启。 更新 Classpath 的方式取决于您使用的工具:
- 在 Eclipse 中,保存修改后的文件会导致 Classpath 更新并触发重新启动。
- 在 IntelliJ IDEA 中,构建项目 (Build +→+ Build Project) 具有相同的效果。
- 如果使用构建插件,则为Maven运行
mvn compile
或 Gradle 运行gradle build
将触发重启。
TIP
如果要使用构建插件通过 Maven 或 Gradle 重新启动,则必须将设置forking
保留为 enabled
。 如果禁用 forking,则不会创建 devtools 使用的隔离应用程序类加载器,并且重启将无法正常运行。
TIP
与 LiveReload 一起使用时,自动重启效果非常好。有关详细信息,请参阅 LiveReload 部分。 如果使用 JRebel,则禁用自动重启,以支持动态类重新加载。 其他 devtools 功能(例如 LiveReload 和属性覆盖)仍然可以使用。
TIP
DevTools 依赖于应用程序上下文的 shutdown 钩子在重启期间关闭它。 如果你禁用了 shutdown hook (SpringApplication.setRegisterShutdownHook(false)
),它就无法正常工作
TIP
DevTools 需要使用ApplicationContext
自定义 ResourceLoader
. 如果您的应用程序已经提供了一个,那么它将被包装。 不支持直接覆盖ApplicationContext
上的getResource
方法。
TIP
使用 AspectJ 编织时不支持自动重启。
TIP
重启 vs 重新加载
Spring Boot 提供的重启技术通过使用两个类加载器来工作。 不更改的类(例如,来自第三方 jar 的类)将加载到基类加载器中。 您正在积极开发的类将加载到重新启动类加载器中。 重新启动应用程序时,将丢弃重新启动类加载器,并创建一个新的类加载器。 这种方法意味着应用程序重启通常比 “冷启动” 快得多,因为基类加载器已经可用并已填充。
如果您发现重新启动对于您的应用程序来说不够快,或者您遇到了类加载问题,您可以考虑从 ZeroTurnaround 重新加载 JRebel 等技术。 这些通过在加载时重写类来使它们更适合重新加载。
在条件评估中记录变化
默认情况下,每次应用程序重新启动时,都会记录一个显示条件评估增量的报告。 该报告显示在您进行更改(例如添加或删除 Bean 以及设置配置属性)时对应用程序的自动配置的更改。
要禁用报表的日志记录,请设置以下属性:
properties
spring.devtools.restart.log-condition-evaluation-delta=false
yaml
spring:
devtools:
restart:
log-condition-evaluation-delta: false
排除资源
某些资源在更改时不一定需要触发重启。 例如,可以就地编辑 Thymeleaf 模板。 默认情况下,更改 /META-INF/maven
, /META-INF/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/**"
TIP
如果要保留这些默认值并添加其他排除项,请改用spring.devtools.restart.additional-exclude
属性
监视其他路径
您可能希望在更改不在 Classpath 上的文件时重新启动或重新加载应用程序。 为此,请使用spring.devtools.restart.additional-paths
属性配置其他路径以监视更改。 您可以使用前面描述的spring.devtools.restart.exclude
属性来控制其他路径下的更改是触发完全重新启动还是实时重新加载。
禁用重启
如果不想使用重新启动功能,可以使用spring.devtools.restart.enabled
属性 . 在大多数情况下,你可以在你的 application.properties
(这样做仍然会初始化重启 classloader,但它不会监视文件更改)
如果需要完全禁用重新启动支持(例如,因为它不适用于特定库),则需要将系统属性spring.devtools.restart.enabled
设置为false
在调用SpringApplication.run(…)
之前,如以下示例所示:
java
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);
}
}
Kotlin
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
object MyApplication {
@JvmStatic
fun main(args: Array<String>) {
System.setProperty("spring.devtools.restart.enabled", "false")
SpringApplication.run(MyApplication::class.java, *args)
}
}
使用 Trigger 文件
如果使用持续编译更改文件的 IDE,则可能更愿意仅在特定时间触发重启。 为此,您可以使用 “trigger file”,这是一个特殊文件,当您想要实际触发重启检查时必须对其进行修改。
TIP
对文件的任何更新都会触发检查,但只有在 Devtools 检测到它有事情要做时,才会真正发生重启。
要使用触发器文件,请将spring.devtools.restart.trigger-file
设置为触发器文件的名称(不包括任何路径)。 触发器文件必须出现在 Classpath 上的某个位置
例如,如果您有一个具有以下结构的项目:
txt
src
+- main
+- resources
+- .reloadtrigger
那么您的trigger-file
将是:
properties
spring.devtools.restart.trigger-file=.reloadtrigger
yaml
spring:
devtools:
restart:
trigger-file: ".reloadtrigger"
现在,只有在src/main/resources/.reloadtrigger
更新时才会重新启动。
TIP
您可能希望设置spring.devtools.restart.trigger-file
为全局设置,以便所有项目都以相同的方式运行。
某些 IDE 具有无需手动更新触发器文件的功能。Spring Tools for Eclipse 和 IntelliJ IDEA(旗舰版)都有这样的支持。 使用 Spring Tools,您可以使用控制台视图中的 “reload” 按钮(只要您的trigger-file
名称为.reloadtrigger
)。 对于 IntelliJ IDEA,您可以按照其文档中的说明进行操作。
自定义 Restart Classloader
如前面的 Restart vs Reload 部分所述,重新启动功能是使用两个类加载器实现的。 如果这会导致问题,您可能需要自定义哪个 Classloader 加载的内容。
默认情况下,IDE 中任何打开的项目都使用 “restart” 类加载器加载,任何常规文件.jar
都使用 “base” 类加载器加载。 如果使用mvn spring-boot:run
或者gradle bootRun
,情况也是如此:包含@SpringBootApplication
的项目使用 “restart” 类加载器加载,其他所有内容都使用 “base” 类加载器加载。
你可以通过创建一个META-INF/spring-devtools.properties
文件来指示 Spring Boot 使用不同的类加载器加载项目的各个部分。 spring-devtools.properties
文件可以包含前缀为 restart.exclude
和 restart.include
的属性。 include
元素是应该被拉入 “restart” 类加载器中的项,exclude
元素是应该被下推到 “base” 类加载器中的项。 该属性的值是应用于 Classpath 的正则表达式模式,如以下示例所示:
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"
TIP
所有属性键都必须是唯一的。 只要属性以restart.include.
或restart.exclude.
开头
TIP
所有在Classpath 中的META-INF/spring-devtools.properties
所有内容都被加载。 您可以将文件打包到项目内部,也可以打包到项目使用的库中
已知限制
重新启动功能不适用于使用标准ObjectInputStream
. 如果需要反序列化数据,则可能需要结合Thread.currentThread().getContextClassLoader()
使用Spring的ConfigurableObjectInputStream
不幸的是,一些第三方库在没有考虑上下文类加载器的情况下进行反序列化。 如果您发现此类问题,则需要与原作者请求修复。
6.8.4 LiveReload
spring-boot-devtools
模块包括一个嵌入式 LiveReload 服务器,该服务器可用于在更改资源时触发浏览器刷新。 LiveReload 浏览器扩展可免费用于 Chrome、Firefox 和 Safari。 您可以通过在所选浏览器的市场或商店中搜索“LiveReload”来找到这些扩展
如果不想在应用程序运行时启动 LiveReload 服务器,则可以将spring.devtools.livereload.enabled
属性设置为 false
TIP
您一次只能运行一个 LiveReload 服务器。 在启动应用程序之前,请确保没有其他 LiveReload 服务器正在运行。 如果从 IDE 启动多个应用程序,则只有第一个应用程序支持 LiveReload。
WARNING
要在文件更改时触发 LiveReload,必须启用 Automatic Restart。
6.8.5 全局设置
您可以通过将以下任何文件添加到目录$HOME/.config/spring-boot directory
来配置全局 devtools 设置:
- spring-boot-devtools.properties
- spring-boot-devtools.yaml
- spring-boot-devtools.yml
添加到这些文件的任何属性都适用于计算机上使用 devtools 的所有 Spring Boot 应用程序。 例如,要将 restart 配置为始终使用触发器文件,请将以下属性添加到spring-boot-devtools
文件中:
properties
spring.devtools.restart.trigger-file=.reloadtrigger
yaml
spring:
devtools:
restart:
trigger-file: ".reloadtrigger"
默认情况下,$HOME
是用户的主目录。 要自定义此位置,请设置环境变量SPRING_DEVTOOLS_HOME
或系统属性spring.devtools.home
。
TIP
如果在$HOME/.config/spring-boot
中找不到 devtools 配置文件,则搜索目录$HOME
的根目录以查找是否存在文件.spring-boot-devtools.properties
。 这允许您将 devtools 全局配置与位于不支持$HOME/.config/spring-boot
位置的较旧版本 Spring Boot 上的应用程序共享。
TIP
devtools properties/yaml 文件中不支持配置文件。
在.spring-boot-devtools.properties
中激活的任何配置文件都不会影响特定于配置文件的配置文件的加载。 不支持 YAML 和 Properties 文件中的配置文件特定文件名(形式spring-boot-devtools-<profile>.properties
)和spring.config.activate.on-profile
文档。
配置文件系统监控器
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 秒轮询一次受监视的 Classpath 目录以查找更改,并保持 1 秒的静默期以确保没有其他类更改。
6.8.6 远程应用程序
Spring Boot 开发人员工具不仅限于本地开发。 在远程运行应用程序时,您还可以使用多项功能。 远程支持是可选的,因为启用远程支持可能会带来安全风险。 仅当在受信任的网络上运行时或使用 SSL 进行保护时,才应启用它。 如果这两个选项都不可用,则不应使用 DevTools 的远程支持。 您永远不应在生产部署中启用支持。
要启用它,您需要确保devtools
包含在重新打包的存档中,如下面的清单所示:
xml
<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
属性。 与任何重要的密码或密钥一样,该值应是唯一且强大的,以便无法猜测或暴力破解。
远程 devtools 支持分两部分提供:接受连接的服务器端终端节点和您在 IDE 中运行的客户端应用程序。 设置spring.devtools.remote.secret
属性时,将自动启用服务器组件。 必须手动启动 client 组件。
TIP
Spring WebFlux 应用程序不支持远程 devtools。
运行远程客户端应用程序
远程客户端应用程序设计为从 IDE 中运行。 您需要使用org.springframework.boot.devtools.RemoteSpringApplication
与连接到的远程项目相同的 Classpath 运行。 应用程序的单个必需参数是它连接到的远程 URL。
例如,如果您正在使用 Eclipse 或 Spring Tools,并且您有一个名为my-app
的 Cloud Foundry项目,并且已将其部署到 Cloud Foundry,则可以执行以下操作:
从菜单
Run
中选择Run Configurations…
。创建新的
Java Application
启动配置。浏览
my-app
项目。org.springframework.boot.devtools.RemoteSpringApplication
用作主类。添加
https://myapp.cfapps.io
到Program arguments
(或任何您的远程 URL)
正在运行的远程客户端可能类似于以下清单:
txt
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \
\\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) )
' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / /
=========|_|==============|___/===================================/_/_/_/
:: Spring Boot Remote :: (v2.7.18)
2023-11-23 07:23:21.930 INFO 28462 --- [ main] o.s.b.devtools.RemoteSpringApplication : Starting RemoteSpringApplication v2.7.18 using Java 1.8.0_392 on myhost with PID 28462 (/Users/myuser/.m2/repository/org/springframework/boot/spring-boot-devtools/2.7.18/spring-boot-devtools-2.7.18.jar started by myuser in /opt/apps/)
2023-11-23 07:23:21.936 INFO 28462 --- [ main] o.s.b.devtools.RemoteSpringApplication : No active profile set, falling back to 1 default profile: "default"
2023-11-23 07:23:22.314 INFO 28462 --- [ main] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2023-11-23 07:23:22.338 INFO 28462 --- [ main] o.s.b.devtools.RemoteSpringApplication : Started RemoteSpringApplication in 0.858 seconds (JVM running for 1.35)
TIP
因为远程客户端使用与真实应用程序相同的 Classpath,所以它可以直接读取应用程序属性。 这是读取spring.devtools.remote.secret
属性并将其传递给服务器进行身份验证的方式。
TIP
始终建议用https:
作连接协议,以便对流量进行加密并且无法拦截密码
TIP
如果需要使用代理访问远程应用程序,请配置spring.devtools.remote.proxy.host
和spring.devtools.remote.proxy.port
属性。
远程更新
远程客户端以与本地重启相同的方式监视应用程序 Classpath 的更改。 任何更新的资源都会推送到远程应用程序,并 (如果需要) 触发重启。 如果您迭代使用本地没有的云服务的功能,这可能会很有帮助。 通常,远程更新和重启比完整的重新生成和部署周期要快得多。
在较慢的开发环境中,可能会出现 Mand period 不够的情况,并且 classes 中的更改可能会被拆分为多个批次。 在上传第一批类更改后,服务器将重新启动。 无法将下一个批次发送到应用程序,因为服务器正在重新启动
这通常表现为RemoteSpringApplication
日志中有关无法上传某些类的警告,以及随后的重试。 但也可能导致应用程序代码不一致,以及在上传第一批更改后无法重新启动。 如果您经常观察到此类问题,请尝试将 spring.devtools.restart.poll-interval
和spring.devtools.restart.quiet-period
参数增加到适合您的开发环境的值。 有关配置这些属性的信息,请参阅配置文件系统监控器部分
TIP
仅当远程客户端运行时,文件才会受到监控。 如果在启动远程客户端之前更改文件,则不会将其推送到远程服务器。
6.9 打包应用程序以进行生产
可执行 jar 可用于生产部署。 由于它们是独立的,因此它们也非常适合基于云的部署。
对于其他“生产就绪”功能,例如运行状况、审核和度量 REST 或 JMX 端点,请考虑添加spring-boot-actuator
. 有关详细信息,请参阅生产就绪功能。
6.10 下一步要读什么
现在,您应该了解如何使用 Spring Boot 以及应遵循的一些最佳实践。 您现在可以继续深入了解特定的 Spring Boot 功能,也可以跳过并阅读 Spring Boot 的“生产就绪”方面。