本站(springdoc.cn)中的内容来源于 spring.io ,原始版权归属于 spring.io。由 springdoc.cn 进行翻译,整理。可供个人学习、研究,未经许可,不得进行任何转载、商用或与之相关的行为。 商标声明:Spring 是 Pivotal Software, Inc. 在美国以及其他国家的商标。

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

如果你刚开始使用Spring Boot,在进入本节之前,你应该先阅读 入门 指南。

1. 构建系统

强烈建议你选择一个支持依赖管理的构建系统,并且它可以从 “Maven Central” 拉取依赖。我们建议你选择Maven或Gradle。选择其他构建系统(例如Ant),也不是不行,但它们的支持并不特别好。

1.1. 依赖管理

Spring Boot的每个版本都提供了一个它所支持的依赖的列表。 在实践中,你不需要在构建配置中为这些依赖声明版本,因为Spring Boot会帮你管理这些。 当你升级Spring Boot本身时,这些依赖也会一同升级。

你仍然可以指定某个依赖的版本,来覆盖spring boot默认的版本。

这份精心策划依赖清单包含了所有可以在Spring Boot中使用的Spring模块,以及一份第三方库的列表。该列表以依赖( spring-boot-dependencies )的形式提供,可在MavenGradle中使用。

Spring Boot的每个版本都与Spring框架的基本版本有关。 我们 强烈建议 你不要修改Spring的版本。

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项目。 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="3.2.0-SNAPSHOT" />

    <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 模块,请参阅 “How-to”

1.5. Starter

Starter是一系列开箱即用的依赖,你可以在你的应用程序中导入它们。 通过你Starter,可以获得所有你需要的Spring和相关技术的一站式服务,免去了需要到处大量复制粘贴依赖的烦恼。 例如,如果你想开始使用Spring和JPA进行数据库访问,那么可以直接在你的项目中导入 spring-boot-starter-data-jpa 依赖。

Starter含了很多你需要的依赖,以使项目快速启动和运行,并拥有一套一致的、受支持的可管理的过渡性依赖。

关于Starter的命名

所有官方的Starter都遵循一个类似的命名模式;spring-boot-starter-*,其中 * 是一个特定类型的应用程序。 这种命名结构是为了在你需要寻找Starter时提供帮助。 许多IDE中集成的Maven可以让你按名称搜索依赖。 例如,如果安装了相应的Eclipse或Spring Tools插件,你可以在POM编辑器中按下 ctrl-space ,然后输入 “spring-boot-starter” 来获取完整的列表。

正如 “创建你自己的 Starter” 一节所解释的,第三方启动器不应该以 spring-boot 开头,因为它是留给Spring Boot官方组件的。 相反,第三方启动器通常以项目的名称开始。 例如,一个名为 thirdpartyproject 的第三方启动器项目通常被命名为 thirdpartyproject-spring-boot-starter

以下是Spring Boot在 org.springframework.boot 这个 groupId 下提供的starter组件。

Table 1. Spring Boot 应用 starter
Name Description

spring-boot-starter

Core starter, including auto-configuration support, logging and YAML

spring-boot-starter-activemq

Starter for JMS messaging using Apache ActiveMQ

spring-boot-starter-amqp

Starter for using Spring AMQP and Rabbit MQ

spring-boot-starter-aop

Starter for aspect-oriented programming with Spring AOP and AspectJ

spring-boot-starter-artemis

Starter for JMS messaging using Apache Artemis

spring-boot-starter-batch

Starter for using Spring Batch

spring-boot-starter-cache

Starter for using Spring Framework’s caching support

spring-boot-starter-data-cassandra

Starter for using Cassandra distributed database and Spring Data Cassandra

spring-boot-starter-data-cassandra-reactive

Starter for using Cassandra distributed database and Spring Data Cassandra Reactive

spring-boot-starter-data-couchbase

Starter for using Couchbase document-oriented database and Spring Data Couchbase

spring-boot-starter-data-couchbase-reactive

Starter for using Couchbase document-oriented database and Spring Data Couchbase Reactive

spring-boot-starter-data-elasticsearch

Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch

spring-boot-starter-data-jdbc

Starter for using Spring Data JDBC

spring-boot-starter-data-jpa

Starter for using Spring Data JPA with Hibernate

spring-boot-starter-data-ldap

Starter for using Spring Data LDAP

spring-boot-starter-data-mongodb

Starter for using MongoDB document-oriented database and Spring Data MongoDB

spring-boot-starter-data-mongodb-reactive

Starter for using MongoDB document-oriented database and Spring Data MongoDB Reactive

spring-boot-starter-data-neo4j

Starter for using Neo4j graph database and Spring Data Neo4j

spring-boot-starter-data-r2dbc

Starter for using Spring Data R2DBC

spring-boot-starter-data-redis

Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client

spring-boot-starter-data-redis-reactive

Starter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce client

spring-boot-starter-data-rest

Starter for exposing Spring Data repositories over REST using Spring Data REST and Spring MVC

spring-boot-starter-freemarker

Starter for building MVC web applications using FreeMarker views

spring-boot-starter-graphql

Starter for building GraphQL applications with Spring GraphQL

spring-boot-starter-groovy-templates

Starter for building MVC web applications using Groovy Templates views

spring-boot-starter-hateoas

Starter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS

spring-boot-starter-integration

Starter for using Spring Integration

spring-boot-starter-jdbc

Starter for using JDBC with the HikariCP connection pool

spring-boot-starter-jersey

Starter for building RESTful web applications using JAX-RS and Jersey. An alternative to spring-boot-starter-web

spring-boot-starter-jooq

Starter for using jOOQ to access SQL databases with JDBC. An alternative to spring-boot-starter-data-jpa or spring-boot-starter-jdbc

spring-boot-starter-json

Starter for reading and writing json

spring-boot-starter-mail

Starter for using Java Mail and Spring Framework’s email sending support

spring-boot-starter-mustache

Starter for building web applications using Mustache views

spring-boot-starter-oauth2-authorization-server

Starter for using Spring Authorization Server features

spring-boot-starter-oauth2-client

Starter for using Spring Security’s OAuth2/OpenID Connect client features

spring-boot-starter-oauth2-resource-server

Starter for using Spring Security’s OAuth2 resource server features

spring-boot-starter-quartz

Starter for using the Quartz scheduler

spring-boot-starter-rsocket

Starter for building RSocket clients and servers

spring-boot-starter-security

Starter for using Spring Security

spring-boot-starter-test

Starter for testing Spring Boot applications with libraries including JUnit Jupiter, Hamcrest and Mockito

spring-boot-starter-thymeleaf

Starter for building MVC web applications using Thymeleaf views

spring-boot-starter-validation

Starter for using Java Bean Validation with Hibernate Validator

spring-boot-starter-web

Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container

spring-boot-starter-web-services

Starter for using Spring Web Services

spring-boot-starter-webflux

Starter for building WebFlux applications using Spring Framework’s Reactive Web support

spring-boot-starter-websocket

Starter for building WebSocket applications using Spring Framework’s MVC WebSocket support

除了应用starter外,以下启动器可用于添加 生产就绪 功能。

Table 2. Spring Boot 生产(环境) starter
Name Description

spring-boot-starter-actuator

Starter for using Spring Boot’s Actuator which provides production ready features to help you monitor and manage your application

最后,Spring Boot还包括以下starter,如果你想排除或更换特定的技术实现,那么可以使用它们。

Table 3. Spring Boot 技术(实现) starter
Name Description

spring-boot-starter-jetty

Starter for using Jetty as the embedded servlet container. An alternative to spring-boot-starter-tomcat

spring-boot-starter-log4j2

Starter for using Log4j2 for logging. An alternative to spring-boot-starter-logging

spring-boot-starter-logging

Starter for logging using Logback. Default logging starter

spring-boot-starter-reactor-netty

Starter for using Reactor Netty as the embedded reactive HTTP server.

spring-boot-starter-tomcat

Starter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web

spring-boot-starter-undertow

Starter for using Undertow as the embedded servlet container. An alternative to spring-boot-starter-tomcat

要学习如何更换技术实现,请看更换WEB服务器日志系统的操作文档。

有关其他社区贡献的starter列表,请参见GitHub上 spring-boot-starters 模块的 README 文件

2. 代码结构

Spring Boot对代码的布局,没有特别的要求。 但是,有一些最佳实践。

2.1. “default” 包

当一个类不包括 package 的声明时,它被认为是在 “default package” 中。 通常应避免使 “default package”。 对于使用了 @ComponentScan, @ConfigurationPropertiesScan, @EntityScan 或者 @SpringBootApplication 注解的Spring Boot应用程序来说,它可能会造成一个问题:项目中的所有jar里面的所有class都会被读取(扫描)。

我们建议你遵循Java推荐的包的命名惯例,使用域名反转作为包名(例如, com.example.project)。

2.2. 启动类的位置

我们通常建议你将你启动类放在一个根package中,高于其他的类,@SpringBootApplication 注解一般都是注解在启动类上的。它默认会扫描当前类下的所有子包。例如,如果你正在编写一个JPA应用程序,你的 @Entity 类只有定义在启动类的子包下才能被扫描加载到。这样的好处也显而易见,@SpringBootApplication 默认只会扫描加载你项目工程中的组件。

如果你不想使用 @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. Configuration 类

Spring Boot倾向于通过Java代码来进行配置的定义。 虽然也可以使用XML来配置 SpringApplication ,但还是建议你通过 @Configuration 类来进行配置。 通常,可以把启动类是作为主要的 @Configuration 类。

网上有很多关于“通过XML配置Spring”的示例,如果可以的话,还是尽量使用Java代码的方式来实现相同的配置。你可以尝试着搜索 Enable* 注解。

3.1. 导入额外的 Configuration 类

你不需要把所有的 @Configuration 放在一个类中。 @Import 注解可以用来导入额外的配置类。 另外,你可以使用 @ComponentScan 来自动扫描加载所有Spring组件,包括 @Configuration 类。

3.2. 导入 XML Configuration

如果你确实需要使用基于XML的配置,我们建议你仍然从 @Configuration 类开始,然后通过 @ImportResource 注解来加载XML配置文件。

4. 自动装配(配置)

Spring Boot的自动装配机制会试图根据你所添加的依赖来自动配置你的Spring应用程序。 例如,如果你添加了 HSQLDB 依赖,而且你没有手动配置任何DataSource Bean,那么Spring Boot就会自动配置内存数据库。

你需要将 @EnableAutoConfiguration@SpringBootApplication 注解添加到你的 @Configuration 类中,从而开启自动配置功能。

你应该只添加一个 @SpringBootApplication@EnableAutoConfiguration 注解。 建议添加到主要的 @Configuration 类上。

4.1. 逐步取代自动配置

自动配置是非侵入性的。 在任何时候,你都可以开始定义你自己的配置来取代自动配置的特定部分。 例如,如果你添加了你自己的 DataSource bean,默认的嵌入式数据库支持就会“退步”从而让你的自定义配置生效。

如果你想知道在应用中使用了哪些自动配置,你可以在启动命令后添加 --debug 参数。 这个参数会为核心的logger开启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

如果要禁用的自动装配类不在classpath上(没有导入),那么你可以在注解的 excludeName 属性中指定类的全路径名称。 excludeexcludeName 属性在 @EnableAutoConfiguration 中也可以使用。 最后,你也可以在配置文件中通过 spring.autoconfigure.exclude[] 配置来定义要禁用的自动配置类列表。

你可以同时使用注解 + 配置的方式来禁用自动装配类。
自动配置类一般都是 public 的,除了这个类的名称以外(用来禁用它)的任何东西,例如它的方法和属性,包括嵌套的配置类。都不建议你去使用。

5. Spring Bean 和 依赖注入

你可以使用任何标准的Spring技术来定义你的Bean以及依赖注入关系。 推荐使用构造函数注入,并使用 @ComponentScan 注解来扫描Bean。

如果你按照上面的建议构造你的代码(将你的启动类定位在顶级包中),你可以在启动类添加 @ComponentScan 注解,也不需要定义它任何参数, 你的所有应用组件(@Component@Service@Repository@Controller 和其他)都会自动注册为Spring Bean。

也可以直接使用 @SpringBootApplication 注解(该注解已经包含了 @ComponentScan)。

下面的例子展示了一个 @Service Bean,它使用构造器注入的方式注入了 RiskAssessor 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,表示一旦Bean创建这个字段就不被改变了。这也是我们推荐的做法。

6. 使用 @SpringBootApplication 注解

许多Spring Boot开发者希望他们的应用程序能够使用自动配置、组件扫描,并且能够在他们的 "application class "上定义额外的配置。 一个 @SpringBootApplication 注解就可以用来启用这三个功能,如下。

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

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

  • @SpringBootConfiguration:允许在Context中注册额外的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)
}
@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文件,请参阅你所使用的Server和IDE的文档。

7.1. 在IDE中运行应用

你可以在IDE中像运行普通Java程序一样运行你的Spring Boot应用。 不过,你首先需要导入你的项目。 不同的IDE导入方式可能不同, 大多数IDE可以直接导入Maven项目。 例如,Eclipse用户可以从 File 菜单中选择 Import…​Existing Maven Projects

如果你不能直接将项目导入IDE,你可以通过构建插件来生成IDE的元数据。包括用于 EclipseIDEA 的 Maven 插件。Gradle为各种 IDE 都提供了插件。

如果你不小心把一个Web应用程序运行了两次,你会看到 “Port already in use” 这个异常提示。 Spring Tools用户可以使用 Relaunch 按钮而不是 Run 按钮来实现“重启”(如果程序已经在运行,那么会先关闭它再启动)。

7.2. 运行打包后的应用

如果你使用Spring Boot的Maven或Gradle插件来创建可执行jar,你可以使用 java -jar 来运行你的打包后应用程序,如下例所示。

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

打包后的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 目标(goal),可用于快速编译和运行你的应用程序。 应用程序以 exploded 的形式运行,就像在IDE中一样。 运行Spring Boot应用的Maven命令如下。

$ mvn spring-boot:run

如果项目的构建需要消耗很大的内存,你可以考虑使用 MAVEN_OPTS 环境变量来修改最大内存,参考如下。

$ export MAVEN_OPTS=-Xmx1024m

7.4. 使用 Gradle 插件

Spring Boot Gradle插件还包括一个 bootRun 任务,可以用来以 exploded 的形式运行你的应用程序。 只要你应用了了 org.springframework.bootjava 插件,就会添加 bootRun 任务,如下例所示。

$ gradle bootRun

同上,如果Gradle构建项目出现内存不足,可以通过 JAVA_OPTS 环境变量来增加JVM的内存。

$ export JAVA_OPTS=-Xmx1024m

7.5. 热部署(Hot Swapping)

由于Spring Boot应用程序是普通的Java应用程序,JVM的热替换功能可以直接使用。但是,JVM的热替换能替换的字节码有限。要想获得更完整的解决方案,可以使用 JRebel

spring-boot-devtools 模块提供了快速重启应用程序的支持。详情请见 热部署 “How-to”

8. 开发者工具(Developer Tools)

Spring Boot 提供了一套额外的工具,可以让你更加愉快的开发应用。 spring-boot-devtools 模块可以包含在任何项目中,以在开发期间提供一些有用的特性。 要使用devtools,请添加以下依赖到项目中。

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 启动的,或者是从一个特殊的classloader启动的,那么它就被认为是一个 "生产级别的应用程序",开发者工具会被自动禁用。 你可以通过 spring.devtools.restart.enabled 配置属性来控制这一行为。 要启用devtools,无论用于启动应用程序的类加载器是什么,请设置启动参数 -Dspring.devtools.restart.enabled=true 。 在生产环境中不能这样做,因为运行devtools会有安全风险。 要禁用devtools,请删除该依赖或者设置启动参数 -Dspring.devtools.restart.enabled=false
应该在Maven中把这个依赖的scope标记为 optional,或在Gradle中使用 developmentOnly 配置(如上所示)。以防止使用你的项目的其他模块,传递地依赖了devtools。
重新打包的压缩文件默认不包含devtools。如果你想使用某个远程devtool功能,,你需要包含它。使用Maven插件时,将 excludeDevtools 属性设为false。使用Gradle插件时, 配置任务的classpath,使其包括 developmentOnly 配置

8.1. 诊断类加载问题

重启 Vs 重载 一节所述,重启功能是通过使用两个classloader实现的。 对于大多数应用程序来说,这种方法效果很好。 然而,它有时会导致类加载问题,特别是在多模块项目中。

为了诊断类加载问题是否确实是由devtools和它的两个类加载器引起的,请试着禁用 restart。如果这能解决你的问题,请定制 restart 类加载器 以包括你的整个项目。

8.2. 属性的默认值

在Spring Boot支持的一些库中,会使用缓存来提高性能。例如,模板引擎会缓存已编译的模板,以避免重复解析模板文件。另外,Spring MVC可以在响应静态资源时往响应中添加HTTP缓存头。

虽然缓存在生产中是非常有益的,但在开发过程中可能会产生反作用,使你无法看到你在应用程序中刚做的改动。 由于这个原因,spring-boot-devtools 默认禁用了缓存选项。

缓存的选项通常是通过 application.properties 文件中的属性来配置的。 例如,Thymeleaf提供了 spring.thymeleaf.cache[] 属性。 与其需要手动设置这些属性,spring-boot-devtools 模块会在开发场景下合理的设置这些属性。

下表列出了所有被设置的属性。

Name Default Value

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日志。这将给你提供关于客户端的请求信息,哪个handler正在处理它,响应结果,以及其他细节。如果你希望记录所有的请求细节(包括潜在的敏感信息),你可以打开 spring.mvc.log-request-details[]spring.codec.log-request-details[] 配置。

8.3. 自动重启

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

触发重启

由于DevTools监控classpath资源,触发重启的唯一方法是更新classpath。 无论你使用的是IDE还是构建插件,被修改的文件都必须被重新编译以触发重启。 导致更新classpath的方式取决于你所使用的工具。

  • 在Eclipse中,保存一个修改过的文件会导致classpath被更新并触发重启。

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

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

如果你用Maven或Gradle的构建插件重启,你必须将 forking 设置为 enabled。 如果你禁用 forking,devtools使用的“应用隔离类加载器(isolated application classloader)”将不会被创建,重启功能将无法正常运行。
与LiveReload一起使用时,自动重启的效果非常好。 详见 LiveReload 部分。 如果你使用JRebel,自动重启被禁用,而采用动态类重载。 其他devtools特性(如LiveReload和属性覆盖)仍然可以使用。
DevTools依靠应用程序上下文的关机hook来在重启期间关闭它。 如果你禁用了关机钩子( SpringApplication.setRegisterShutdownHook(false) ),它就不能正确工作。
DevTools需要定制 ApplicationContext 所使用的 ResourceLoader。 如果你的应用程序已经提供了一个,它将被“包装”(装饰者设计模式)起来。 不支持直接覆盖 ApplicationContext 上的 getResource 方法。
在使用AspectJ 切面时,不支持自动重启。
重启 vs 重载

Spring Boot通过两个类加载器实现了重启。 不变的类(例如,来自第三方jar的类)被加载到一个 base classloader。 你正在开发的类被加载到 restart classloader中。 当应用程序被重新启动时, restart classloader 被丢弃,并被创建一个新的。 这种方法意味着应用程序的重启通常比 “冷启动” 快得多,因为 base classloader 已经可用并被填充。

如果你发现重启对你的应用程序来说不够快,或者你遇到了类加载相关的问题,你可以考虑重载技术,如ZeroTurnaround的 JRebel。这些技术的工作原理是在类被加载时对其进行重写,使其更容易被重载。

8.3.1. 记录条件评估的变化

默认情况下,每次你的应用程序重新启动时,都会记录一份显示条件评估delta的报告。 该报告显示了你的应用程序的自动配置的变化,因为你做了一些改变,如添加或删除Bean和设置配置属性。

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

Properties
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 ,你可以设置以下属性。

Properties
spring.devtools.restart.exclude=static/**,public/**
Yaml
spring:
  devtools:
    restart:
      exclude: "static/**,public/**"
如果你想保留这些默认值并增加额外的排除资源,请使用 spring.devtools.restart.extra-exclude 属性来代替。

8.3.3. 监控额外的路径

当你对不在classpath上的文件进行修改时,你可能希望你的应用程序被重新启动或重新加载。为此,使用 spring.devtools.restart.extra-paths 属性来配置监控变化的额外路径。你可以使用前面说过的spring.devtools.restart.exclude 属性来控制额外路径下的变化是触发完全重启还是实时重载

8.3.4. 禁止重启

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

如果你需要完全禁用重启支持(例如,因为它不能与特定的库一起工作),你需要在调用 SpringApplication.run(…​) 之前将 spring.devtools.restart.enabled 属性设置为 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. 使用 trigger file

如果你只想在在特定时间触发重启,你可以使用 “trigger file”,这是一个特殊的文件,当你想实际触发重启检查时,那你就对这个文件进行修改。

对文件的任何更新都会触发检查,但只有当Devtools检测到它有改动发生时,才会实际重新启动。

通过属性 spring.devtools.restart.trigger-file 设置trigger file 文件的名称(不包括任何路径)。 trigger file必须在classpath路径上。

例如,如果你有一个结构如下的项目。

src
+- main
   +- resources
      +- .reloadtrigger

那么你的 “trigger-file” 属性应该设置为如下。

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 EclipseIntelliJ IDEA (Ultimate Edition))都有这种支持。对于Spring Tools,你可以使用控制台视图中的 “reload” 按钮(需要把你的 trigger-file 命名为 .reloadtrigger)。对于IntelliJ IDEA,你可以按照其文档中的说明进行操作。

8.3.6. 自定义重启类加载器(Restart Classloader)

正如前面在"Restart vs Reload"所描述的,重启功能是通过使用两个classloader实现的。如果这导致了其他的问题,你可能需要自定义类加载器。

默认情况下,你的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” 类加载器中的项目。 该属性的值是一个基于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"
所有的key必须是唯一的。只要一个属性以 restart.include.restart.exclude. 开头,就会被考虑进去。
所有在classpath的 META-INF/spring-devtools.properties 都会被加载。 你可以把它打包到你的项目中,或者打包进你项目依赖的项目中。

8.3.7. 已知的限制

如果你使用标准的 ObjectInputStream 来反序列化对象,那么重启功能的效果可能并不好。 如果你需要反序列化数据,你可能需要使用到Spring的 ConfigurableObjectInputStreamThread.currentThread().getContextClassLoader()

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

8.4. LiveReload

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应用程序。 例如,如果要将重启配置为总是使用trigger file,你可以在 spring-boot-devtools 文件中添加以下属性。

Properties
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 文件。 这允许你与那些不支持 $HOME/.config/spring-boot 位置的旧版Spring Boot的应用程序共享devtools全局配置。

devtools properties/yaml文件中不支持Profiles。

任何在 .spring-boot-devtools.properties 中激活的Profiles都不会影响指定配置文件的加载。不支持在YAML和Properties文件中配置Profiles(形式为 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 参数到适合你开发环境的值。

Properties
spring.devtools.restart.poll-interval=2s
spring.devtools.restart.quiet-period=1s
Yaml
spring:
  devtools:
    restart:
      poll-interval: "2s"
      quiet-period: "1s"

受监控的classpath目录现在每2秒轮询一次变化,并保持1秒的安静期以确保没有额外的类变化。

8.6. 远程应用

Spring Boot的开发者工具并不局限于本地开发。 你也可以在远程运行应用程序时使用一些功能。 远程支持是可选的,因为启用它可能会有安全风险。 只有在受信任的网络上运行时,或在用SSL保护时,才应启用它。 如果这两个选项对你来说都不可用,你就不应该使用DevTools的远程支持。 你更不应该在生产环境中启用它。

要启用它,你需要确保 devtools 包含在重新打包的归档文件(jar)中,如以下所示。

<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 属性。 就像任何重要的密码或密钥一样,这个值应该是唯一的和足够强大的,以至于它不能被猜到或被暴力破解。

Remote devtools support is provided in two parts: a server-side endpoint that accepts connections and a client application that you run in your IDE. The server component is automatically enabled when the spring.devtools.remote.secret property is set. The client component must be launched manually.

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

Spring WebFlux应用程序不支持远程devtools。

8.6.1. 运行远程客户端程序

远程客户端应用程序被设计成可以在你的IDE中运行。 你需要运行 org.springframework.boot.devtools.RemoteSpringApplication ,其classpath与你所连接的远程项目相同。 该应用程序的唯一必要参数是它所连接的远程URL。

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

  • Run 菜单中选择 Run Configurations…​

  • 创建一个新的 Java Application “launch configuration”。

  • 浏览 my-app 项目。

  • 使用 org.springframework.boot.devtools.RemoteSpringApplication 作为main类。

  • Program arguments 中添加 https://myapp.cfapps.io(或者你的远程URL)。

一个正在运行的远程客户端可能类似于如下。

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

2023-09-10T13:32:07.711+08:00  INFO 16764 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication v3.2.0-SNAPSHOT using Java 17 with PID 16764 (/Users/myuser/.m2/repository/org/springframework/boot/spring-boot-devtools/3.2.0-SNAPSHOT/spring-boot-devtools-3.2.0-SNAPSHOT.jar started by myuser in /opt/apps/)
2023-09-10T13:32:07.764+08:00  INFO 16764 --- [           main] o.s.b.devtools.RemoteSpringApplication   : No active profile set, falling back to 1 default profile: "default"
2023-09-10T13:32:08.094+08:00  INFO 16764 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2023-09-10T13:32:08.121+08:00  INFO 16764 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 1.388 seconds (process running for 2.843)
因为远程客户端使用的是与真实应用程序相同的classpath,它可以直接读取应用程序属性。 spring.devtools.remote.secret 属性就是这样被读取并传递给服务器进行验证的。
始终建议使用 https:// 作为连接协议,这样流量会被加密,密码也不会被截获。
如果你需要使用代理来访问远程应用程序,可以配置 spring.devtools.remote.proxy.hostspring.devtools.remote.proxy.port 属性。

8.6.2. 远程更新

远程客户端以与本地 restart相同的方式监控你的应用程序classpath的变化。任何更新的资源都会被推送到远程应用程序,并(如果需要)触发重启。如果你在一个云服务上进行功能迭代,而你在本地没有云服务,这可能会很有帮助。一般来说,远程更新和重启要比完整的重建和部署周期快得多。

在一个较慢的开发环境中,可能会发生“等待时间”不够的情况,类的变化可能被分成几批。 在第一批类的变化被上传后,服务器被重新启动。 下一批则不能被发送到应用程序,因为服务器正在重启。

这通常表现为 RemoteSpringApplication 日志中的警告,即未能上传一些类,并随之重试。 但它也可能导致应用程序代码不一致,以及在第一批修改上传后无法重新启动。 如果你经常观察到这样的问题,可以尝试增加 spring.devtools.restart.poll-intervalspring.devtools.restart.quiet-period 参数到适合你开发环境的值。 参见"配置文件系统监听器"一节,以配置这些属性。

文件只在远程客户端运行时被监控。 如果你在启动远程客户端之前改变了一个文件,它不会被推送到远程服务器上。

9. 打包应用,部署到生产环境

可执行jar可以用于生产环境,由于它们是独立的,非常适合部署到云服务中。

对于额外的 “生产就绪” 功能,如健康、审计和度量REST或JMX端点,考虑添加 spring-boot-actuator 。详情见 actuator

10. 接下来读什么

你现在应该明白如何使用Spring Boot以及应该遵循的一些最佳实践。现在你可以继续深入了解 Spring Boot 特性 ,或者你可以跳过前面,阅读Spring Boot的 “生产就绪” 方面的内容。