20220507 Using Spring Boot

前言

文档地址

本节更详细地介绍了如何使用 Spring Boot。它涵盖了诸如构建系统、自动配置以及如何运行应用程序等主题。我们还介绍了一些 Spring Boot 最佳实践。尽管 Spring Boot 没有什么特别之处(它只是您可以使用的另一个库),但有一些建议可以让您的开发过程更轻松一些。

1. 构建系统

强烈建议您选择支持 依赖管理 并且可以使用发布到 Maven Central 存储库的工件的构建系统。我们建议您选择 Maven 或 Gradle 。可以让 Spring Boot 与其他构建系统(例如 Ant)一起工作,但它们并没有得到特别好的支持。

1.1. 依赖管理

Spring Boot 的每个版本都提供了它支持的依赖项的精选列表。实际上,您不需要在构建配置中为任何这些依赖项提供版本,因为 Spring Boot 会为您管理。当您升级 Spring Boot 本身时,这些依赖项也会以一致的方式升级。

如果需要,您仍然可以指定版本并覆盖 Spring Boot 的建议。

精选列表包含您可以与 Spring Boot 一起使用的所有 Spring 模块以及第三方库。该列表以标准材料清单 ( spring-boot-dependencies ) 的形式提供,可与 MavenGradle 一起使用。

Spring Boot 的每个版本都与 Spring Framework 的基本版本相关联。我们 强烈 建议您不要指定其版本。

1.2. Maven

要了解如何将 Spring Boot 与 Maven 结合使用,请参阅 Spring Boot 的 Maven 插件的文档:

1.3. Gradle

要了解如何将 Spring Boot 与 Gradle 一起使用,请参阅 Spring Boot 的 Gradle 插件的文档:

1.4. Ant

可以使用 Apache Ant + Ivy 构建 Spring Boot 项目。spring-boot-antlib AntLib 模块也可用于帮助 Ant 创建可执行的 jar。

要声明依赖项,典型的 ivy.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 的例子如下所示:

<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.6.7" />

    <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>

如果您不想使用 spring-boot-antlib 模块,请参阅 Build an Executable Archive from Ant without Using spring-boot-antlib

1.5. Starters

Starters 是一组方便的依赖描述符,您可以将其包含在您的应用程序中。您可以获得所需的所有 Spring 和相关技术的一站式支持,而无需搜索示例代码和复制粘贴加载的依赖描述符。例如,如果您想开始使用 Spring 和 JPA 进行数据库访问,请将 spring-boot-starter-data-jpa 依赖项包含在您的项目中。

启动器包含许多依赖项,您需要这些依赖项使项目快速启动并运行,并具有一致的、受支持的托管传递依赖项集。

名称里有什么

所有 官方 启动器都遵循类似的命名模式;spring-boot-starter-* ,其中 * 是特定类型的应用程序。此命名结构旨在帮助您在需要查找启动器时提供帮助。许多 IDE 中的 Maven 集成允许您按名称搜索依赖项。例如,安装了适当的 Eclipse 或 Spring Tools 插件后,您可以在 POM 编辑器中按下 ctrl-space 并键入 spring-boot-starter 以获取完整列表。

正如 “创建您自己的 Starter ” 部分所述,第三方 starter 不应以 spring-boot 开头,因为它是为官方 Spring Boot 工件保留的。相反,第三方启动器通常以项目名称开头。例如,一个名为 thirdpartyproject 的第三方启动器通常被命名为 thirdpartyproject-spring-boot-starter

以下应用程序启动器由 org.springframework.boot group 下的 Spring Boot 提供:

Spring Boot application starters

名称 描述
spring-boot-starter 核心启动器,包括自动配置支持、日志记录和 YAML
spring-boot-starter-activemq 使用 Apache ActiveMQ 进行 JMS 消息传递的启动器
spring-boot-starter-amqp 使用 Spring AMQP 和 Rabbit MQ 的启动器
spring-boot-starter-aop 使用 Spring AOP 和 AspectJ 进行面向切面编程的启动器
spring-boot-starter-artemis 使用 Apache Artemis 的 JMS 消息传递启动器
spring-boot-starter-batch 使用 Spring Batch 的启动器
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 使用带有 Spring Data Redis reactive 和 Lettuce 客户端的 Redis 键值数据存储的启动器
spring-boot-starter-data-rest 使用 Spring Data REST 通过 REST 公开 Spring Data 存储库的启动器
spring-boot-starter-freemarker 使用 FreeMarker 视图构建 MVC Web 应用程序的启动器
spring-boot-starter-groovy-templates 使用 Groovy 模板视图构建 MVC Web 应用程序的启动器
spring-boot-starter-hateoas 使用 Spring MVC 和 Spring HATEOAS 构建基于超媒体的 RESTful Web 应用程序的启动器
spring-boot-starter-integration 使用 Spring Integration 的启动器
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-jpaspring-boot-starter-jdbc
spring-boot-starter-json 读写 json 的启动器
spring-boot-starter-jta-atomikos 使用 Atomikos 进行 JTA 事务的启动器
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 客户端和服务器的启动器
spring-boot-starter-security 使用 Spring Security 的启动器
spring-boot-starter-test 使用包括 JUnit Jupiter、Hamcrest 和 Mockito 在内的库来测试 Spring Boot 应用程序的启动器
spring-boot-starter-thymeleaf 使用 Thymeleaf 视图构建 MVC Web 应用程序的启动器
spring-boot-starter-validation 使用带有 Hibernate Validator 的 Java Bean Validation 的启动器
spring-boot-starter-web 使用 Spring MVC 构建 Web 应用程序的启动器,包括 RESTful 应用程序。使用 Tomcat 作为默认的嵌入式容器
spring-boot-starter-web-services 使用 Spring Web Services 的启动器
spring-boot-starter-webflux 使用 Spring Framework 的反应式 Web 支持构建 WebFlux 应用程序的启动器
spring-boot-starter-websocket 使用 Spring Framework 的 WebSocket 支持构建 WebSocket 应用程序的启动器

除了应用程序启动器之外,以下启动器可用于添加 生产就绪production ready) 功能:

Spring Boot production starters

名称 描述
spring-boot-starter-actuator 使用 Spring Boot 的 Actuator 的 Starter,它提供了生产就绪的特性来帮助你监控和管理你的应用程序

最后,Spring Boot 还包括以下启动器,如果您想排除或切换特定的技术,可以使用它们:

Spring Boot technical starters

名称 描述
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 服务器日志系统 的操作指南文档。

有关 其他社区贡献的启动器 的列表,请参阅 GitHub 上 spring-boot-starters 模块中的 README 文件

2. 构建你的代码

Spring Boot 不需要任何特定的代码布局即可工作。但是,有一些最佳实践会有所帮助。

2.1. 使用 “default” 包

当一个类不包含 package 声明时,它被认为在“默认包”中。通常不鼓励使用“默认包”,应避免使用。它可能会导致使用 @ComponentScan@ConfigurationPropertiesScan@EntityScan@SpringBootApplication 注解的 Spring Boot 应用程序出现特殊问题,因为每个 jar 中的每个类都被读取。

我们建议您遵循 Java 推荐的包命名约定并使用反向域名(例如,com.example.project )。

2.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 文件将声明 main 方法以及 @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);
    }

}

3. 配置类

Spring Boot 支持基于 Java 的配置。尽管可以与 XML 源一起使用 SpringApplication ,但我们通常建议您的主要源是单个 @Configuration 类。通常,定义 main 方法的类是首选的 @Configuration

互联网上已经发布了许多使用 XML 配置的 Spring 配置示例。如果可能,请始终尝试使用等效的基于 Java 的配置。搜索 Enable* 注解可能是一个很好的起点。

3.1. 导入其他配置类

你不需要把你所有的东西都放在一个 @Configuration 类里。@Import 注解可用于导入其他配置类。或者,您可以使用 @ComponentScan 自动获取所有 Spring 组件,包括 @Configuration 类。

3.2. 导入 XML 配置

如果您必须使用基于 XML 的配置,我们建议您仍然从 @Configuration 类开始。然后,您可以使用 @ImportResource 注解来加载 XML 配置文件。

4. 自动配置

Spring Boot 自动配置尝试根据您添加的 jar 依赖项自动配置您的 Spring 应用程序。例如,如果 HSQLDB 在你的类路径上,并且你没有手动配置任何数据库连接 bean ,那么 Spring Boot 会自动配置一个内存数据库。

您需要通过向其中一个 @Configuration 类添加 @EnableAutoConfiguration@SpringBootApplication 注解来选择自动配置。

您应该只添加一个 @SpringBootApplication@EnableAutoConfiguration 注解。我们通常建议您仅将其中一个添加到您的主要 @Configuration 类中。

4.1. 逐步取代自动配置

自动配置是非侵入性的。在任何时候,您都可以开始定义自己的配置来替换自动配置的特定部分。例如,如果您添加自己的 DataSource bean,则默认的嵌入式数据库支持会退出。

如果您需要了解当前正在应用哪些自动配置以及原因,请使用 --debug 开关启动您的应用程序。这样做可以为选择的核心记录器启用调试日志,并将条件报告记录到控制台。

4.2. 禁用特定的自动配置类

如果您发现正在应用您不想要的特定自动配置类,您可以使用 @SpringBootApplicationexclude 属性来禁用它们,如下例所示:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class MyApplication {

}

如果类不在类路径上,您可以使用注解的 excludeName 属性并指定完全限定名称。如果您更喜欢使用 @EnableAutoConfiguration 而不是 @SpringBootApplicationexcludeexcludeName 也可用。最后,您还可以使用 spring.autoconfigure.exclude 属性控制要排除的自动配置类的列表。

您可以在注解级别和使用属性定义排除项。

尽管自动配置类是 public ,但被认为是公共 API 的类的唯一作用是可用于禁用自动配置的类的名称。这些类的实际内容,例如嵌套配置类或 bean 方法仅供内部使用,我们不建议直接使用它们。

5. Spring Beans 和依赖注入

您可以自由使用任何标准 Spring Framework 技术来定义您的 bean 及其注入的依赖项。我们通常建议使用构造函数注入来装配依赖项并使用 @ComponentScan 查找 bean 。

如果您按照上面的建议构建代码(将应用程序类放在顶级包中),您可以添加 @ComponentScan 不带任何参数或使用 @SpringBootApplication 隐式包含它。您的所有应用程序组件( @Component@Service@Repository@Controller 等)都会自动注册为 Spring Bean。

以下示例显示了一个使用构造函数注入来获取所需 RiskAssessor bean 的 @Service bean:

import org.springframework.stereotype.Service;

@Service
public class MyAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

    public MyAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
    }

    // ...

}

如果一个 bean 有多个构造函数,你需要使用 @Autowired 标记你希望 Spring 使用的那个:

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 ,表明它不能随后更改。

6. 使用 @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 的属性。

这些功能都不是强制性的,您可以选择将此单个注解替换为它启用的任何功能。例如,您可能不想在应用程序中使用组件扫描或配置属性扫描:

@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 )。

7. 运行您的应用程序

将应用程序打包为 jar 并使用嵌入式 HTTP 服务器的最大优势之一是,您可以像运行其他应用程序一样运行应用程序。调试 Spring Boot 应用程序也很容易。您不需要任何特殊的 IDE 插件或扩展。

本节仅介绍基于 jar 的打包。如果您选择将应用程序打包为 war 文件,请参阅您的服务器和 IDE 文档。

7.1. 从 IDE 运行

7.2. 作为打包应用程序运行

如果您使用 Spring Boot Maven 或 Gradle 插件创建可执行 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

7.3. 使用 Maven 插件

Spring Boot Maven 插件包含一个可用于快速编译和运行应用程序的 run 目标。应用程序以分解(exploded)的形式运行,就像在您的 IDE 中一样。以下示例显示了运行 Spring Boot 应用程序的典型 Maven 命令:

$ mvn spring-boot:run

您可能还想使用 MAVEN_OPTS 操作系统环境变量,如以下示例所示:

$ export MAVEN_OPTS=-Xmx1024m

7.4. 使用 Gradle 插件

Spring Boot Gradle 插件包括一个 bootRun 任务,可用于以分解的形式运行您的应用程序。每当您应用 org.springframework.bootjava 插件时都会添加 bootRun 任务,如下例所示:

$ gradle bootRun

您可能还想使用 JAVA_OPTS 操作系统环境变量,如以下示例所示:

$ export JAVA_OPTS=-Xmx1024m

7.5. 热插拔(Hot Swapping)

由于 Spring Boot 应用程序是普通的 Java 应用程序,因此 JVM 热交换应该开箱即用。JVM 热交换在某种程度上受限于它可以替换的字节码。对于更完整的解决方案,可以使用 JRebel

spring-boot-devtools 模块还包括对快速应用程序重启的支持。有关详细信息,请参阅 热插拔“操作方法”

8. 开发者工具

Spring Boot 包含一组额外的工具,可以使应用程序开发体验更加愉快。spring-boot-devtools 模块可以包含在任何项目中,以提供额外的开发时功能。要包含 devtools 支持,请将模块依赖项添加到您的构建中,如下面的 Maven 和 Gradle 清单所示:

Maven:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

Gradle:

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 插件时,配置任务的类路径以包含 developmentOnly 配置

8.1. 诊断类加载问题

Restart vs Reload 部分所述,重新启动功能是通过使用两个类加载器实现的。对于大多数应用程序,这种方法效果很好。但是,它有时会导致类加载问题,尤其是在多模块项目中。

要诊断类加载问题是否确实是由 devtools 及其两个类加载器引起的,请 尝试禁用 restart 。如果这解决了您的问题,请 自定义 restart 类加载器 以包含您的整个项目。

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.groovy.template.cache false
spring.h2.console.enabled true
spring.mustache.cache false
spring.mvc.log-resolved-exception true
spring.reactor.debug true
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-propertiesfalse

因为您在开发 Spring MVC 和 Spring WebFlux 应用程序时需要有关 Web 请求的更多信息,所以开发人员工具建议您为 web 日志记录组启用 DEBUG 级别。这将为您提供有关传入请求、正在处理它的处理器、响应结果和其他详细信息。如果您希望记录所有请求详细信息(包括潜在的敏感信息),您可以打开 spring.mvc.log-request-detailsspring.codec.log-request-details 配置属性。

8.3. 自动重启

每当类路径上的文件更改时,应用程序使用 spring-boot-devtools 自动重新启动。在 IDE 中工作时,这可能是一个有用的功能,因为它为代码更改提供了一个非常快速的反馈循环。默认情况下,类路径上指向目录的任何条目都会被监视更改。请注意,某些资源,例如静态资产和视图模板,不需要重新启动应用程序

触发重启

由于 DevTools 监控类路径资源,触发重启的唯一方法是更新类路径。无论您使用的是 IDE 还是其中一个构建插件,都必须重新编译修改后的文件以触发重新启动。更新类路径的方式取决于您使用的工具:

  • 在 Eclipse 中,保存修改后的文件会导致类路径更新并触发重新启动。
  • 在 IntelliJ IDEA 中,构建项目 ( Build +→+ Build Project ) 具有相同的效果。
  • 如果使用构建插件,运行 Maven mvn compile 或 Gradle gradle build 将触发重新启动。

如果您使用构建插件使用 Maven 或 Gradle 重新启动,则必须将 forking 设置保留为 enabled 。如果禁用 forking ,将不会创建 devtools 使用的隔离应用程序类加载器,并且重新启动将无法正常运行。

与 LiveReload 一起使用时,自动重启效果很好。 有关详细信息,请参阅 LiveReload 部分。如果您使用 JRebel,则会禁用自动重新启动以支持动态类重新加载。其他 devtools 功能(例如 LiveReload 和属性覆盖)仍然可以使用。

DevTools 依赖应用程序上下文的关闭挂钩在重新启动期间将其关闭。如果您禁用了关闭挂钩 ( SpringApplication.setRegisterShutdownHook(false) ) ,它将无法正常工作。

DevTools 需要自定义 ApplicationContext 使用的 ResourceLoader 。如果您的应用程序已经提供了一个,它将被包装。不支持 直接覆盖 ApplicationContext 上的 getResource 方法。

使用 AspectJ 编织时不支持自动重启。

重新启动与重新加载

Spring Boot 提供的重启技术通过使用两个类加载器来工作。不会更改的类(例如,来自第三方 jar 的类)被加载到 base 类加载器中。您正在积极开发的类被加载到 restart 类加载器中。当应用程序重新启动时,restart 类加载器被丢弃并创建一个新的。这种方法意味着应用程序重新启动通常比“冷启动”快得多,因为 base 类加载器已经可用并已填充。

如果您发现重新启动对您的应用程序来说不够快,或者您遇到类加载问题,您可以考虑重新加载技术,例如 ZeroTurnaround 的 JRebel 。它通过在加载类时重写类来工作,以使它们更易于重新加载。

8.3.1. 记录条件评估中的变化

默认情况下,每次您的应用程序重新启动时,都会记录显示条件评估增量的报告。该报告显示在您进行更改(例如添加或删除 bean 和设置配置属性)时对应用程序自动配置的更改。

要禁用报告的日志记录,请设置以下属性:

spring.devtools.restart.log-condition-evaluation-delta=false

8.3.2. 排除资源

某些资源在更改时不一定需要触发重新启动。例如,Thymeleaf 模板可以就地编辑。默认情况下,更改 /META-INF/maven , /META-INF/resources , /resources , /static , /public/templates 中的资源不会触发重新启动,但会触发 实时重新加载 。如果要自定义这些排除项,可以使用 spring.devtools.restart.exclude 属性。例如,仅排除 /static/public ,您可以设置:

spring.devtools.restart.exclude=static/**,public/**

如果要保留这些默认值并添加其他排除项,请改用 spring.devtools.restart.additional-exclude 属性。

8.3.3. 监视其他路径

当您对不在类路径上的文件进行更改时,您可能希望重新启动或重新加载您的应用程序。为此,请使用 spring.devtools.restart.additional-paths 属性配置其他路径以监视更改。您可以使用 前面描述spring.devtools.restart.exclude 属性来控制附加路径下的更改是触发完全重新启动还是 实时重新加载

8.3.4. 禁用重启

如果您不想使用重启功能,可以使用 spring.devtools.restart.enabled 属性禁用它。在大多数情况下,您可以在您的 application.properties 中设置此属性(这样做仍然会初始化 restart 类加载器,但它不会监视文件更改)。

如果您需要完全禁用重启支持(例如,因为它不适用于特定库),则需要在调用 SpringApplication.run(…) 之前将 System 属性 spring.devtools.restart.enabled 设置为 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);
    }

}

8.3.5. 使用触发文件

如果您使用持续编译更改文件的 IDE,您可能更愿意仅在特定时间触发重新启动。为此,您可以使用“触发文件”,这是一个特殊文件,当您想要实际触发重新启动检查时必须对其进行修改。

对文件的任何更新都会触发检查,但只有在 Devtools 检测到它有事情要做时才会真正发生重新启动。

要使用触发器文件,请将 spring.devtools.restart.trigger-file 属性设置为触发器文件的名称(不包括任何路径)。触发器文件必须出现在您的类路径中的某处。

例如,如果您有一个具有以下结构的项目:

src
+- main
   +- resources
      +- .reloadtrigger

那么您的 trigger-file 属性将是:

spring.devtools.restart.trigger-file=.reloadtrigger

现在仅在 src/main/resources/.reloadtrigger 更新时才会重新启动。

您可能希望设置 spring.devtools.restart.trigger-file全局设置 ,以便您的所有项目都以相同的方式运行。

某些 IDE 具有使您无需手动更新触发器文件的功能。 Spring Tools for EclipseIntelliJ IDEA(终极版) 都有这样的支持。使用 Spring Tools,您可以使用控制台视图中的“重新加载”按钮(只要您的 trigger-file 名称为 .reloadtrigger )。对于 IntelliJ IDEA,您可以按照其文档中的说明进行操作

8.3.6. 自定义重启类加载器

正如前面在 Restart vs Reload 部分中所描述的,重启功能是通过使用两个类加载器来实现的。如果这会导致问题,您可能需要自定义由哪个类加载器加载的内容。

默认情况下,IDE 中任何打开的项目都使用 restart 类加载器加载,任何常规 .jar 文件都使用 base 类加载器加载。如果您使用 mvn spring-boot:rungradle bootRun 也是如此:包含您的 @SpringBootApplication 的项目使用 restart 类加载器加载,其他所有内容都使用 base 类加载器加载。

您可以通过创建 META-INF/spring-devtools.properties 文件来指示 Spring Boot 使用不同的类加载器加载项目的一部分。spring-devtools.properties 文件可以包含以 restart.excluderestart.include 为前缀的属性。include 元素是应该被拉入 restart 类加载器的项目,exclude 元素是应该被推入 base 类加载器的项目。该属性的值是应用于类路径的正则表达式模式,如以下示例所示:

restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\\.]+\\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\\.]+\\.jar

所有属性键都必须是唯一的。只要一个属性以 restart.include.restart.exclude. 开头就被考虑。

类路径中的所有 META-INF/spring-devtools.properties 内容都会被加载。您可以在项目中或项目使用的库中打包文件。

8.3.7. 已知限制

重新启动功能不适用于使用标准 ObjectInputStream 反序列化的对象。如果需要反序列化数据,可能需要结合使用 Spring 的 ConfigurableObjectInputStreamThread.currentThread().getContextClassLoader()

不幸的是,一些第三方库在不考虑上下文类加载器的情况下反序列化。如果您发现这样的问题,您需要向原作者请求修复。

8.4. 实时重载

spring-boot-devtools 模块包括一个嵌入式 LiveReload 服务器,可用于在资源更改时触发浏览器刷新。LiveReload 浏览器扩展可从 livereload.com 免费获得,适用于 Chrome、Firefox 和 Safari 。

如果您不想在应用程序运行时启动 LiveReload 服务器,您可以将 spring.devtools.livereload.enabled 属性设置为 false

您一次只能运行一个 LiveReload 服务器。在启动您的应用程序之前,请确保没有其他 LiveReload 服务器正在运行。如果您从 IDE 启动多个应用程序,则只有第一个具有 LiveReload 支持。

要在文件更改时触发 LiveReload,必须启用 自动重启

8.5. 全局设置

您可以通过将以下任何文件添加到 $HOME/.config/spring-boot 目录来配置全局 devtools 设置:

  1. spring-boot-devtools.properties
  2. spring-boot-devtools.yaml
  3. spring-boot-devtools.yml

添加到这些文件的任何属性都适用于您机器上使用 devtools 的所有 Spring Boot 应用程序。例如,要将重新启动配置为始终使用触发器文件,您可以将以下属性添加到 spring-boot-devtools 文件中:

spring.devtools.restart.trigger-file=.reloadtrigger

默认情况下,$HOME 是用户的主目录。要自定义此位置,请设置 SPRING_DEVTOOLS_HOME 环境变量或 spring.devtools.home 系统属性。

如果在 $HOME/.config/spring-boot 中找不到 devtools 配置文件,则会在 $HOME 目录的根目录中搜索 .spring-boot-devtools.properties 文件是否存在。这允许您与不支持 $HOME/.config/spring-boot 位置的旧版 Spring Boot 上的应用程序共享 devtools 全局配置。

devtools 属性 properties/yaml 文件中不支持 profile 。

任何在 .spring-boot-devtools.properties 中激活的 profile 都不会影响 特定 profile 配置文件 的加载。不支持 YAML 和属性文件中的特定 profile 的文件名( spring-boot-devtools-<profile>.properties 的形式)和 spring.config.activate.on-profile 文档 。

8.5.1. 配置文件系统监视器

FileSystemWatcher 的工作原理是按特定时间间隔轮询类更改,然后等待预定义的静默期以确保没有更多更改。由于 Spring Boot 完全依赖 IDE 来编译文件并将其复制到 Spring Boot 可以读取它们的位置,因此您可能会发现有时某些更改在 devtools 重新启动应用程序时不会反映出来。如果您经常观察到此类问题,请尝试将 spring.devtools.restart.poll-intervalspring.devtools.restart.quiet-period 参数增加到适合您的开发环境的值:

spring.devtools.restart.poll-interval=2s
spring.devtools.restart.quiet-period=1s

现在每 2 秒轮询一次受监视的类路径目录以进行更改,并保持 1 秒的静默期以确保没有额外的类更改。

8.6. 远程应用程序

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 属性。与任何重要的密码或秘密一样,该值应该是唯一且强大的,以至于无法猜测或暴力破解。

远程 devtools 支持分两部分提供:接受连接的服务器端端点和在 IDE 中运行的客户端应用程序。设置 spring.devtools.remote.secret 属性时,服务器组件会自动启用。客户端组件必须手动启动。

Spring WebFlux 应用程序不支持远程开发工具。

8.6.1. 运行远程客户端应用程序

远程客户端应用程序旨在从您的 IDE 中运行。您需要使用与您连接到的远程项目相同的类路径运行 org.springframework.boot.devtools.RemoteSpringApplication 。应用程序的唯一必需参数是它连接到的远程 URL。

例如,如果您正在使用 Eclipse 或 Spring Tools ,并且您有一个名为 my-app 的项目已部署到 Cloud Foundry,您将执行以下操作:

  • Run 菜单中选择 Run Configurations…
  • 创建一个新的 Java Application “启动配置”
  • 浏览 my-app 项目
  • org.springframework.boot.devtools.RemoteSpringApplication 作主类
  • 添加 https://myapp.cfapps.ioProgram arguments (或任何您的远程 URL)

正在运行的远程客户端可能类似于以下列表:

  .   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: Spring Boot Remote :: 2.6.7

2015-06-10 18:25:06.632  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/spring-boot-project/spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code)
2015-06-10 18:25:06.671  INFO 14938 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
2015-06-10 18:25:07.043  WARN 14938 --- [           main] o.s.b.d.r.c.RemoteClientConfiguration    : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2015-06-10 18:25:07.074  INFO 14938 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2015-06-10 18:25:07.130  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)

因为远程客户端使用与真实应用程序相同的类路径,所以它可以直接读取应用程序属性。这是读取 spring.devtools.remote.secret 属性并将其传递给服务器进行身份验证的方式。

始终建议将 https:// 用作连接协议,以便对流量进行加密并且无法截获密码。

如果您需要使用代理访问远程应用程序,请配置 spring.devtools.remote.proxy.hostspring.devtools.remote.proxy.port 属性。

8.6.2. 远程更新

远程客户端以与本地重新启动 相同的方式监视您的应用程序类路径的更改。任何更新的资源都会被推送到远程应用程序并触发重新启动(如果需要)。如果您迭代使用本地没有的云服务的功能,这会很有帮助。通常,远程更新和重新启动比完整的重建和部署周期快得多。

在较慢的开发环境上,可能会出现静默期不够,类的变化可能会分批进行。上传第一批类更改后,服务器会重新启动。下一批无法发送到应用程序,因为服务器正在重新启动。

这通常表现为 RemoteSpringApplication 日志中有关未能上传某些类的警告以及随后的重试。但这也可能导致应用程序代码不一致,在第一批更改上传后无法重启。如果您经常观察到此类问题,请尝试将 spring.devtools.restart.poll-intervalspring.devtools.restart.quiet-period 参数增加到适合您的开发环境的值。请参阅 配置文件系统监视器 部分以配置这些属性。

只有在远程客户端运行时才会监控文件。如果您在启动远程客户端之前更改了文件,则不会将其推送到远程服务器。

9. 打包您的生产应用程序

可执行 jar 可用于生产部署。由于它们是独立的,因此它们也非常适合基于云的部署。

对于其他“生产就绪”功能,例如健康检查、审计和 metrics REST 或 JMX 端点,请考虑添加 spring-boot-actuator 。有关详细信息,请参见 actuator.html

posted @   流星<。)#)))≦  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示