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

如果您刚开始使用Spring Boot,您可能应该先阅读 入门指南,然后再深入阅读本节内容。

1. 构建系统

强烈建议您选择一个支持依赖管理并且可以消费发布到“Maven中央仓库”的构建系统。我们建议您选择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

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

1.3. Gradle

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

1.4. Ant

可以使用Apache Ant+Ivy构建Spring Boot项目。还提供了“AntLib”模块spring-boot-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="编译此模块所需的所有内容" />
        <conf name="runtime" extends="compile" description="运行此模块所需的所有内容" />
    </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="3.2.3" />

    <target name="resolve" description="--> 使用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="编译">
        <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模块,请参阅howto.html中的“如何”。

1.5. 启动器

启动器是一组方便的依赖描述符,您可以将其包含在应用程序中。您可以一站式获取所有Spring和相关技术,而无需查找示例代码并复制粘贴大量依赖描述符。例如,如果您想要开始使用Spring和JPA进行数据库访问,请在项目中包含spring-boot-starter-data-jpa依赖。

启动器包含许多您需要快速启动项目并具有一组一致、受支持的托管传递依赖项的依赖项。

名字的含义

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

如“创建您自己的启动器”部分所解释的,第三方启动器不应以spring-boot开头,因为该名称保留给官方Spring Boot构件。相反,第三方启动器通常以项目名称开头。例如,名为thirdpartyproject的第三方启动器项目通常被命名为thirdpartyproject-spring-boot-starter

Spring Boot在org.springframework.boot组下提供了以下应用程序启动器:

表1. Spring Boot 应用程序启动器
名称 描述

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的缓存支持的启动器

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

用于使用Spring与Apache Pulsar的启动器

spring-boot-starter-pulsar-reactive

用于使用Spring与Apache Pulsar Reactive的启动器

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验证的启动器

spring-boot-starter-web

用于使用Spring MVC构建Web(包括RESTful)应用程序的启动器。默认使用Tomcat作为嵌入式容器

spring-boot-starter-web-services

用于使用Spring Web Services的启动器

spring-boot-starter-webflux

用于使用Spring Framework的Reactive Web支持构建WebFlux应用程序的启动器

spring-boot-starter-websocket

用于使用Spring Framework的MVC WebSocket支持构建WebSocket应用程序的启动器

除了应用程序启动器之外,还可以使用以下启动器来添加生产就绪功能:

表2. Spring Boot生产启动器
名称 描述

spring-boot-starter-actuator

用于使用Spring Boot的Actuator的启动器,提供生产就绪功能,帮助您监视和管理应用程序

最后,Spring Boot还包括以下启动器,如果您想要排除或交换特定的技术方面,则可以使用:

表3. Spring Boot技术启动器
名称 描述

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不需要任何特定的代码布局即可工作。但是,有一些最佳实践可以帮助。

如果您希望基于域强制执行结构,请查看 Spring Modulith

2.1. 使用“default”包

当一个类不包含package声明时,它被视为在“default包”中。通常不建议使用“default包”,应该避免使用。对于使用@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,如下所示:

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

3. 配置类

Spring Boot偏爱基于Java的配置。虽然可以使用SpringApplication与XML源,但我们通常建议您的主要源是单个@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. 禁用特定的自动配置类

如果发现应用了您不想要的特定自动配置类,您可以使用@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

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

您可以在注解级别和使用属性的方式定义排除项。
尽管自动配置类是public的,但被视为公共API的仅是类的名称,可用于禁用自动配置。这些类的实际内容,如嵌套配置类或bean方法,仅供内部使用,我们不建议直接使用。

4.3. 自动配置包

自动配置包是各种自动配置功能在默认情况下查找实体和Spring Data存储库等内容时查找的包。@EnableAutoConfiguration注解(直接或通过其在@SpringBootApplication上的存在)确定默认的自动配置包。可以使用@AutoConfigurationPackage注解配置其他包。

5. Spring Beans和依赖注入

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

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

以下示例显示了一个使用构造函数注入获取所需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有多个构造函数,您需要使用@Autowired标记您希望Spring使用的构造函数:

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
    }

    // ...

}
注意使用构造函数注入使riskAssessor字段标记为final,表示它不能被后续更改。

6. 使用 @SpringBootApplication 注解

许多 Spring Boot 开发者喜欢他们的应用程序使用自动配置、组件扫描,并能够在“应用程序类”上定义额外的配置。一个单独的 @SpringBootApplication 注解可以用来启用这三个特性,即:

  • @EnableAutoConfiguration: 启用 Spring Boot 的自动配置机制

  • @ComponentScan: 在应用程序所在的包上启用 @Component 扫描(参见 最佳实践

  • @SpringBootConfiguration: 启用在上下文中注册额外的 bean 或导入额外的配置类。这是 Spring 标准 @Configuration 的替代方案,有助于在集成测试中检测配置

Java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

// 等同于 @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

// 等同于 @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan
@SpringBootApplication
class MyApplication

fun main(args: Array<String>) {
    runApplication<MyApplication>(*args)
}
@SpringBootApplication 还提供了别名,用于自定义 @EnableAutoConfiguration@ComponentScan 的属性。

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

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

在这个例子中,MyApplication 就像任何其他 Spring Boot 应用程序一样,只是不会自动检测 @Component 注解的类和 @ConfigurationProperties 注解的类,用户定义的 bean 需要显式导入(参见 @Import)。

7. 运行您的应用程序

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

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

7.1. 从IDE中运行

您可以从IDE中将Spring Boot应用程序作为Java应用程序运行。但是,您首先需要导入您的项目。导入步骤取决于您的IDE和构建系统。大多数IDE可以直接导入Maven项目。例如,Eclipse用户可以从“文件”菜单中选择导入…​现有的Maven项目

如果您无法直接将项目导入IDE,则可以使用构建插件生成IDE元数据。Maven包含用于EclipseIDEA的插件。Gradle为各种IDE提供插件。

如果意外运行了两次Web应用程序,则会看到“端口已被使用”错误。Spring Tools用户可以使用重新启动按钮而不是运行按钮,以确保关闭任何现有实例。

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

如果您使用Spring Boot Maven或Gradle插件创建可执行jar文件,则可以使用java -jar运行您的应用程序,如下例所示:

$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar

还可以启用远程调试支持来运行打包的应用程序。这样做可以让您附加调试器到您的打包应用程序,如下例所示:

$ java -agentlib:jdwp=server=y,transport=dt_socket,address=8000,suspend=n \
       -jar target/myapplication-0.0.1-SNAPSHOT.jar

7.3. 使用Maven插件

Spring Boot Maven插件包括一个run目标,可用于快速编译和运行您的应用程序。应用程序以展开形式运行,就像在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. 热交换

由于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. 诊断类加载问题

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

要诊断是否由 devtools 及其两个类加载器引起的类加载问题,尝试禁用重启。如果这解决了你的问题,定制重启类加载器 来包含整个项目。

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.docker.compose.readiness.wait

only-if-started

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-detailsspring.codec.log-request-details 配置属性。

8.3. 自动重启

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

触发重启

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

  • 在Eclipse中,保存修改后的文件会导致类路径更新并触发重启。

  • 在IntelliJ IDEA中,构建项目(Build +→+ Build Project)具有相同的效果。

  • 如果使用构建插件,运行mvn compile(Maven)或gradle build(Gradle)将触发重启。

如果您使用Maven或Gradle与构建插件进行重启,必须将forking设置为enabled。如果禁用分叉,DevTools使用的隔离应用程序类加载器将不会被创建,重启将无法正常运行。
与LiveReload一起使用时,自动重启效果非常好。有关详细信息,请参阅LiveReload部分。如果您使用JRebel,则会禁用自动重启,而是使用动态类重新加载。其他DevTools功能(如LiveReload和属性覆盖)仍然可以使用。
DevTools依赖于应用程序上下文的关闭挂钩在重启期间关闭它。如果您已禁用关闭挂钩(SpringApplication.setRegisterShutdownHook(false)),它将无法正常工作。
DevTools需要自定义ApplicationContext使用的ResourceLoader。如果您的应用程序已经提供了一个,它将被包装。不支持直接覆盖ApplicationContext上的getResource方法。
在使用AspectJ织入时不支持自动重启。
重启与重新加载

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

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

8.3.1. 记录条件评估的更改

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

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

属性
spring.devtools.restart.log-condition-evaluation-delta=false
Yaml
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/**
Yaml
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中设置此属性(这样做仍会初始化重启类加载器,但不会监视文件更改)。

如果需要完全禁用重启支持(例如,因为它与特定库不兼容),您需要在调用SpringApplication.run(…​)之前将spring.devtools.restart.enabled System属性设置为false,如下例所示:

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

}

8.3.5. 使用触发文件

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

对文件的任何更新都将触发检查,但只有在Devtools检测到有事情要做时才会实际发生重启。
spring.devtools.restart.trigger-file属性设置为触发文件的名称(不包括任何路径)。触发文件必须出现在类路径的某个位置。

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

src
+- main
   +- resources
      +- .reloadtrigger

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

属性
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 EclipseIntelliJ IDEA(旗舰版) 都具有此类支持。使用Spring Tools,您可以从控制台视图中使用“重新加载”按钮(只要您的trigger-file命名为.reloadtrigger)。对于IntelliJ IDEA,您可以按照他们文档中的说明进行操作。

8.3.6. 自定义重启类加载器

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

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

您可以通过创建一个META-INF/spring-devtools.properties文件来指示Spring Boot使用不同的类加载器加载项目的部分内容。 spring-devtools.properties文件可以包含以restart.excluderestart.include为前缀的属性。 include元素是应该提升到“重启”类加载器中的项目,而exclude元素是应该推送到“基本”类加载器中的项目。属性的值是应用于类路径的正则表达式模式,如下例所示:

属性
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"
所有属性键必须是唯一的。只要属性以restart.include.restart.exclude.开头,它就会被考虑。
类路径中加载所有META-INF/spring-devtools.properties。您可以将文件打包到项目内部或项目消耗的库中。

8.3.7. 已知限制

重启功能与使用标准ObjectInputStream进行反序列化的对象不兼容。如果您需要反序列化数据,可能需要结合使用Spring的ConfigurableObjectInputStreamThread.currentThread().getContextClassLoader()

不幸的是,有几个第三方库在反序列化时没有考虑上下文类加载器。如果您发现此类问题,您需要向原始作者请求修复。

8.4. LiveReload

spring-boot-devtools模块包含一个内置的LiveReload服务器,可用于在资源更改时触发浏览器刷新。Chrome、Firefox和Safari都可以免费获得LiveReload浏览器扩展。您可以通过在所选浏览器的市场或商店中搜索“LiveReload”来找到这些扩展。

如果您不希望在应用程序运行时启动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
Yaml
spring:
  devtools:
    restart:
      trigger-file: ".reloadtrigger"

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

如果在$HOME/.config/spring-boot中找不到devtools配置文件,则会在$HOME目录的根目录中搜索.spring-boot-devtools.properties文件的存在。这使您可以与运行较旧版本Spring Boot且不支持$HOME/.config/spring-boot位置的应用程序共享devtools全局配置。

devtools属性/yaml文件不支持配置文件。

.spring-boot-devtools.properties中激活的任何配置文件都不会影响加载特定配置文件。不支持特定配置文件名(形式为spring-boot-devtools-<profile>.properties)和YAML和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
Yaml
spring:
  devtools:
    restart:
      poll-interval: "2s"
      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应用程序不支持远程devtools。

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.io添加到Program arguments(或您的远程URL)。

运行中的远程客户端可能类似于以下清单:

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

2024-02-22T18:33:07.762Z  INFO 34942 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication v3.2.3 using Java 17.0.10 with PID 34942 (/Users/myuser/.m2/repository/org/springframework/boot/spring-boot-devtools/3.2.3/spring-boot-devtools-3.2.3.jar started by myuser in /opt/apps/)
2024-02-22T18:33:07.766Z  INFO 34942 --- [           main] o.s.b.devtools.RemoteSpringApplication   : No active profile set, falling back to 1 default profile: "default"
2024-02-22T18:33:08.081Z  INFO 34942 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2024-02-22T18:33:08.116Z  INFO 34942 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 0.786 seconds (process running for 1.137)
由于远程客户端使用与真实应用程序相同的类路径,因此可以直接读取应用程序属性。这就是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包可用于生产部署。由于它们是自包含的,因此它们也非常适合基于云的部署。

对于额外的“生产就绪”功能,例如健康、审计和度量的REST或JMX端点,请考虑添加 spring-boot-actuator。有关详细信息,请参阅 actuator.html

10. 接下来阅读什么

您现在应该了解如何使用Spring Boot以及应该遵循的一些最佳实践。您现在可以深入了解特定的 Spring Boot功能,或者您可以直接阅读有关Spring Boot“生产就绪”方面的内容。