1. Spring Boot

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

1.1. 构建系统

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

1.1.1. 依赖管理

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

你仍然可以指定版本,并在需要时覆盖Spring Boot的建议版本。

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

Spring Boot的每个发行版都与Spring Framework的基本版本相关联。强烈 建议你不要更改其版本。

1.1.2. Maven

Maven用户可以从 spring-boot-starter-parent 项目继承来获得合理的默认值。父项目提供以下功能:

  • Java 1.8是默认的编译器级别。

  • UTF-8源编码。

  • 从spring-boot-dependencies pom继承的依赖管理部分, 它管理公共依赖项的版本。当在自己的pom中使用这些依赖关系时,可以为这些依赖关系省略 <version> 标记。

  • 使用 repackage 执行id执行 repackage 目标

  • 明智的 资源过滤.

  • 明智的插件配置 (exec plugin, Git commit IDshade).

  • application.propertiesapplication.yml 进行明智的资源过滤,包括特定于环境的文件 (例如:application-dev.propertiesapplication-dev.yml

请注意,由于 application.propertiesapplication.yml 文件接受Spring样式的占位符(${…​}), 因此Maven过滤已更改为使用 @..@ 占位符。(你可以通过设置一个名为 resource.delimiter 的Maven属性来覆盖它。)

继承Starter Parent

要将项目配置为从 spring-boot-starter-parent 继承,请设置 parent,如下所示:

<!-- Inherit defaults from Spring Boot -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.2.RELEASE</version>
</parent>
你只需要为此依赖项指定Spring Boot版本号。如果导入其他starter,则可以安全地省略版本号。

使用该设置,你还可以通过覆盖自己项目中的属性来覆盖各个依赖项。例如,要升级到另一个Spring Data发布系列, 可以将以下内容添加到 pom.xml 中:

<properties>
    <spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>
检查 spring-boot-dependencies pom以获取受支持属性的列表。
在没有父POM的情况下使用Spring Boot

并非每个人都喜欢从 spring-boot-starter-parent 父POM继承。你可能需要使用自己公司的标准父POM,或者可能希望显式声明所有Maven配置。

如果你不想使用 spring-boot-starter-parent,仍然可以通过使用 scope=import 依赖项来保留依赖项管理(而不是插件管理)的好处,如下所示:

<dependencyManagement>
    <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.2.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

如上所述,前面的示例设置不允许你使用属性来覆盖各个依赖项。为了获得相同的结果, 需要在项目的 dependencyManagementspring-boot-dependencies 条目 之前 添加一个条目。 例如,要升级到另一个Spring Data发布系列,可以将以下元素添加到 pom.xml 中:

<dependencyManagement>
    <dependencies>
        <!-- Override Spring Data release train provided by Spring Boot -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-releasetrain</artifactId>
            <version>Fowler-SR2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.2.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
在前面的示例中,我们指定了 BOM,但是可以以相同方式覆盖任何依赖项类型。
使用Spring Boot Maven插件

Spring Boot包含一个 Maven插件, 可以将项目打包为可执行jar。如果要使用插件,请将其添加到你的 <plugins> 部分,如以下示例所示:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
如果你使用Spring Boot starter parent pom,则只需添加插件。除非你要更改父级中定义的设置,否则无需对其进行配置。

1.1.3. Gradle

要了解有关将Spring Boot与Gradle结合使用的信息,请参阅Spring Boot的Gradle插件的文档:

1.1.4. Ant

可以使用Apache Ant+Ivy构建Spring Boot项目。spring-boot-antlibAntLib”模块也可用于帮助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.2.2.RELEASE" />

    <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 模块,请参阅 不使用spring-boot-antlib “How-to”从Ant构建可执行存档

1.1.5. Starters

启动器是一组便捷的依赖项描述符,你可以在应用程序中包括它们。你可以一站式安装所需的所有Spring和相关技术, 而不必遍历示例代码和依赖描述符复制粘贴它。例如,如果要开始使用Spring和JPA进行数据库访问,请在项目中包括 spring-boot-starter-data-jpa 依赖项。

启动器包含许多启动项目并快速运行所需的依赖项,并且具有一组受支持的被管理的传递性依赖项。

名字叫什么

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

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

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

Table 1. Spring Boot application starters
名称 描述 Pom

spring-boot-starter

核心启动器,包括自动配置支持,日志记录和YAML

Pom

spring-boot-starter-activemq

使用Apache ActiveMQ的JMS消息传递启动器

Pom

spring-boot-starter-amqp

使用Spring AMQP和Rabbit MQ的启动器

Pom

spring-boot-starter-aop

使用Spring AOP和AspectJ进行面向方面编程的启动器

Pom

spring-boot-starter-artemis

使用Apache Artemis的JMS消息传递启动器

Pom

spring-boot-starter-batch

使用Spring Batch的启动器

Pom

spring-boot-starter-cache

使用Spring Framework缓存支持的启动器

Pom

spring-boot-starter-cloud-connectors

使用Spring Cloud Connectors的启动器,可简化与Cloud Foundry和Heroku等云平台中服务的连接。不赞成使用Java CFEnv

Pom

spring-boot-starter-data-cassandra

使用Cassandra分布式数据库和Spring Data Cassandra的启动器

Pom

spring-boot-starter-data-cassandra-reactive

使用Cassandra分布式数据库和Spring Data Cassandra Reactive的启动器

Pom

spring-boot-starter-data-couchbase

使用Couchbase面向文档的数据库和Spring Data Couchbase的启动器

Pom

spring-boot-starter-data-couchbase-reactive

使用Couchbase面向文档的数据库和Spring Data Couchbase Reactive的启动器

Pom

spring-boot-starter-data-elasticsearch

使用Elasticsearch搜索和分析引擎以及Spring Data Elasticsearch的启动器

Pom

spring-boot-starter-data-jdbc

使用Spring Data JDBC的启动器

Pom

spring-boot-starter-data-jpa

将Spring Data JPA与Hibernate结合使用的启动器

Pom

spring-boot-starter-data-ldap

使用Spring Data LDAP的启动器

Pom

spring-boot-starter-data-mongodb

使用MongoDB面向文档的数据库和Spring Data MongoDB的启动器

Pom

spring-boot-starter-data-mongodb-reactive

使用MongoDB面向文档的数据库和Spring Data MongoDB Reactive的启动器

Pom

spring-boot-starter-data-neo4j

使用Neo4j图数据库和Spring Data Neo4j的启动器

Pom

spring-boot-starter-data-redis

将Redis键值对数据库与Spring Data Redis和Lettuce客户端一起使用的启动器

Pom

spring-boot-starter-data-redis-reactive

将Redis键值对数据库与Spring Data Redis Reacting和Lettuce客户端一起使用的启动器

Pom

spring-boot-starter-data-rest

使用Spring Data REST在REST上公开Spring Data存储库的启动器

Pom

spring-boot-starter-data-solr

使用Apache Solr搜索平台和Spring Data Solr的启动器

Pom

spring-boot-starter-freemarker

使用FreeMarker视图构建MVC Web应用程序的启动器

Pom

spring-boot-starter-groovy-templates

使用Groovy模板视图构建MVC Web应用程序的启动器

Pom

spring-boot-starter-hateoas

使用Spring MVC和Spring HATEOAS构建基于超媒体的RESTful Web应用程序的启动器

Pom

spring-boot-starter-integration

使用Spring Integration的启动器

Pom

spring-boot-starter-jdbc

通过HikariCP连接池使用JDBC的启动器

Pom

spring-boot-starter-jersey

使用JAX-RS和Jersey构建RESTful Web应用程序的启动器。 spring-boot-starter-web的替代品

Pom

spring-boot-starter-jooq

使用jOOQ访问SQL数据库的启动器。 spring-boot-starter-data-jpaspring-boot-starter-jdbc的替代品

Pom

spring-boot-starter-json

读写JSON的启动器

Pom

spring-boot-starter-jta-atomikos

使用Atomikos的JTA事务启动器

Pom

spring-boot-starter-jta-bitronix

使用Bitronix的JTA事务启动器

Pom

spring-boot-starter-mail

使用Java Mail和Spring Framework的电子邮件发送支持的启动器

Pom

spring-boot-starter-mustache

使用Mustache视图构建Web应用程序的启动器

Pom

spring-boot-starter-oauth2-client

使用Spring Security的OAuth2/OpenID Connect客户端功能的启动器

Pom

spring-boot-starter-oauth2-resource-server

使用Spring Security的OAuth2资源服务器功能的启动器

Pom

spring-boot-starter-quartz

使用Quartz Scheduler的启动器

Pom

spring-boot-starter-rsocket

用于构建RSocket客户端和服务器的启动器

Pom

spring-boot-starter-security

使用Spring Security的启动器

Pom

spring-boot-starter-test

使用包括JUnit,Hamcrest和Mockito在内的库测试Spring Boot应用程序的启动器

Pom

spring-boot-starter-thymeleaf

使用Thymeleaf视图构建MVC Web应用程序的启动器

Pom

spring-boot-starter-validation

通过Hibernate Validator使用Java Bean验证的启动器

Pom

spring-boot-starter-web

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

Pom

spring-boot-starter-web-services

使用Spring Web Services的启动器

Pom

spring-boot-starter-webflux

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

Pom

spring-boot-starter-websocket

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

Pom

除了应用程序启动程序,以下启动程序可用于添加 生产就绪 功能:

Table 2. Spring Boot production starters
名称 描述 Pom

spring-boot-starter-actuator

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

Pom

最后,Spring Boot还包括以下启动程序,如果你想排除或替换特定的技术方面,可以使用这些启动程序:

Table 3. Spring Boot technical starters
名称 描述 Pom

spring-boot-starter-jetty

使用Jetty作为嵌入式servlet容器的启动器。spring-boot-starter-tomcat的替代品

Pom

spring-boot-starter-log4j2

使用Log4j2进行日志记录的启动器。spring-boot-starter-logging的替代品

Pom

spring-boot-starter-logging

使用Logback进行日志记录的启动器。默认日志记录启动器

Pom

spring-boot-starter-reactor-netty

使用Reactor Netty作为嵌入式响应式HTTP服务器的启动器

Pom

spring-boot-starter-tomcat

用于将Tomcat用作嵌入式servlet容器的启动器。spring-boot-starter-web使用的默认servlet容器启动器

Pom

spring-boot-starter-undertow

使用Undertow作为嵌入式servlet容器的启动器。spring-boot-starter-tomcat的替代品

Pom

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

1.2. 结构化你的代码

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

1.2.1. 使用“default”包

当类不包含 package 声明时,将其视为在“default package”中。通常不建议使用“default package”,应避免使用。 对于使用 @ComponentScan@ConfigurationPropertiesScan@EntityScan@SpringBootApplication 注解的Spring Boot应用程序,这可能会引起特定的问题,因为每个jar中的每个类都会被读取。

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

1.2.2. 找到应用程序主类

我们通常建议你将应用程序主类放在其他类之上的根包中。@SpringBootApplication 注解通常放在你的主类上,它隐式定义某些条目的基本“search package”。 例如,如果你正在编写JPA应用程序,则使用带 @SpringBootApplication 注解的类的包来搜索 @Entity 条目。 使用根软件包还允许组件扫描仅应用于你的项目。

如果你不想使用 @SpringBootApplication,则可以通过导入的 @EnableAutoConfiguration@ComponentScan 注解来定义该行为,因此也可以使用它们。

以下清单显示了典型的布局:

com
 +- example
     +- myapplication
         +- Application.java
         |
         +- customer
         |   +- Customer.java
         |   +- CustomerController.java
         |   +- CustomerService.java
         |   +- CustomerRepository.java
         |
         +- order
             +- Order.java
             +- OrderController.java
             +- OrderService.java
             +- OrderRepository.java

Application.java 文件将声明 main 方法以及基本的 @SpringBootApplication 注解,如下所示:

package com.example.myapplication;

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

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

1.3. 配置类

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

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

1.3.1. 导入其他配置类

你无需将所有 @Configuration 放在单个类中。@Import 注解可用于导入其他配置类。 另外,你可以使用 @ComponentScan 自动拾取所有Spring组件,包括 @Configuration 类。

1.3.2. 导入XML配置

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

1.4. 自动配置

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

你需要通过将 @EnableAutoConfiguration@SpringBootApplication 注解添加到你的 @Configuration 类之一来启用自动配置。

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

1.4.1. 逐渐取代自动配置

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

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

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

如果发现正在应用某个不需要的特定自动配置类,则可以使用 @EnableAutoConfigurationexclude 属性禁用它们,如以下示例所示:

import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;
import org.springframework.context.annotation.*;

@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}

如果该类不在类路径中,则可以使用注解的 excludeName 属性,并指定完全限定的名称。最后,你还可以使用 spring.autoconfigure.exclude 属性控制要排除的自动配置类的列表。

你可以在注解级别和使用属性来定义排除项。
即使自动配置类是 public,类中唯一被认为是公共API的是类的名称,它可以用来禁用自动配置。 这些类的实际内容(例如:嵌套配置类或Bean方法)仅供内部使用,我们不建议直接使用它们。

1.5. Spring Beans和依赖注入

你可以自由使用任何标准的Spring Framework技术来定义bean及其注入依赖关系。为简单起见,我们经常发现使用 @ComponentScan(查找你的bean)和使用 @Autowired(进行构造函数注入)效果很好。

如果按照上面的建议构造代码(将应用程序类放在根包中),则可以添加 @ComponentScan,而无需添加任何参数。 你的所有应用程序组件(@Component@Service@Repository@Controller 等)都将自动注册为Spring Bean。

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

package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DatabaseAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

    @Autowired
    public DatabaseAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
    }

    // ...

}

如果bean具有一个构造函数,则可以省略 @Autowired,如以下示例所示:

@Service
public class DatabaseAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

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

    // ...

}
请注意如何使用构造函数注入将 riskAssessor 字段标记为 final,以表示它随后不能更改。

1.6. 使用@SpringBootApplication注解

许多Spring Boot开发人员喜欢他们的应用程序使用自动配置,组件扫描,并能够在其“应用程序类”上定义额外的配置。 单个 @SpringBootApplication 注解可用于同时启用这三个功能,即:

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

  • 在应用程序所在的软件包上启用 @Component 扫描(请参阅最佳实践

  • @Configuration: 允许在上下文中注册额外的bean或导入其他配置类

package com.example.myapplication;

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

@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
@SpringBootApplication 还提供别名以自定义 @EnableAutoConfiguration@ComponentScan 的属性。

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

package com.example.myapplication;

import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@Import({ MyConfig.class, MyAnotherConfig.class })
public class Application {

    public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
    }

}

在此示例中,除了没有自动检测到 @Component@ConfigurationProperties 注解的类并且显式导入了用户定义的Bean外, Application 就像其他任何Spring Boot应用程序一样(请参阅 @Import)。

1.7. 运行你的应用程序

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

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

1.7.1. 从IDE运行

你可以将IDE中的Spring Boot应用程序作为简单的Java应用程序运行。但是,你首先需要导入你的项目。 导入步骤因你的IDE和构建系统而异。大多数IDE可以直接导入Maven项目。例如:Eclipse用户可以从 File 中选择 Import…​Existing Maven Projects

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

如果不小心两次运行Web应用程序,则会看到“Port already in use”错误。 STS用户可以使用 Relaunch 按钮而不是 Run 按钮来确保关闭任何现有实例。

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

1.7.3. 使用Maven插件

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

$ mvn spring-boot:run

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

$ export MAVEN_OPTS=-Xmx1024m

1.7.4. 使用Gradle插件

Spring Boot Gradle插件包含一个 bootRun 任务,该任务可用于以爆炸形式运行你的应用程序。每当你应用 org.springframework.bootjava 插件时,都会添加 bootRun 任务,在以下示例中显示:

$ gradle bootRun

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

$ export JAVA_OPTS=-Xmx1024m

1.7.5. 热交换

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

spring-boot-devtools 模块还包括对应用程序快速重启的支持。有关详细信息,请参见本章后面的开发者工具部分和 “How-to” 热交换

1.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
configurations {
    developmentOnly
    runtimeClasspath {
        extendsFrom developmentOnly
    }
}
dependencies {
    developmentOnly("org.springframework.boot:spring-boot-devtools")
}
运行完全打包的应用程序时,将自动禁用开发者工具。如果你的应用程序是以 java -jar 启动的, 或者是从特殊的类加载器启动的,则将其视为“生产应用程序”。如果这不适用于你(即如果你从容器中运行应用程序), 请考虑排除devtools或设置 -Dspring.devtools.restart.enabled=false 系统属性。
在Maven中将依赖项标记为optional或在Gradle中使用自定义 developmentOnly 配置(如上所示)是一种最佳实践, 它可以防止将devtools过渡地应用到使用你项目的其他模块。
重新打包的存档默认情况下不包含devtools。如果要使用某个远程devtools功能, 则需要禁用 excludeDevtools 构建属性以包括它。Maven和Gradle插件均支持该属性。

1.8.1. 属性默认值

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

尽管缓存在生产中非常有益,但在开发过程中可能适得其反,从而使你无法看到刚刚在应用程序中所做的更改。因此,默认情况下,spring-boot-devtools 禁用缓存选项。

缓存选项通常由 application.properties 文件中的设置配置。例如,Thymeleaf提供 spring.thymeleaf.cache 属性。 spring-boot-devtools 模块不需要手动设置这些属性,而是自动应用合理的开发时配置。

由于在开发Spring MVC和Spring WebFlux应用程序时需要有关Web请求的更多信息,因此开发者工具将为 web 日志记录组启用 DEBUG 日志记录。 这将为你提供有关传入请求,正在处理的处理程序,响应结果等的信息。如果你希望记录所有请求详细信息(包括潜在的敏感信息), 则可以打开 spring.http.log-request-details 配置属性。

如果你不希望应用默认属性,则可以在 application.properties 中将 spring.devtools.add-properties 设置为 false
有关devtools应用的属性完整列表,请参见 DevToolsPropertyDefaultsPostProcessor

1.8.2. 自动重启

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

触发重启

当DevTools监视类路径资源时,触发重启的唯一方法是更新类路径。导致类路径更新的方式取决于所使用的IDE。 在Eclipse中,保存修改后的文件将导致类路径被更新并触发重新启动。 在IntelliJ IDEA中,构建项目(Build -> Build Project)具有相同的效果。

只要启用了forking,你还可以使用受支持的构建插件(Maven和Gradle)启动应用程序, 因为DevTools需要一个隔离的应用程序类加载器才能正常运行。默认情况下,Gradle和Maven插件会fork应用程序进程。
与LiveReload一起使用时,自动重启非常有效。有关详细信息,请参见LiveReload部分。 如果使用JRebel,则禁用自动重新启动,而支持动态类重新加载。其他devtools功能(例如LiveReload和属性覆盖)仍可以使用。
DevTools依赖于应用程序上下文的关闭钩子在重新启动期间将其关闭。如果你禁用了关闭钩子 (SpringApplication.setRegisterShutdownHook(false)),它将无法正常工作。
在确定类路径上的条目是否应在更改后触发重新启动时,DevTools会自动忽略名为 spring-bootspring-boot-devtoolsspring-boot-autoconfigurespring-boot-actuatorspring-boot-starter 的项目。
DevTools需要自定义 ApplicationContext 使用的 ResourceLoader。如果你的应用程序已经提供了,它将被包装。 不支持在 ApplicationContext 上直接重写 getResource 方法。
重新启动 vs 重新加载

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

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

记录条件评估中的更改

默认情况下,每次应用程序重新启动时,都会记录一个报告,其中显示了条件评估增量变化。 该报告显示了你进行代码更改(例如:添加或删除Bean以及设置配置属性)时所造成的对应用程序自动配置的更改。

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

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

spring.devtools.restart.exclude=static/**,public/**
如果要保留这些默认值并 添加 其他排除项,请改用 spring.devtools.restart.additional-exclude 属性。
监视其他路径

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

禁用重启

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

如果你需要 完全 禁用重启支持(例如:因为它不适用于特定的库),则需要在调用 SpringApplication.run(…​) 之前将 spring.devtools.restart.enabled 系统属性设置为 false。如以下示例所示:

public static void main(String[] args) {
    System.setProperty("spring.devtools.restart.enabled", "false");
    SpringApplication.run(MyApp.class, args);
}
使用触发文件

如果使用持续编译更改文件的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,你可以从控制台视图使用“reload”按钮(只要你的 trigger-file.reloadtrigger)。 对于IntelliJ,你可以按照 其文档中的说明进行操作。

自定义重启类加载器

如前面的重新启动 vs 重新加载部分所述,重新启动功能是通过使用两个类加载器实现的。 对于大多数应用程序,此方法效果很好。但是,有时可能会导致类加载问题。

默认情况下,IDE中的任何打开的项目都使用“重启”类加载器加载,而任何常规的 .jar 文件都使用“基本”类加载器加载。 如果你在多模块项目上工作,并且并非每个模块都导入到IDE中,则可能需要自定义内容。为此,你可以创建一个 META-INF/spring-devtools.properties 文件。

spring-devtools.properties 文件可以包含带有 restart.excluderestart.include 前缀的属性。 include 元素是应上拉到“重启”类加载器中的项目,而 exclude 元素是应下推到“基本”类加载器中的项目。 该属性的值是应用于类路径的正则表达式模式,如以下示例所示:

restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\.]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\.]+\.jar
所有属性键都必须是唯一的。只要属性以 restart.includerestart.exclude 开头,它就会被考虑。
将加载类路径中的所有 META-INF/spring-devtools.properties。你可以将文件打包到项目内部,也可以打包到项目使用的库中。
已知局限性

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

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

1.8.3. LiveReload

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

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

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

1.8.4. 全局设置

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

  1. spring-boot-devtools.properties

  2. spring-boot-devtools.yaml

  3. spring-boot-devtools.yml

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

~/.config/spring-boot/spring-boot-devtools.properties
spring.devtools.restart.trigger-file=.reloadtrigger
如果在 $HOME/.config/spring-boot 中找不到devtools配置文件,则在 $HOME 文件夹的根目录中搜索是否存在 .spring-boot-devtools.properties 文件。这使你可以与不支持 $HOME/.config/spring-boot 位置的较旧版本的Spring Boot上的应用程序共享devtools全局配置。
上述文件中激活的Profiles不会影响 特定于环境的配置文件的加载。

1.8.5. 远程应用

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 属性后,将自动启用服务器组件,客户端组件必须手动启动。

运行远程客户端应用程序

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

例如,如果你使用的是Eclipse或STS,并且有一个名为 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 :: 2.2.2.RELEASE

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 属性。
远程更新

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

仅在远程客户端正在运行时监视文件。如果在启动远程客户端之前更改文件,则不会将其推送到远程服务器。
配置文件系统观察器

FileSystemWatcher 的工作方式是按一定的时间间隔轮询类更改,然后等待预定义的静默期以确保没有更多更改。 然后将更改上传到远程应用程序。在较慢的开发环境中,可能会发生静默期不够的情况,并且类中的更改可能会分为几批。 第一批类更改上传后,服务器将重新启动。由于服务器正在重新启动,因此下一批不能发送到应用程序。

这通常通过 RemoteSpringApplication 日志中的警告来证明,即有关上载某些类失败的消息,然后进行重试。 但是,这也可能导致应用程序代码不一致,并且在上传第一批更改后无法重新启动。

如果你经常观察到此类问题,请尝试将 spring.devtools.restart.poll-intervalspring.devtools.restart.quiet-period 参数增加到适合你的开发环境的值:

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

现在每2秒轮询一次受监视的classpath文件夹以进行更改,并保持1秒钟的静默时间以确保没有其他类更改。

1.9. 打包你的应用程序用于生产

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

对于其他“生产就绪”功能,例如运行状况,审核和度量REST或JMX端点,请考虑添加 spring-boot-actuator。 有关详细信息,请参见 生产就绪

1.10. 接下来要读什么

现在,你应该了解了如何使用Spring Boot以及应遵循的一些最佳实践。现在,你可以继续深入了解特定的 Spring Boot功能,或者可以跳过并阅读有关 Spring Boot的 生产就绪 方面的信息。

2. Spring Boot特性

本节将深入介绍Spring Boot。在这里,你可以了解可能要使用和自定义的关键功能。开始之前,建议你先阅读Spring Boot部分, 以便你有足够的基础知识。

2.1. SpringApplication

SpringApplication 类提供了一种便捷的方式来引导从 main() 方法启动的Spring应用程序。在大多数情况下, 你可以委托给静态 SpringApplication.run 方法,如以下示例所示:

public static void main(String[] args) {
    SpringApplication.run(MySpringConfiguration.class, args);
}

当你的应用程序启动时,你应该看到类似于以下输出的内容:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::   v2.2.2.RELEASE

2019-04-31 13:09:54.117  INFO 56603 --- [           main] o.s.b.s.app.SampleApplication            : Starting SampleApplication v0.1.0 on mycomputer with PID 56603 (/apps/myapp.jar started by pwebb)
2019-04-31 13:09:54.166  INFO 56603 --- [           main] ationConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy
2019-04-01 13:09:56.912  INFO 41370 --- [           main] .t.TomcatServletWebServerFactory : Server initialized with port: 8080
2019-04-01 13:09:57.501  INFO 41370 --- [           main] o.s.b.s.app.SampleApplication            : Started SampleApplication in 2.992 seconds (JVM running for 3.658)

默认情况下,显示 INFO 日志消息,包括一些相关的启动详细信息,例如:启动应用程序的用户。如果你需要除 INFO 级别以外的其他日志, 则可以按照日志级别中的说明进行设置。使用主应用程序类包中的实现版本来确定应用程序版本。 可以通过将 spring.main.log-startup-info 设置为 false 来关闭启动信息记录。这还将关闭对应用程序激活的环境配置文件的日志记录。

要在启动期间添加其他日志记录,可以在 SpringApplication 的子类中重写 logStartupInfo(boolean)

2.1.1. 启动失败

如果你的应用程序无法启动,则已注册的 FailureAnalyzers 将有机会提供专门的错误消息和解决该问题的具体措施。 例如:如果你在端口8080上启动Web应用程序并且该端口已在使用中,则应该看到类似于以下消息的内容:

***************************
APPLICATION FAILED TO START
***************************

Description:

Embedded servlet container failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.
Spring Boot提供了大量的 FailureAnalyzer 实现,你可以添加自己的实现

如果没有故障分析器能够处理该异常,你仍然可以显示完整条件报告以更好地了解出了什么问题。 为此,你需要为 org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener 启用 debug 属性启用 DEBUG 日志记录

例如,如果使用 java -jar 运行应用程序,则可以按以下方式启用 debug 属性:

$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug

2.1.2. 延迟初始化

SpringApplication 允许延迟初始化应用程序。启用延迟初始化后,将根据需要创建bean,而不是在应用程序启动期间创建bean。 因此,启用延迟初始化可以减少应用程序启动所需的时间。在Web应用程序中,启用延迟初始化将导致许多与Web相关的Bean直到收到HTTP请求后才被初始化。

延迟初始化的缺点是,它可能会延迟发现应用程序问题的时间。如果错误配置的Bean被延迟初始化,则启动期间将不再发生故障, 并且只有在初始化Bean时问题才会发现。还必须注意确保JVM有足够的内存来容纳所有应用程序的bean, 而不仅仅是启动期间初始化的bean。由于这些原因,默认情况下不会启用延迟初始化, 因此建议在启用延迟初始化之前先对JVM的堆大小进行微调。

可以使用 SpringApplicationBuilder 上的 lazyInitialization 方法或 SpringApplication 上的 setLazyInitialization 方法以编程方式启用延迟初始化。另外,可以使用 spring.main.lazy-initialization 属性启用它,如以下示例所示:

spring.main.lazy-initialization=true
如果要在对应用程序其余部分使用延迟初始化时禁用某些bean的延迟初始化,则可以使用 @Lazy(false) 注解将它们的延迟属性显式设置为 false

2.1.3. 自定义横幅

可以通过将 banner.txt 文件添加到类路径或将 spring.banner.location 属性设置为此类文件的位置来更改启动时打印的横幅。 如果文件的编码不是UTF-8,则可以设置 spring.banner.charset。除了文本文件之外,你还可以将 banner.gifbanner.jpgbanner.png 图像文件添加到类路径中,或设置 spring.banner.image.location 属性。 图像将转换为ASCII艺术品并打印在任何文字横幅上方。

banner.txt 文件中,你可以使用以下任意占位符:

Table 4. 横幅变量
Variable Description

${application.version}

你的应用程序的版本号,在 MANIFEST.MF 中声明。例如:Implementation-Version: 1.0 被打印为 1.0

${application.formatted-version}

你在 MANIFEST.MF 中声明的应用程序版本号的格式化显示(用小括号括起来并以v开头)。例如:(v1.0)

${spring-boot.version}

你正在使用的Spring Boot版本。例如 2.2.2.RELEASE

${spring-boot.formatted-version}

你正在使用的Spring Boot版本的格式化显示(用小括号括起来并以v开头)。例如:(v2.2.2.RELEASE)

${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME})

其中 NAME 是ANSI转义代码的名称。有关详细信息,请参见 AnsiPropertySource

${application.title}

你在 MANIFEST.MF 中声明的应用程序标题。例如:Implementation-Title: MyApp 被打印为 MyApp

如果你要以编程方式生成横幅,则可以使用 SpringApplication.setBanner(…​) 方法。 使用 org.springframework.boot.Banner 接口并实现自己的 printBanner() 方法。

你还可以使用 spring.main.banner-mode 属性来确定横幅是否必须在 System.out控制台)上打印, 是否必须发送到配置的日志记录器(log)或根本不打印(关闭)。

打印的横幅用 springBootBanner 名称注册为单例bean。

2.1.4. 自定义SpringApplication

如果 SpringApplication 的默认设置不符合你的喜好,你可以创建一个本地实例并对其进行自定义。例如:要关闭横幅,你可以编写:

public static void main(String[] args) {
    SpringApplication app = new SpringApplication(MySpringConfiguration.class);
    app.setBannerMode(Banner.Mode.OFF);
    app.run(args);
}
传递给 SpringApplication 的构造函数参数是Spring bean的配置源。在大多数情况下, 它们是对 @Configuration 类的引用,但也可以是对XML配置或应扫描的程序包的引用。

也可以通过使用 application.properties 文件配置 SpringApplication。有关详细信息,请参见 外部化配置

有关配置选项的完整列表,请参见 SpringApplication Javadoc

2.1.5. 流式构建器API

如果你需要构建 ApplicationContext 层次结构(具有父/子关系的多个上下文),或者如果你更喜欢使用“流式”构建器API, 则可以使用 SpringApplicationBuilder

SpringApplicationBuilder 使你可以将多个方法调用链接在一起,并包括允许你创建层次结构的 parentchild 方法,如以下示例所示:

new SpringApplicationBuilder()
        .sources(Parent.class)
        .child(Application.class)
        .bannerMode(Banner.Mode.OFF)
        .run(args);
创建 ApplicationContext 层次结构时有一些限制。例如,Web组件必须包含在子上下文中, 并且父上下文和子上下文都使用相同的 Environment。有关完整的详细信息,请参见 SpringApplicationBuilder Javadoc

2.1.6. 应用程序事件和监听器

除了通常的Spring Framework事件(例如: ContextRefreshedEvent)之外, SpringApplication 还发送一些其他应用程序事件。

实际上在创建 ApplicationContext 之前会触发一些事件,因此你不能将监听器注册为 @Bean。 你可以使用 SpringApplication.addListeners(…​) 方法或 SpringApplicationBuilder.listeners(…​) 方法注册它们。

如果希望这些侦听器自动注册,而不管以何种方式创建应用程序,都可以将 META-INF/spring.factories 文件添加到你的项目中,并使用 org.springframework.context.ApplicationListener 键引用你的侦听器。如以下示例所示:

org.springframework.context.ApplicationListener=com.example.project.MyListener

应用程序事件在你的应用程序运行时按以下顺序发送:

  1. 在运行开始时但在任何处理之前(侦听器和初始化器的注册除外)发送 ApplicationStartingEvent

  2. 已知晓要在上下文中使用的环境但在创建上下文之前,将发送 ApplicationEnvironmentPreparedEvent

  3. 准备 ApplicationContext 并调用ApplicationContextInitializers之后但在加载任何bean 定义之前发送 ApplicationContextInitializedEvent

  4. 在刷新开始之前但在加载bean定义之后发送 ApplicationPreparedEvent

  5. 在刷新上下文之后但在调用任何应用程序和命令行运行程序之前,将发送 ApplicationStartedEvent

  6. 在调用任何应用程序和命令行运行程序之后,将发送 ApplicationReadyEvent。它指示该应用程序已准备就绪,可以处理请求。

  7. 如果启动时发生异常,则发送 ApplicationFailedEvent

上面的列表仅包含绑定到 SpringApplicationSpringApplicationEvents。除这些以外,以下事件也在 ApplicationPreparedEvent 之后和 ApplicationStartedEvent 之前发布:

  1. 刷新 ApplicationContext 后发送 ContextRefreshedEvent

  2. WebServer准备就绪后,将发送 WebServerInitializedEventServletWebServerInitializedEventReactiveWebServerInitializedEvent 分别是servlet和reactive的变体。

你通常不需要使用应用程序事件,但是知道它们的存在可能很方便。在Spring Boot内部使用事件来处理各种任务。

应用程序事件是通过使用Spring Framework的事件发布机制发送的。 此机制的一部分确保在子级上下文中发布给侦听器的事件也可以在任何祖先上下文中发布给侦听器。 结果,如果你的应用程序使用 SpringApplication 实例的层次结构,则侦听器可能会收到同一类型的应用程序事件的多个实例。

为了使你的侦听器能够区分其上下文的事件和后代上下文的事件,则应请求注入其应用程序上下文, 然后将注入的上下文与事件的上下文进行比较。可以通过实现 ApplicationContextAware 来注入上下文, 或者如果侦听器是bean,则可以使用 @Autowired 注入上下文。

2.1.7. Web环境

SpringApplication 尝试代表你创建正确的 ApplicationContext 类型。用于确定是 WebApplicationType 的算法非常简单:

  • 如果存在Spring MVC,则使用 AnnotationConfigServletWebServerApplicationContext

  • 如果不存在Spring MVC但存在Spring WebFlux,则使用 AnnotationConfigReactiveWebServerApplicationContext

  • 否则,将使用 AnnotationConfigApplicationContext

这意味着,如果你在同一应用程序中使用Spring MVC和Spring WebFlux中的新 WebClient,则默认情况下将使用Spring MVC。你可以通过调用 setWebApplicationType(WebApplicationType) 轻松覆盖它。

也可以通过调用 setApplicationContextClass(…​) 完全控制要使用的 ApplicationContext 类型。

在JUnit测试中使用 SpringApplication 时,通常希望调用 setWebApplicationType(WebApplicationType.NONE)

2.1.8. 访问应用程序参数

如果你需要访问传递给 SpringApplication.run(…​) 的应用程序参数, 则可以注入 org.springframework.boot.ApplicationArguments bean。ApplicationArguments 接口提供对原始 String[] 参数以及已解析的 optionnon-option 参数的访问,如以下示例所示:

import org.springframework.boot.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;

@Component
public class MyBean {

    @Autowired
    public MyBean(ApplicationArguments args) {
        boolean debug = args.containsOption("debug");
        List<String> files = args.getNonOptionArgs();
        // if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
    }

}
Spring Boot还向Spring Environment 注册了 CommandLinePropertySource。 这样,你还可以使用 @Value 注解注入单个应用程序参数。

2.1.9. 使用ApplicationRunner或CommandLineRunner

如果 SpringApplication 启动后需要运行一些特定的代码,则可以实现 ApplicationRunnerCommandLineRunner 接口。 这两个接口以相同的方式工作并提供一个 run 方法,该方法在 SpringApplication.run(…​) 完成之前被调用。

CommandLineRunner 接口以简单的字符串数组提供对应用程序参数的访问,而 ApplicationRunner 使用前面讨论的 ApplicationArguments 接口。以下示例显示了带有 run 方法的 CommandLineRunner

import org.springframework.boot.*;
import org.springframework.stereotype.*;

@Component
public class MyBean implements CommandLineRunner {

    public void run(String... args) {
        // Do something...
    }

}

如果定义了必须按特定顺序调用的几个 CommandLineRunnerApplicationRunner Beans,则可以另外实现 org.springframework.core.Ordered 接口或使用 org.springframework.core.annotation.Order 注解。

2.1.10. 应用程序退出

每个 SpringApplication 向JVM注册一个关闭钩子,以确保 ApplicationContext 在退出时正常关闭。 可以使用所有标准的Spring生命周期回调(例如:DisposableBean 接口或 @PreDestroy 注解)。

另外,如果bean希望在调用 SpringApplication.exit() 时返回特定的退出码, 则可以实现 org.springframework.boot.ExitCodeGenerator 接口。然后可以将此退出码传递给 System.exit(), 以将其作为状态码返回,如以下示例所示:

@SpringBootApplication
public class ExitCodeApplication {

    @Bean
    public ExitCodeGenerator exitCodeGenerator() {
        return () -> 42;
    }

    public static void main(String[] args) {
        System.exit(SpringApplication.exit(SpringApplication.run(ExitCodeApplication.class, args)));
    }

}

另外,ExitCodeGenerator 接口可以通过异常实现。遇到此类异常时,Spring Boot返回实现的 getExitCode() 方法提供的退出码。

2.1.11. 管理员功能

通过指定 spring.application.admin.enabled 属性,可以为应用程序启用与管理员相关的功能。 这将在平台MBeanServer上公开 SpringApplicationAdminMXBean。 你可以使用此功能来远程管理Spring Boot应用程序。此功能对于任何服务包装器实现也可能很有用。

如果你想知道应用程序在哪个HTTP端口上运行,请使用 local.server.port 键获取属性。

2.2. 外部化配置

Spring Boot使你可以外部化配置,以便可以在不同环境中使用相同的应用程序代码。你可以使用properties文件,YAML文件, 环境变量和命令行参数来外部化配置。可以使用 @Value 注解将属性值直接注入到你的bean中, 可以通过Spring的 Environment 抽象访问,也可以通过 @ConfigurationProperties 绑定到结构化对象

Spring Boot使用一个非常特殊的 PropertySource 顺序,该顺序旨在允许合理地覆盖值。按以下顺序考虑属性:

  1. 当devtools处于活动状态时,$HOME/.config/spring-boot 文件夹中的 Devtools全局设置属性

  2. 测试上的 @TestPropertySource注解。

  3. 测试中的properties属性。在 @SpringBootTest 和测试注解上可用, 用于测试应用程序的特定部分

  4. 命令行参数。

  5. 来自 SPRING_APPLICATION_JSON 的属性(嵌入在环境变量或系统属性中的嵌入式JSON)。

  6. ServletConfig 的初始化参数。

  7. ServletContext 的初始化参数。

  8. 来自 java:comp/env 的JNDI属性。

  9. Java系统属性(System.getProperties())。

  10. 操作系统环境变量。

  11. 一个 RandomValuePropertySource 仅具有 random.* 属性。

  12. 打包jar之外的特定于profile的应用程序属性application-{profile}.properties 和YAML变体)。

  13. 打包jar中的特定于profile的应用程序属性application-{profile}.properties 和YAML变体)。

  14. 打包jar之外的应用程序属性(application.properties 和YAML变体)。

  15. 打包jar中的应用程序属性(application.properties 和YAML变体)。

  16. @Configuration 类上的 @PropertySource注解。 请注意,在刷新应用程序上下文之前,不会将此类属性源添加到 Environment 中。现在配置某些属性 (如 logging.*spring.main.*)为时已晚,这些属性在刷新开始之前就已读取。

  17. 默认属性(通过设置 SpringApplication.setDefaultProperties 指定)。

为了提供一个具体的示例,假设你开发了一个使用 name 属性的 @Component,如以下示例所示:

import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;

@Component
public class MyBean {

    @Value("${name}")
    private String name;

    // ...

}

在你的应用程序类路径上(例如:在jar中),你可以拥有一个 application.properties 文件,该文件为 name 提供合理的默认属性值。在新环境中运行时,可以在jar外部提供一个覆盖 nameapplication.properties 文件。 对于一次性测试,可以使用特定的命令行开关启动(例如:java -jar app.jar --name="Spring")。

可以在命令行中使用环境变量来提供 SPRING_APPLICATION_JSON 属性。例如,你可以在UN*X shell中使用以下行:

$ SPRING_APPLICATION_JSON='{"acme":{"name":"test"}}' java -jar myapp.jar

在前面的示例中,你最终在Spring Environment 中获得了 acme.name=test。你还可以在System属性中将JSON作为 spring.application.json 提供,如以下示例所示:

$ java -Dspring.application.json='{"name":"test"}' -jar myapp.jar

你还可以使用命令行参数来提供JSON,如以下示例所示:

$ java -jar myapp.jar --spring.application.json='{"name":"test"}'

你还可以将JSON作为JNDI变量提供,如下所示: java:comp/env/spring.application.json

2.2.1. 配置随机值

RandomValuePropertySource 可用于注入随机值(例如:注入密钥或测试用例)。它可以产生整数,longs,uuid或字符串,如以下示例所示:

my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}

random.int* 语法是 OPEN value (,max) CLOSE,其中 OPEN,CLOSE 是任何字符, 而 value,max 是整数。如果提供了 max,则 value 是最小值,而 max 是最大值(不包括它)。

2.2.2. 访问命令行Properties

默认情况下,SpringApplication 将所有命令行选项参数(即以 -- 开头的参数,例如 --server.port=9000)转换为属性, 并将其添加到Spring Environment 中。如前所述,命令行属性始终优先于其他属性源。

如果你不希望将命令行属性添加到环境中,可以使用 SpringApplication.setAddCommandLineProperties(false) 禁用它们。

2.2.3. 应用程序属性文件

SpringApplication 在以下位置从 application.properties 文件加载属性,并将它们添加到Spring Environment

  1. 当前目录的 /config 子目录

  2. 当前目录

  3. 类路径下的 /config 目录

  4. 类路径根目录

该列表按优先级排序(列表前面定义的属性会覆盖后面的)。

你还可以使用YAML ('.yml')文件来替代 '.properties'。

如果你不喜欢 application.properties 作为配置文件名,则可以通过指定 spring.config.name 环境属性来切换到另一个文件名。 你还可以通过使用 spring.config.location 环境属性(这是目录位置或以逗号分隔的文件路径列表)来显式引用位置。 下面的示例演示如何指定其他文件名:

$ java -jar myproject.jar --spring.config.name=myproject

The following example shows how to specify two locations:

$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
spring.config.namespring.config.location 很早就被用于确定必须加载的文件。 必须将它们定义为环境属性(通常是操作系统环境变量,系统属性或命令行参数)。

配置位置以相反的顺序搜索。默认情况下,配置的位置是 classpath:/,classpath:/config/,file:./,file:./config/。结果搜索顺序如下:

  1. file:./config/

  2. file:./

  3. classpath:/config/

  4. classpath:/

使用 spring.config.location 配置自定义配置位置后,它们将替换默认位置。例如:如果 spring.config.location 配置为值 classpath:custom-config/,file:./custom-config/,则搜索顺序如下:

  1. file:./custom-config/

  2. classpath:custom-config/

另外,当使用 spring.config.additional-location 配置自定义配置位置时,除默认位置外,还会考虑使用它们。 在默认位置之前搜索其他附加位置。例如:如果配置了 classpath:/custom-config/,file:./custom-config/ 的附加位置,则搜索顺序如下:

  1. file:./custom-config/

  2. classpath:custom-config/

  3. file:./config/

  4. file:./

  5. classpath:/config/

  6. classpath:/

通过此搜索顺序,你可以在一个配置文件中指定默认值,然后在另一个配置文件中有选择地覆盖这些值。 你可以在默认位置之一的 application.properties(或使用 spring.config.name 选择的其他任何基本名称)中为应用程序提供默认值。 然后,可以在运行时使用自定义位置之一中的其他文件覆盖这些默认值。

如果使用环境变量而不是系统属性,则大多数操作系统都不允许使用句点分隔的键名,但是可以使用下划线 (例如:使用 SPRING_CONFIG_NAME 代替 spring.config.name)。
如果你的应用程序在容器中运行,则可以使用JNDI属性(在 java:comp/env 中)或servlet上下文初始化参数代替环境变量或系统属性。

2.2.4. 特定于Profile的Properties

除了 application.properties 文件之外,还可以使用以下命名约定来定义特定于profile的属性: application-{profile}.properties。如果没有设置激活的profile,则 Environment 具有一组默认的profiles(默认为 [default])。换句话说,如果未显式激活任何profiles,那么将从 application-default.properties 中加载属性。

特定于profile的属性是从与标准 application.properties 相同的位置加载的,特定于profile的文件始终会覆盖非特定文件, 而无论特定于profile的文件是位于打包jar的内部还是外部。

如果指定了多个profiles,则采用最后一个获胜策略。例如:将 spring.profiles.active 属性指定的profiles添加到通过SpringApplication API配置的profiles之后,因此具有优先权。

如果你在 spring.config.location 中指定了任何文件,则不会考虑这些文件特定于profile的变体。 如果你还想使用特定于profile的属性,请使用 spring.config.location 中的目录。

2.2.5. Properties中的占位符

application.properties 中的值在使用时会通过现有的 Environment 进行过滤,因此你可以参考在它之前定义的值(例如:从System属性中)。

app.name=MyApp
app.description=${app.name} is a Spring Boot application
你还可以使用这种技术来创建现有Spring Boot属性的“简短”变体。有关详细信息,请参见 使用“简短”命令行参数方法

2.2.6. 加密Properties

Spring Boot不提供对加密属性值的任何内置支持,但是,它确实提供了修改Spring Environment 中包含的值所必需的钩子。 EnvironmentPostProcessor 界面允许你在应用程序启动之前操纵 Environment。 有关详细信息,请参见 在启动前自定义环境或ApplicationContext

如果你正在寻找一种安全的方式来存储凭据和密码, Spring Cloud Vault 项目提供了对在 HashiCorp Vault中存储外部配置的支持。

2.2.7. 使用YAML代替Properties

YAML是一个JSON超集,因此是一种用于指定层次结构配置数据的便捷格式。只要在类路径上具有 SnakeYAML库, SpringApplication 类就会自动支持YAML作为Properties的替代方法。

如果你使用“启动器”,则 spring-boot-starter 会自动提供SnakeYAML。
加载YAML

Spring Framework提供了两个方便的类,可用于加载YAML文档。YamlPropertiesFactoryBean 将YAML作为 Properties 加载, 而 YamlMapFactoryBean 将YAML作为 Map 加载。

例如:考虑以下YAML文档:

environments:
    dev:
        url: https://dev.example.com
        name: Developer Setup
    prod:
        url: https://another.example.com
        name: My Cool App

前面的示例将转换为以下属性:

environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App

YAML列表用 [index] 解引用器表示为属性键。例如:考虑以下YAML:

my:
   servers:
       - dev.example.com
       - another.example.com

前面的示例将转换为以下属性:

my.servers[0]=dev.example.com
my.servers[1]=another.example.com

要通过使用Spring Boot的 Binder 实用程序(@ConfigurationProperties 所做的)绑定到类似的属性, 你需要在目标bean中拥有一个类型为 java.util.List(或 Set)属性,或者你需要提供一个setter或使用可变值对其进行初始化。 例如,以下示例绑定到前面显示的属性:

@ConfigurationProperties(prefix="my")
public class Config {

    private List<String> servers = new ArrayList<String>();

    public List<String> getServers() {
        return this.servers;
    }
}
在Spring环境中将YAML公开为Properties

YamlPropertySourceLoader 类可用于在Spring Environment 中将YAML公开为 PropertySource。 这样做可以让你使用 @Value 注解和占位符语法来访问YAML属性。

Multi-profile的YAML文档

你可以使用 spring.profiles 键在一个文件中指定多个特定于profile的YAML文档,以指示何时应用该文档,如以下示例所示:

server:
    address: 192.168.1.100
---
spring:
    profiles: development
server:
    address: 127.0.0.1
---
spring:
    profiles: production & eu-central
server:
    address: 192.168.1.120

在前面的示例中,如果 development profile处于激活状态,则 server.address 属性为 127.0.0.1。 同样,如果 production eu-central profile处于激活状态,则 server.address 属性为 192.168.1.120。 如果 启用 development, productioneu-central profiles,则该属性的值为 192.168.1.100

因此 spring.profiles 可以包含一个简单的profile名称(例如:production)或profile表达式。 profile表达式允许表达更复杂的profile逻辑,例如:production & (eu-central | eu-west)。有关更多详细信息,请参阅 参考指南

如果在启动应用程序上下文时未明确激活任何profiles,则会激活默认的profiles。因此,在以下YAML中,我们为 spring.security.user.password 设置了一个值,该值 在 "default" profile中可用:

server:
  port: 8000
---
spring:
  profiles: default
  security:
    user:
      password: weak

而在以下示例中,则会始终设置密码是因为该密码未附加到任何profile,并且必须根据需要在所有其他profiles中将其显式重置:

server:
  port: 8000
spring:
  security:
    user:
      password: weak

使用 spring.profiles 元素指定的Spring profiles可以选择使用 ! 字符来否定。如果为单个文档指定了否定的和非否定的profiles, 则至少一个非否定的profile必须匹配,并且否定的profiles不能匹配。

YAML的缺点

无法使用 @PropertySource 注解加载YAML文件。因此,在需要以这种方式加载值的情况下,需要使用properties文件。

在特定于profile的YAML文件中使用多YAML文档语法可能会导致意外行为。例如:考虑文件中的以下配置:

application-dev.yml
server:
  port: 8000
---
spring:
  profiles: "!test"
  security:
    user:
      password: "secret"

如果使用参数 --spring.profiles.active=dev 运行该应用程序,则可能希望将 security.user.password 设置为“secret”,但事实并非如此。

嵌套文档将被过滤,因为主文件名为 application-dev.yml。它已经被认为是特定于profile的,并且嵌套文档将被忽略。

我们建议你不要混用特定于profile的YAML文件和多个YAML文档。坚持只使用其中之一。

2.2.8. 类型安全的配置Properties

使用 @Value("${property}") 注解来注入配置属性有时会很麻烦,尤其是当你使用多个properties或数据本质上是分层的时。 Spring Boot提供了一种使用属性的替代方法,使用强类型的properties bean来管理和验证应用程序的配置。

JavaBean properties绑定

可以绑定一个声明标准JavaBean属性的bean,如以下示例所示:

package com.example;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("acme")
public class AcmeProperties {

    private boolean enabled;

    private InetAddress remoteAddress;

    private final Security security = new Security();

    public boolean isEnabled() { ... }

    public void setEnabled(boolean enabled) { ... }

    public InetAddress getRemoteAddress() { ... }

    public void setRemoteAddress(InetAddress remoteAddress) { ... }

    public Security getSecurity() { ... }

    public static class Security {

        private String username;

        private String password;

        private List<String> roles = new ArrayList<>(Collections.singleton("USER"));

        public String getUsername() { ... }

        public void setUsername(String username) { ... }

        public String getPassword() { ... }

        public void setPassword(String password) { ... }

        public List<String> getRoles() { ... }

        public void setRoles(List<String> roles) { ... }

    }
}

前面的POJO定义了以下属性:

  • acme.enabled,默认值为 false

  • acme.remote-address,其类型可以从 String 强制转换。

  • acme.security.username,带有嵌套的“security”对象,其名称由属性名称确定。 特别是,返回类型根本没有使用,也可能是 SecurityProperties

  • acme.security.password

  • acme.security.roles,带有默认拥有单个 USERString 集合。

Spring Boot自动配置大量使用 @ConfigurationProperties 来轻松配置自动配置的bean。 与自动配置类相似,Spring Boot中可用的 @ConfigurationProperties 类仅供内部使用。 通过Properties文件、YAML文件、环境变量等配置映射到的类属性是公共API,但是该类本身的内容并不意味着可以直接使用。

这种自动配置依赖于默认的空构造函数,并且getter和setter通常是强制性的,因为绑定是通过标准Java Beans属性描述符进行的, 就像在Spring MVC中一样。在以下情况下,可以忽略setter:

  • Maps,只要它们被初始化,需要一个getter但不一定是setter,因为绑定器可以对它们进行修改。

  • 可以通过索引(通常使用YAML)或使用单个逗号分隔的值(properties)来访问集合和数组。 在后一种情况下,必须使用setter。我们建议始终为此类类型添加setter。如果初始化集合,请确保它不是不可变的(如上例所示)。

  • 如果初始化了嵌套的POJO属性(如前面示例中的 Security 字段),则不需要setter。 如果希望绑定器通过使用其默认构造函数动态创建实例,则需要一个setter。

有些人使用Lombok项目自动添加getters和setters。确保Lombok不会为这种类型生成任何特定的构造函数,因为容器会自动使用它来实例化该对象。

最后,仅考虑标准Java Bean属性,不支持对静态属性的绑定。

构造函数绑定

上一节中的示例可以用不可变的方式重写,如下例所示:

package com.example;

import java.net.InetAddress;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.DefaultValue;

@ConstructorBinding
@ConfigurationProperties("acme")
public class AcmeProperties {

    private final boolean enabled;

    private final InetAddress remoteAddress;

    private final Security security;

    public AcmeProperties(boolean enabled, InetAddress remoteAddress, Security security) {
        this.enabled = enabled;
        this.remoteAddress = remoteAddress;
        this.security = security;
    }

    public boolean isEnabled() { ... }

    public InetAddress getRemoteAddress() { ... }

    public Security getSecurity() { ... }

    public static class Security {

        private final String username;

        private final String password;

        private final List<String> roles;

        public Security(String username, String password,
                @DefaultValue("USER") List<String> roles) {
            this.username = username;
            this.password = password;
            this.roles = roles;
        }

        public String getUsername() { ... }

        public String getPassword() { ... }

        public List<String> getRoles() { ... }

    }

}

在此设置中,@ConstructorBinding 注解用于指示应使用构造函数绑定。这意味着绑定器将期望找到带有你希望绑定的参数的构造函数。

@ConstructorBinding 类的嵌套成员(例如上例中的 Security)也将通过其构造函数进行绑定。

可以使用 @DefaultValue 指定默认值,并且将应用相应的转换服务将 String 值强制转换为缺失属性的目标类型。

要使用构造函数绑定,必须使用 @EnableConfigurationProperties 或配置属性扫描来启用该类。你不能对通过常规Spring机制创建的bean 使用构造函数绑定(例如:@Component bean,通过 @Bean 方法创建的bean或使用 @Import 加载的bean)。
如果你的类具有多个构造函数,则还可以直接在应绑定的构造函数上使用 @ConstructorBinding
启用被 @ConfigurationProperties 注解的类型

Spring Boot提供了绑定 @ConfigurationProperties 类型并将其注册为Bean的基础设施。 你可以逐类启用配置属性,也可以启用与组件扫描类似的方式进行配置属性扫描。

有时,用 @ConfigurationProperties 注解的类可能不适用于扫描,例如:如果你正在开发自己的自动配置, 或者想要有条件地启用它们。在这些情况下,请使用 @EnableConfigurationProperties 注解指定要处理的类型列表。 可以在任何 @Configuration 类上完成此操作,如以下示例所示:

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}

要使用配置属性扫描,请将 @ConfigurationPropertiesScan 注解添加到你的应用程序。 通常,它被添加到使用 @SpringBootApplication 注解的主应用程序类中,但可以将其添加到任何 @Configuration 类中。 默认情况下,将从声明注解的类的包中进行扫描。如果要定义待扫描的特定程序包,可以按照以下示例所示进行操作:

@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "org.acme.another" })
public class MyApplication {
}

When the @ConfigurationProperties bean is registered using configuration property scanning or via @EnableConfigurationProperties, the bean has a conventional name: <prefix>-<fqn>, where <prefix> is the environment key prefix specified in the @ConfigurationProperties annotation and <fqn> is the fully qualified name of the bean. If the annotation does not provide any prefix, only the fully qualified name of the bean is used.

使用配置属性扫描或通过 @EnableConfigurationProperties 注册 @ConfigurationProperties Bean时, 该Bean具有常规名称:<prefix>-<fqn>,其中 <prefix>@ConfigurationProperties 注解中指定的环境键前缀。 <fqn> 是Bean的完全限定名称。如果注解不提供任何前缀,则仅使用Bean的完全限定名称。

上例中的bean名称是 acme-com.example.AcmeProperties

我们建议 @ConfigurationProperties 仅处理环境,尤其不要从上下文中注入其他bean。 对于极端情况,可以使用setter注入或框架提供的任何 *Aware 接口(例如:需要访问 EnvironmentEnvironmentAware)。 如果仍然想使用构造函数注入其他bean,则必须使用 @Component 注解配置properties bean,并使用基于JavaBean的属性绑定。

使用被 @ConfigurationProperties 注解的类型

这种配置方式在 SpringApplication 外部的YAML配置中特别好用,如以下示例所示:

# application.yml

acme:
    remote-address: 192.168.1.1
    security:
        username: admin
        roles:
          - USER
          - ADMIN

# additional configuration as required

要与 @ConfigurationProperties Bean一起使用,可以像其他任何Bean一样注入它们,如以下示例所示:

@Service
public class MyService {

    private final AcmeProperties properties;

    @Autowired
    public MyService(AcmeProperties properties) {
        this.properties = properties;
    }

     //...

    @PostConstruct
    public void openConnection() {
        Server server = new Server(this.properties.getRemoteAddress());
        // ...
    }

}
使用 @ConfigurationProperties 还可让你生成元数据文件,IDE可以使用这些元数据文件为你自己的键提供自动完成功能。 有关详细信息,请参见 附录
第三方配置

除了使用 @ConfigurationProperties 注解类外,还可以在public @Bean 方法上使用它。当你要将属性绑定到控件之外的第三方组件时,这样做特别有用。

要从 Environment 属性配置Bean,请将 @ConfigurationProperties 添加到其Bean注册中,如以下示例所示:

@ConfigurationProperties(prefix = "another")
@Bean
public AnotherComponent anotherComponent() {
    ...
}

another 前缀定义的任何JavaBean属性都以类似于前面的 AcmeProperties 示例的方式映射到该 AnotherComponent bean。

宽松绑定

Spring Boot使用一些宽松的规则将 Environment 属性绑定到 @ConfigurationProperties bean, 因此 Environment 属性名称和bean属性名称之间不需要完全匹配。有用的常见示例包括:以破折号分隔的环境属性 (例如:context-path 绑定到 contextPath)和大写的环境属性(例如:PORT 绑定到 port)。

例如:考虑以下 @ConfigurationProperties 类:

@ConfigurationProperties(prefix="acme.my-project.person")
public class OwnerProperties {

    private String firstName;

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

}

使用前面的代码,以下属性名称均可以使用:

Table 5. 宽松绑定
属性 说明

acme.my-project.person.first-name

Kebab格式,建议在 .properties.yml 文件中使用。

acme.myProject.person.firstName

标准小驼峰式语法。

acme.my_project.person.first_name

下划线表示法,是 .properties.yml 文件中使用的另一种格式。

ACME_MYPROJECT_PERSON_FIRSTNAME

大写格式,使用系统环境变量时建议使用。

注解的前缀值 必须 为kebab格式(小写,并用 - 分隔,例如:acme.my-project.person)。
Table 6. 每个属性源的宽松绑定规则
属性源 支持 列表

Properties文件

小驼峰,kebab或下划线表示法

使用 [] 或逗号分隔值的标准列表语法

YAML文件

小驼峰,kebab或下划线表示法

Standard YAML list syntax or comma-separated values

环境变量

以下划线作为定界符的大写格式。_ 不应在属性名称中使用

下划线包围的数值,例如:MY_ACME_1_OTHER = my.acme[1].other

系统属性

小驼峰,kebab或下划线表示法

使用 [] 或逗号分隔值的标准列表语法

我们建议,如果可能,属性以小写kebab格式存储,例如:my.property-name=acme

绑定到 Map 属性时,如果 key 包含小写字母数字字符或 - 以外的任何其他字符,则需要使用方括号表示法,以便保留原始值。 如果键没有被 [] 包围,则所有非字母数字或 - 字符都将被删除。例如,考虑将以下属性绑定到 Map

acme:
  map:
    "[/key1]": value1
    "[/key2]": value2
    /key3: value3

上面的属性将以 /key1/key2key3 作为映射中的键被绑定到 Map

对于YAML文件,方括号需要用引号引起来,以便正确解析。
合并复杂类型

如果在多个地方配置了列表,则通过替换整个列表来进行覆盖。

例如:假设 MyPojo 对象的 namedescription 属性默认为 null。 下面的示例从 AcmeProperties 公开 MyPojo 对象的列表:

@ConfigurationProperties("acme")
public class AcmeProperties {

    private final List<MyPojo> list = new ArrayList<>();

    public List<MyPojo> getList() {
        return this.list;
    }

}

考虑以下配置:

acme:
  list:
    - name: my name
      description: my description
---
spring:
  profiles: dev
acme:
  list:
    - name: my another name

如果 dev profile未处于激活状态,则 AcmeProperties.list 包含一个 MyPojo 条目,如先前所定义。 但是,如果启用了 dev profile,则该列表仍然仅包含一个条目(名称为 my another name,并且描述为 null)。 此配置 不会 将第二个 MyPojo 实例添加到列表中,并且不会合并条目。

在多个profiles中指定 List 时,将使用优先级最高的列表(并且仅使用那个列表)。考虑以下示例:

acme:
  list:
    - name: my name
      description: my description
    - name: another name
      description: another description
---
spring:
  profiles: dev
acme:
  list:
    - name: my another name

在前面的示例中,如果 dev profile处于激活状态,则 AcmeProperties.list 包含一个 MyPojo 条目 (其名称为 my another name,并且描述为 null)。对于YAML,可以使用逗号分隔的列表和YAML列表来完全覆盖列表的内容。

对于 Map 属性,可以绑定从多个来源绘制的属性值。但是,对于多个源中的同一属性,将使用优先级最高的属性。 下面的示例从 AcmeProperties 公开 Map<String, MyPojo>

@ConfigurationProperties("acme")
public class AcmeProperties {

    private final Map<String, MyPojo> map = new HashMap<>();

    public Map<String, MyPojo> getMap() {
        return this.map;
    }

}

考虑以下配置:

acme:
  map:
    key1:
      name: my name 1
      description: my description 1
---
spring:
  profiles: dev
acme:
  map:
    key1:
      name: dev name 1
    key2:
      name: dev name 2
      description: dev description 2

如果 dev profile未处于激活状态,则 AcmeProperties.map 包含一个键为key1的条目(名称为 my name 1,描述为 my description 1)。 但是,如果启用了 dev profile,则map包含两个条目,其中键为key1的条目(名称为 dev name 1,描述为 my description 1) 和key2(名称为 dev name 2,描述为 dev description 2)。

前述合并规则不仅适用于YAML文件,而且适用于所有属性源中的属性。
属性转换

当Spring Boot绑定到 @ConfigurationProperties bean时,它尝试将外部应用程序属性强制为正确的类型。 如果需要自定义类型转换,则可以提供一个 ConversionService bean(具有一个名为 conversionService 的bean) 或自定义属性编辑器(通过 CustomEditorConfigurer bean)或自定义 Converters(具有定义为 @ConfigurationPropertiesBinding 的bean定义)。

由于在应用程序生命周期中非常早就请求了此bean,因此请确保限制你的 ConversionService 使用的依赖项。 通常,你需要的任何依赖项可能在创建时未完全初始化。如果配置键强制转换不需要自定义的转换服务,则可能要重命名自定义的 ConversionService 且它仅依赖于具有 @ConfigurationPropertiesBinding 限定的自定义转换器。
转换持续时间

Spring Boot为表达持续时间提供了专门的支持。如果公开 java.time.Duration 属性,则应用程序属性中的以下格式可用:

  • 常规的 long 表示形式(使用毫秒作为默认单位,除非已指定 @DurationUnit

  • java.time.Duration 使用的标准ISO-8601格式

  • 值和单位相结合的更易读的格式(例如:10s表示10秒)

考虑以下示例:

@ConfigurationProperties("app.system")
public class AppSystemProperties {

    @DurationUnit(ChronoUnit.SECONDS)
    private Duration sessionTimeout = Duration.ofSeconds(30);

    private Duration readTimeout = Duration.ofMillis(1000);

    public Duration getSessionTimeout() {
        return this.sessionTimeout;
    }

    public void setSessionTimeout(Duration sessionTimeout) {
        this.sessionTimeout = sessionTimeout;
    }

    public Duration getReadTimeout() {
        return this.readTimeout;
    }

    public void setReadTimeout(Duration readTimeout) {
        this.readTimeout = readTimeout;
    }

}

要指定30秒的会话超时,则 30PT30S30s 都是等效的。可以使用以下任意形式指定500ms的读取超时: 500PT0.5S500ms

你也可以使用任何受支持的单位:

  • ns 纳秒

  • us 微秒

  • ms 毫秒

  • s

  • m 分钟

  • h 小时

  • d

默认单位是毫秒,可以使用 @DurationUnit 覆盖,如上面的示例所示。

如果你要从仅使用 Long 表示持续时间的先前版本进行升级,原单位若不是毫秒那么请确保在切换到 Duration 时指定单位(使用 @DurationUnit)。这样做可以提供透明的升级路径,同时支持更丰富的格式。
转换数据大小

Spring Framework具有 DataSize 值类型,以字节为单位表示大小。如果公开 DataSize 属性,则应用程序属性中的以下格式可用:

  • 常规的 long 表示形式(除非已指定 @DataSizeUnit,否则使用字节作为默认单位)

  • 值和单位耦合在一起的更易读的格式(例如:10MB表示10兆字节)

考虑以下示例:

@ConfigurationProperties("app.io")
public class AppIoProperties {

    @DataSizeUnit(DataUnit.MEGABYTES)
    private DataSize bufferSize = DataSize.ofMegabytes(2);

    private DataSize sizeThreshold = DataSize.ofBytes(512);

    public DataSize getBufferSize() {
        return this.bufferSize;
    }

    public void setBufferSize(DataSize bufferSize) {
        this.bufferSize = bufferSize;
    }

    public DataSize getSizeThreshold() {
        return this.sizeThreshold;
    }

    public void setSizeThreshold(DataSize sizeThreshold) {
        this.sizeThreshold = sizeThreshold;
    }

}

若要指定10 MB的缓冲区大小,则 1010MB 是等效的。256个字节大小的阈值可以指定为 256256B

你也可以使用任何受支持的单位:

  • B 字节

  • KB 千字节

  • MB 兆字节

  • GB 千兆字节

  • TB 兆兆字节

默认单位是字节,可以使用 @DataSizeUnit 覆盖,如上面的示例所示。

如果要从仅使用 Long 表示大小的先前版本进行升级,原单位若不是字节那么请确保在切换到 DataSize 时指定单位(使用 @DataSizeUnit)。这样做可以提供透明的升级路径,同时支持更丰富的格式。
@ConfigurationProperties验证

每当使用Spring的 @Validated 注解对 @ConfigurationProperties 类进行批注时, Spring Boot就会尝试对其进行验证。你可以在配置类上直接使用JSR-303 javax.validation 约束注解。 为此,请确保在类路径上有兼容的JSR-303实现,然后将约束注解添加到字段中,如以下示例所示:

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {

    @NotNull
    private InetAddress remoteAddress;

    // ... getters and setters

}
你还可以通过使用 @Validated 注解创建配置属性的 @Bean 方法来触发验证。

为了确保始终为嵌套属性触发验证,即使未找到任何属性,也必须使用 @Valid 注解关联的字段。下面的示例基于前面的 AcmeProperties 示例:

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {

    @NotNull
    private InetAddress remoteAddress;

    @Valid
    private final Security security = new Security();

    // ... getters and setters

    public static class Security {

        @NotEmpty
        public String username;

        // ... getters and setters

    }

}

你还可以通过创建一个名为 configurationPropertiesValidator 的bean定义来添加自定义Spring Validator@Bean 方法应声明为 static。配置属性验证器是在应用程序生命周期的早期创建的, 并且将 @Bean 方法声明为 static 可以使创建该bean而不必实例化 @Configuration 类。这样做避免了由早期实例化引起的任何问题。

spring-boot-actuator 模块包括一个公开所有 @ConfigurationProperties beans的端点。 将你的Web浏览器指向 /actuator/configprops 或使用等效的JMX端点访问。有关详细信息,请参见“ 生产就绪功能”部分。
@ConfigurationProperties vs @Value

@Value 注解是核心容器功能,它没有提供与类型安全的配置属性相同的功能。 下表总结了 @ConfigurationProperties@Value 支持的功能:

功能 @ConfigurationProperties @Value

宽松绑定

Yes

No

元数据支持

Yes

No

SpEL 评估

No

Yes

如果你为自己的组件定义了一组配置键,我们建议你将它们组合在以 @ConfigurationProperties 注解的POJO中。 你还应该意识到,由于 @Value 不支持宽松的绑定,因此如果你需要使用环境变量来提供值,则它不是一个很好的选择。

最后,尽管你可以在 @Value 中编写SpEL表达式,但不会从应用程序属性文件中处理此类表达式。

2.3. Profiles

Spring Profiles提供了一种隔离应用程序配置部分并使之仅在某些环境中可用的方法。 任何 @Component@Configuration@ConfigurationProperties 都可以用 @Profile 标记以限制其加载时间,如以下示例所示:

@Configuration(proxyBeanMethods = false)
@Profile("production")
public class ProductionConfiguration {

    // ...

}
如果 @ConfigurationProperties Bean是通过 @EnableConfigurationProperties 而非自动扫描注册的, 则需要在具有 @EnableConfigurationProperties 注解的 @Configuration 类上指定 @Profile 注解。 在自动扫描 @ConfigurationProperties 的情况下,可以在 @ConfigurationProperties 类本身上指定 @Profile

你可以使用 spring.profiles.active 环境属性来指定哪些配置文件处于激活状态。你可以通过本章前面介绍的任何方式指定属性。 例如,你可以将其包含在 application.properties 中,如以下示例所示:

spring.profiles.active=dev,hsqldb

你也可以使用以下开关在命令行上指定它:--spring.profiles.active=dev,hsqldb

2.3.1. 添加活动Profiles

spring.profiles.active 属性遵循与其他属性相同的排序规则:最高的 PropertySource 获胜。这意味着你可以在 application.properties 中指定要激活配置文件,然后使用命令行开关 替换 它们。

有时,将特定于profile的属性 添加 到活动profiles而不是替换它们很有用。 spring.profiles.include 属性可用于无条件添加活动Profiles。SpringApplication 入口点还具有Java API, 用于设置其他附加的profiles(即在由 spring.profiles.active 属性激活的profiles之上)。 参见 SpringApplication中的 setAdditionalProfiles() 方法。

例如,当使用开关 --spring.profiles.active=prod 运行具有以下属性的应用程序时,proddbprodmq 配置文件也会被激活:

---
my.property: fromyamlfile
---
spring.profiles: prod
spring.profiles.include:
  - proddb
  - prodmq
请记住,可以在YAML文档中定义 spring.profiles 属性,以确定该特定文档何时包含在配置中。有关更多详细信息,请参见 根据环境更改配置

2.3.2. 以编程方式设置Profiles

你可以在应用程序运行之前通过调用 SpringApplication.setAdditionalProfiles(…​) 以编程方式设置活动配置文件。 也可以使用Spring的 ConfigurableEnvironment 接口来激活profiles。

2.3.3. 特定于Profile的配置文件

application.properties(或 application.yml)和通过 @ConfigurationProperties 所引用文件的特定于profile的变体都会被视为配置文件并加载。 有关详细信息,请参见“特定于Profile的Properties”。

2.4. 日志

Spring Boot使用 Commons Logging进行所有内部日志记录,但是使底层日志实现保持打开状态。 提供了 Java Util LoggingLog4J2Logback的默认配置。 在每种情况下,日志记录器都已预先配置为使用控制台输出,同时还提供可选的文件输出。

默认情况下,如果使用“Starters”,则使用Logback进行日志记录。还包括适当的Logback路由,以确保使用 Java Util Logging,Commons Logging,Log4J或SLF4J的从属库都可以正常工作。

Java有许多可用的日志记录框架。如果上面的列表看起来令人困惑,请不要担心。 通常,你不需要更改日志记录依赖项,并且Spring Boot默认值可以正常工作。
将应用程序部署到Servlet容器或应用程序服务器时,通过Java Util Logging API执行的日志记录不会路由到应用程序的日志中。 这样可以防止容器或其他已部署到容器中的应用程序执行的日志记录出现在应用程序的日志中。

2.4.1. 日志格式

Spring Boot的默认日志输出类似于以下示例:

2019-03-05 10:57:51.112  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52
2019-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1358 ms
2019-03-05 10:57:51.698  INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2019-03-05 10:57:51.702  INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]

默认输出以下条目:

  • 日期和时间:毫秒精度,易于分类。

  • 日志级别:ERROR, WARN, INFO, DEBUGTRACE

  • 进程ID。

  • --- 分隔符用于区分实际日志消息的开始。

  • 线程名:用方括号括起来(对于控制台输出,可能会被截断)。

  • 记录器名称:这通常是源类名称(通常是缩写格式)。

  • 日志消息。

Logback没有 FATAL 日志级别。它被映射到 ERROR

2.4.2. 控制台输出

默认日志配置在消息写入时将消息回显到控制台。默认情况下,将记录 ERROR 级别,WARN 级别和 INFO 级别的消息。 你还可以通过使用 --debug 标志启动应用程序来启用“debug”模式。

$ java -jar myapp.jar --debug
你还可以在 application.properties 中指定 debug=true

启用调试模式后,将配置一些核心日志记录器(嵌入式容器,Hibernate和Spring Boot)以输出更多信息。 启用调试模式 不会 将你的应用程序配置为记录所有具有 DEBUG 级别的消息。

或者,你可以通过使用 --trace 标志(或 application.properties 中的 trace=true)启动应用程序来启用“trace”模式。 这样做可以为某些核心记录器(嵌入式容器,Hibernate schema生成以及整个Spring产品组合)启用跟踪记录。

颜色编码输出

如果你的终端支持ANSI,则使用彩色输出来提高可读性。你可以将 spring.output.ansi.enabled 设置为 支持的值,以覆盖自动检测。

使用 %clr 转换字配置颜色编码。转换器以最简单的形式根据日志级别为输出着色,如以下示例所示:

%clr(%5p)

下表描述了日志级别到颜色的映射:

Level Color

FATAL

红色

ERROR

红色

WARN

黄色

INFO

绿色

DEBUG

绿色

TRACE

绿色

另外,你可以通过将其提供为转换的选项来指定应使用的颜色或样式。例如:要使文本变黄,请使用以下设置:

%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}

支持以下颜色和样式:

  • blue

  • cyan

  • faint

  • green

  • magenta

  • red

  • yellow

2.4.3. 文件输出

默认情况下,Spring Boot仅记录到控制台,不写日志文件。如果除了控制台输出外还想写日志文件, 则需要设置 logging.file.namelogging.file.path 属性(例如:在 application.properties 中)。

下表显示了如何结合使用 logging.* 属性:

Table 7. 日志属性
logging.file.name logging.file.path 示例 描述

(none)

(none)

仅控制台记录。

特定文件

(none)

my.log

写入指定的日志文件。名称可以是确切位置,也可以是相对于当前目录的位置。

(none)

特定目录

/var/log

spring.log 写入指定目录。名称可以是确切位置,也可以是相对于当前目录的位置。

日志文件达到10 MB时会旋转,并且与控制台输出一样,默认情况下会记录 ERROR 级别,WARN 级别和 INFO 级别的消息。 可以使用 logging.file.max-size 属性更改大小限制。除非已设置 logging.file.max-history 属性, 否则以前旋转的文件将无限期存档。可以使用 logging.file.total-size-cap 限制日志归档文件的总大小。 当日志归档的总大小超过该阈值时,将删除备份。要在应用程序启动时强制清除日志归档文件, 请使用 logging.file.clean-history-on-start 属性。

日志记录属性独立于实际的日志记录基础设施。因此,特定的配置键(例如:Logback的 logback.configurationFile)不是由Spring Boot管理的。

2.4.4. 日志级别

通过使用 logging.level.<logger-name>=<level> 可以在Spring Environment 中(例如:在 application.properties 中) 设置所有受支持的日志记录器级别。其中 level 是TRACE, DEBUG, INFO, WARN, ERROR, FATAL 或 OFF。 可以使用 logging.level.root 配置 root 记录器。

以下示例显示了 application.properties 中的潜在日志记录设置:

logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error

也可以使用环境变量设置日志记录级别。例如:LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG 会将 org.springframework.web 设置为 DEBUG

以上方法仅适用于程序包级别的日志记录。由于宽松的绑定总是将环境变量转换为小写,因此无法以这种方式为单个类配置日志记录。 如果需要为类配置日志记录,则可以使用SPRING_APPLICATION_JSON变量。

2.4.5. 日志组

能够将相关记录器分组在一起通常是很有用的,以便可以同时配置它们。例如:你可能通常会更改 所有 与Tomcat相关的记录器的日志级别,但是你不容易记住顶层软件包。

为了解决这个问题,Spring Boot允许你在Spring Environment 中定义日志记录组。例如:以下是通过将“tomcat”组添加到 application.properties 来定义它的方法:

logging.group.tomcat=org.apache.catalina, org.apache.coyote, org.apache.tomcat

定义后,你可以仅使用一行就更改该组中所有记录器的日志级别:

logging.level.tomcat=TRACE

Spring Boot包含以下预定义的日志记录组,它们可以直接使用:

名称 记录器

web

org.springframework.core.codec, org.springframework.http, org.springframework.web, org.springframework.boot.actuate.endpoint.web, org.springframework.boot.web.servlet.ServletContextInitializerBeans

sql

org.springframework.jdbc.core, org.hibernate.SQL, org.jooq.tools.LoggerListener

2.4.6. 自定义日志配置

可以通过在类路径中包括适当的库来激活各种日志记录系统,并可以通过在类路径的根目录中或在以下Spring Environment 属性指定的位置中提供适当的配置文件来进一步自定义日志文件:logging.config

你可以通过使用 org.springframework.boot.logging.LoggingSystem 系统属性来强制Spring Boot使用特定的日志记录系统。 该值应该是 LoggingSystem 实现的完全限定类名。你也可以使用 none 值完全禁用Spring Boot的日志记录配置。

由于日志记录是在创建 ApplicationContext 之前 初始化的,因此无法从Spring @Configuration 文件中的 @PropertySources 控制日志记录。更改日志记录系统或完全禁用它的唯一方法是通过系统属性。

根据你的日志记录系统,将加载以下文件:

志记录系统 自定义配置文件

Logback

logback-spring.xml, logback-spring.groovy, logback.xmllogback.groovy

Log4j2

log4j2-spring.xmllog4j2.xml

JDK (Java Util Logging)

logging.properties

如果可能,我们建议你在日志配置中使用 -spring 变体(例如:使用 logback-spring.xml 而不是 logback.xml)。 如果使用标准配置位置,Spring将无法完全控制日志初始化。
在“可执行jar”运行时,Java Util Logging存在一些已知的类加载问题,这会引起问题。我们建议你尽可能在“可执行jar”运行时避免使用它。

为了帮助定制,将一些其他属性从Spring Environment 转移到系统属性,如下表所述:

Spring Environment System Property 说明

logging.exception-conversion-word

LOG_EXCEPTION_CONVERSION_WORD

记录异常时使用的转换字。

logging.file.clean-history-on-start

LOG_FILE_CLEAN_HISTORY_ON_START

是否在启动时清除存档日志文件(如果启用了LOG_FILE)。(仅默认的Logback设置受支持。)

logging.file.name

LOG_FILE

如果定义,它将在默认日志配置中使用。

logging.file.max-size

LOG_FILE_MAX_SIZE

最大日志文件大小(如果启用了LOG_FILE)。(仅默认的Logback设置受支持。)

logging.file.max-history

LOG_FILE_MAX_HISTORY

要保留的最大归档日志文件数(如果启用了LOG_FILE)。(仅默认的Logback设置受支持。)

logging.file.path

LOG_PATH

如果定义,它将在默认日志配置中使用。

logging.file.total-size-cap

LOG_FILE_TOTAL_SIZE_CAP

要保留的备份日志的总大小(如果启用了LOG_FILE)。(仅默认的Logback设置受支持。)

logging.pattern.console

CONSOLE_LOG_PATTERN

控制台上使用的日志模式(stdout)。(仅默认的Logback设置受支持。)

logging.pattern.dateformat

LOG_DATEFORMAT_PATTERN

记录日期格式的附加模式。(仅默认的Logback设置受支持。)

logging.pattern.file

FILE_LOG_PATTERN

文件中使用的日志模式(如果启用了LOG_FILE)。(仅默认的Logback设置受支持。)

logging.pattern.level

LOG_LEVEL_PATTERN

呈现日志级别时使用的格式(默认为 %5p)。(仅默认的Logback设置受支持。)

logging.pattern.rolling-file-name

ROLLING_FILE_NAME_PATTERN

过渡日志文件名的模式(默认为 ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz)。(仅默认的Logback设置受支持。)

PID

PID

当前进程ID(如果可能,并且尚未将其定义为操作系统环境变量时将被发现)。

所有受支持的日志记录系统在解析其配置文件时都可以查阅系统属性。有关示例,请参见 spring-boot.jar 中的默认配置:

如果要在日志记录属性中使用占位符,则应使用Spring Boot的语法而不是基础框架的语法。 值得注意的是,如果使用Logback,则应使用 : 作为属性名称与其默认值之间的分隔符,而不应使用 :-

你可以通过仅覆盖 LOG_LEVEL_PATTERN(或Logback的 logging.pattern.level)来将MDC和其他临时内容添加到日志行。 例如,如果你使用 logging.pattern.level=user:%X{user} %5p,则默认日志格式包含一个名为“user”的MDC条目(如果存在),如以下示例所示。

2019-08-30 12:30:04.031 user:someone INFO 22174 --- [  nio-8080-exec-0] demo.Controller
Handling authenticated request

2.4.7. Logback扩展

Spring Boot包含许多Logback扩展,可以帮助进行高级配置。你可以在 logback-spring.xml 配置文件中使用这些扩展名。

由于标准 logback.xml 配置文件加载得太早,因此无法在其中使用扩展名。你需要使用 logback-spring.xml 或定义 logging.config 属性。
这些扩展不能与Logback的 配置扫描一起使用。 如果尝试这样做,则对配置文件进行更改将导致类似于以下日志之一的错误:
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]
特定于Profile的配置

通过 <springProfile> 标记,你可以根据活动的Spring profiles有选择地包括或排除配置部分。 在 <configuration> 元素内的任何位置都支持profile部分。使用 name 属性指定哪个profile接受配置。 <springProfile> 标记可以包含简单的profile名称(例如:staging)或profile表达式。 profile表达式允许表达更复杂的配置文件逻辑,例如:production & (eu-central | eu-west)。 有关更多详细信息,请参阅 参考指南。 以下清单显示了三个样本profiles:

<springProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>

<springProfile name="dev | staging">
    <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>

<springProfile name="!production">
    <!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>
环境属性

<springProperty> 标签使你可以从Spring Environment 中公开属性,以在Logback中使用。 如果要在Logback配置中访问 application.properties 文件中的值,则这样做很有用。 该标签的工作方式类似于Logback的标准 <property> 标签。但是,不是指定直接 value,而是指定属性的 source(来自 Environment)。 如果需要将属性存储在 local 作用域以外的其他位置,则可以使用 scope 属性。如果需要后备值(如果未在环境中设置该属性), 则可以使用 defaultValue 属性。以下示例显示如何公开在Logback中使用的属性:

<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
        defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
    <remoteHost>${fluentHost}</remoteHost>
    ...
</appender>
source 必须以kebab格式指定(例如:my.property-name)。但是,可以使用宽松的规则将属性添加到 Environment 中。

2.5. 国际化

Spring Boot支持本地化消息,因此你的应用程序可以迎合不同语言首选项的用户。 默认情况下,Spring Boot在类路径的根目录下查找存在的 messages 资源包。

当已配置资源束的默认属性文件可用时(即默认情况下为 messages.properties),将应用自动配置。 如果你的资源包仅包含特定于语言的属性文件,则需要添加默认文件。如果找不到与任何配置的基本名称匹配的属性文件,将没有自动配置的 MessageSource 可用。

可以使用 spring.messages 命名空间配置资源包的基本名称以及其他几个属性,如以下示例所示:

spring.messages.basename=messages,config.i18n.messages
spring.messages.fallback-to-system-locale=false
spring.messages.basename 支持以逗号分隔的位置列表,可以是包限定符,也可以是从类路径根目录解析的资源。

有关更多受支持的选项,请参见 MessageSourceProperties

2.6. JSON

Spring Boot提供了与三个JSON映射库的集成:

  • Gson

  • Jackson

  • JSON-B

Jackson是首选的默认库。

2.6.1. Jackson

提供了Jackson的自动配置,并且Jackson是 spring-boot-starter-json 的一部分。当Jackson放在类路径上时, 将自动配置 ObjectMapper Bean。提供了几个配置属性,用于 自定义 ObjectMapper 的配置

2.6.2. Gson

提供了Gson的自动配置。当Gson在类路径上时,将自动配置 Gson bean。提供了几个 spring.gson.* 配置属性用于自定义配置。为了获得更多控制权,可以使用一个或多个 GsonBuilderCustomizer bean。

2.6.3. JSON-B

提供了JSON-B的自动配置。当JSON-B API和实现位于类路径上时,将自动配置 Jsonb bean。首选的JSON-B实现是提供了依赖管理的 Apache Johnzon

2.7. 开发Web应用程序

Spring Boot非常适合于Web应用程序开发。你可以使用嵌入式Tomcat,Jetty,Undertow或Netty创建独立的HTTP服务器。 大多数Web应用程序都使用 spring-boot-starter-web 模块来快速启动和运行。 你还可以选择使用 spring-boot-starter-webflux 模块构建响应式Web应用程序。

2.7.1. Spring Web MVC框架

Spring Web MVC框架 (通常简称为“Spring MVC”)是一个丰富的“model view controller”Web框架。 Spring MVC使你可以创建特殊的 @Controller@RestController Bean来处理传入的HTTP请求。 使用 @RequestMapping 注解将控制器中的方法映射到HTTP。

以下代码显示了提供JSON数据返回的典型 @RestController

@RestController
@RequestMapping(value="/users")
public class MyRestController {

    @RequestMapping(value="/{user}", method=RequestMethod.GET)
    public User getUser(@PathVariable Long user) {
        // ...
    }

    @RequestMapping(value="/{user}/customers", method=RequestMethod.GET)
    List<Customer> getUserCustomers(@PathVariable Long user) {
        // ...
    }

    @RequestMapping(value="/{user}", method=RequestMethod.DELETE)
    public User deleteUser(@PathVariable Long user) {
        // ...
    }

}

Spring MVC是核心Spring Framework的一部分,有关详细信息,请参阅 参考文档。 在 spring.io/guides 上还有一些涵盖Spring MVC的指南。

Spring MVC自动配置

Spring Boot为Spring MVC提供了自动配置,可与大多数应用程序完美配合。

自动配置在Spring的默认设置之上添加了以下功能:

  • 包含 ContentNegotiatingViewResolverBeanNameViewResolver Bean。

  • 支持服务静态资源,包括对WebJars的支持(在本文档后面介绍)。

  • 自动注册 ConverterGenericConverterFormatter Bean。

  • HttpMessageConverters 的支持(在本文档后面介绍)。

  • 自动注册 MessageCodesResolver在本文档后面介绍)。

  • 静态 index.html 支持。

  • 自定义 Favicon 支持(在本文档后面介绍)。

  • 自动使用 ConfigurableWebBindingInitializer Bean(在本文档后面介绍)。

如果你想保留Spring Boot MVC功能并想要添加其他 MVC配置(拦截器,格式化程序,视图控制器和其他功能), 则可以添加自己的类型为 WebMvcConfigurer@Configuration 类,但 不添加 @EnableWebMvc。 如果希望提供 RequestMappingHandlerMappingRequestMappingHandlerAdapterExceptionHandlerExceptionResolver 的自定义实例,则可以声明一个 WebMvcRegistrationsAdapter 实例以提供此类组件。

如果要完全控制Spring MVC,则可以添加自己的带有 @EnableWebMvc 注解的 @Configuration 类。

HttpMessageConverters

Spring MVC使用 HttpMessageConverter 接口转换HTTP请求和响应。开箱即用中包含明智的默认设置。 例如:可以将对象自动转换为JSON(通过使用Jackson库)或XML(如果可用通过使用Jackson XML扩展或如果Jackson XML扩展不可用通过使用JAXB)。默认情况下,字符串以 UTF-8 编码。

如果你需要添加或自定义转换器,则可以使用Spring Boot的 HttpMessageConverters 类,如以下清单所示:

import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.*;
import org.springframework.http.converter.*;

@Configuration(proxyBeanMethods = false)
public class MyConfiguration {

    @Bean
    public HttpMessageConverters customConverters() {
        HttpMessageConverter<?> additional = ...
        HttpMessageConverter<?> another = ...
        return new HttpMessageConverters(additional, another);
    }

}

上下文中存在的所有 HttpMessageConverter bean都将添加到转换器列表中。你也可以用相同的方法覆盖默认转换器。

自定义JSON序列化器和反序列化器

如果使用Jackson序列化和反序列化JSON数据,则可能要编写自己的 JsonSerializerJsonDeserializer 类。 自定义序列化程序通常是 通过模块向Jackson进行注册的, 但是Spring Boot提供了替代的 @JsonComponent 注解,这使得直接注册Spring Bean更加容易。

你可以直接在 JsonSerializerJsonDeserializerKeyDeserializer 实现上使用 @JsonComponent 注解。 你还可以在包含序列化器/反序列化器作为内部类的类上使用它,如以下示例所示:

import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import org.springframework.boot.jackson.*;

@JsonComponent
public class Example {

    public static class Serializer extends JsonSerializer<SomeObject> {
        // ...
    }

    public static class Deserializer extends JsonDeserializer<SomeObject> {
        // ...
    }

}

ApplicationContext 中的所有 @JsonComponent bean都会自动向Jackson注册。 因为 @JsonComponent@Component 进行元注解,所以适用常规的组件扫描规则。

Spring Boot还提供了 JsonObjectSerializerJsonObjectDeserializer基类, 这些基类在序列化对象时为标准Jackson版本提供了有用的替代方法。有关详细信息,请参见Javadoc中的 JsonObjectSerializerJsonObjectDeserializer

MessageCodesResolver

Spring MVC有一种生成错误码以从绑定错误中呈现错误消息的策略:MessageCodesResolver。 如果你设置 spring.mvc.message-codes-resolver-format 属性为 PREFIX_ERROR_CODEPOSTFIX_ERROR_CODE, Spring Boot会为你创建一个(请参见 DefaultMessageCodesResolver.Format中的枚举)。

静态内容

默认情况下,Spring Boot从类路径中的 /static 目录(或 /public/resources/META-INF/ resources) 或ServletContext的根目录中提供静态内容。它使用Spring MVC中的 ResourceHttpRequestHandler, 以便你可以通过添加自己的 WebMvcConfigurer 并重写 addResourceHandlers 方法来修改该行为。

在独立的Web应用程序中,还启用了容器中的默认Servlet,并将其用作降级方案,如果Spring决定不处理, 则从 ServletContext 的根目录提供内容。在大多数情况下,这不会发生(除非你修改默认的MVC配置), 因为Spring始终可以通过 DispatcherServlet 处理请求。

默认情况下,资源映射在 /** 上,但是你可以使用 spring.mvc.static-path-pattern 属性进行调整。 例如:将所有资源重定位到 /resources/** 可以按如下方式实现:

spring.mvc.static-path-pattern=/resources/**

你还可以使用 spring.resources.static-locations 属性来自定义静态资源位置(用目录位置列表替换默认值)。 根Servlet上下文路径 "/" 也会作为位置自动添加。

除了前面提到的“标准”静态资源位置, Webjars 内容还有一个特殊情况。 如果jar文件以Webjars格式打包,则从jar文件提供带有 /webjars/** 路径的所有资源。

如果你的应用程序打包为jar,则不要使用 src/main/webapp 目录。尽管此目录是一个通用标准, 但它仅与war打包一起使用,并且如果生成jar,大多数构建工具都将其忽略。

Spring Boot还支持Spring MVC提供的高级资源处理功能,允许使用案例如:缓存清除静态资源或对Webjars使用版本无关的URL。

要对Webjars使用版本无关的URL,请添加 webjars-locator-core 依赖项,然后声明你的Webjar。 以jQuery为例,添加 "/webjars/jquery/jquery.min.js" 将得到 "/webjars/jquery/x.y.z/jquery.min.js", 其中 x.y.z 是Webjar版本。

如果使用JBoss,则需要声明 webjars-locator-jboss-vfs 依赖项,而不是 webjars-locator-core。 否则,所有Webjar都解析为 404

要使用缓存清除,以下配置为所有静态资源配置了缓存清除解决方案,并在URL中有效地添加了内容哈希,例如: <link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
通过为Thymeleaf和FreeMarker自动配置 ResourceUrlEncodingFilter,可以在运行时在模板中重写到资源的链接。 使用JSP时,你应该手动声明此过滤器。当前尚不自动支持其他模板引擎,但可以与自定义模板宏/帮助器一起使用,以及使用 ResourceUrlProvider

例如:当使用JavaScript模块加载器动态加载资源时,不能重命名文件。这就是为什么其他策略也受支持并且可以相互组合的原因。 “固定”策略在URL中添加静态版本字符串,而不更改文件名,如以下示例所示:

spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.paths=/js/lib/
spring.resources.chain.strategy.fixed.version=v12

通过这种配置,位于 "/js/lib/" 下的JavaScript模块使用固定的版本控制策略("/v12/js/lib/mymodule.js"), 而其他资源仍使用内容版本(<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>)。

有关更多受支持的选项,请参见 ResourceProperties

该功能已在专门的 博客文章 和Spring Framework的 参考文档中进行了详细说明。

欢迎页面

Spring Boot支持静态和模板欢迎页面。它首先在配置的静态内容位置中查找 index.html 文件。如果未找到,则寻找 index 模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。

自定义图标

与其他静态资源一样,Spring Boot在已配置的静态内容位置中查找 favicon.ico。如果存在这样的文件,它将自动用作应用程序的收藏夹图标。

路径匹配和内容协商

Spring MVC可以通过查看请求路径并将其匹配到应用程序中定义的映射(例如:Controller方法上的 @GetMapping 注解)来将传入的HTTP请求映射到处理程序。

Spring Boot选择默认情况下禁用后缀模式匹配,这意味着 "GET /projects/spring-boot.json" 之类的请求将不会与 @GetMapping("/projects/spring-boot") 映射进行匹配。这被认为是 Spring MVC应用程序的最佳实践。 过去,此功能主要用于未发送正确的“Accept”请求头的HTTP客户端,我们需要确保将正确的内容类型发送给客户端。 如今,内容协商已变得更加可靠。

还有其他处理HTTP客户端的方法,这些客户端不能始终发送正确的“Accept”请求头。 除了使用后缀匹配,我们还可以使用查询参数来确保将诸如 "GET /projects/spring-boot?format=json" 之类的请求映射到 @GetMapping("/projects/spring-boot")

spring.mvc.contentnegotiation.favor-parameter=true

# We can change the parameter name, which is "format" by default:
# spring.mvc.contentnegotiation.parameter-name=myparam

# We can also register additional file extensions/media types with:
spring.mvc.contentnegotiation.media-types.markdown=text/markdown

如果你了解了注意事项,但仍希望你的应用程序使用后缀模式匹配,则需要以下配置:

spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-suffix-pattern=true

另外,与其打开所有后缀模式,不如只支持已注册的后缀模式,这更安全:

spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-registered-suffix-pattern=true

# You can also register additional file extensions/media types with:
# spring.mvc.contentnegotiation.media-types.adoc=text/asciidoc
ConfigurableWebBindingInitializer

Spring MVC使用 WebBindingInitializer 来为特定请求初始化 WebDataBinder。 如果创建自己的 ConfigurableWebBindingInitializer @Bean,Spring Boot会自动配置Spring MVC以使用它。

模板引擎

除了REST Web服务之外,你还可以使用Spring MVC来提供动态HTML内容。Spring MVC支持各种模板技术, 包括Thymeleaf,FreeMarker和JSP。同样,许多其他模板引擎也提供包括他们自己的Spring MVC集成。

Spring Boot包含对以下模板引擎的自动配置支持:

如果可能,应避免使用JSP。将它们与嵌入式servlet容器一起使用时,存在几个已知的限制

当你使用默认配置的这些模板引擎之一时,将从 src/main/resources/templates 中自动提取模板。

根据你运行应用程序的方式,IntelliJ IDEA对类路径的排序不同。与使用Maven或Gradle或从其打包的jar运行应用程序时相比, 从IDE的main方法运行应用程序的顺序会有所不同。这可能导致Spring Boot无法在类路径上找到模板。 如果遇到此问题,可以在IDE中重新排序类路径,以首先放置模块的类和资源。 或者,你可以配置模板前缀以搜索类路径上的每个 templates 目录,例如:classpath*:/templates/
错误处理

默认情况下,Spring Boot提供一个 /error 映射,以一种明智的方式处理所有错误,并且在servlet容器中注册为“global”错误页面。 对于机器客户端,它将生成一个JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。 对于浏览器客户端,有一个“whitelabel”错误视图以HTML格式呈现相同的数据(要对其进行自定义,请添加一个可解决 errorView)。 要完全替换默认行为,可以实现 ErrorController 并注册该类型的bean定义,或者添加类型为 ErrorAttributes 的bean以使用现有机制,但替换其内容。

BasicErrorController 可用作自定义 ErrorController 的基类。如果要为新的内容类型添加处理程序(默认是专门处理 text/html 并为其他所有内容提供降级功能),则此功能特别有用。为此,请继承 BasicErrorController,添加具有 @RequestMapping 的公共方法,该方法具有 produces 属性,并创建新类型的Bean。

你还可以定义一个用 @ControllerAdvice 注解的类,以自定义JSON文档以针对特定的控制器和/或异常类型返回,如以下示例所示:

@ControllerAdvice(basePackageClasses = AcmeController.class)
public class AcmeControllerAdvice extends ResponseEntityExceptionHandler {

    @ExceptionHandler(YourException.class)
    @ResponseBody
    ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
        HttpStatus status = getStatus(request);
        return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }

}

在前面的示例中,如果与 AcmeController 在同一包中定义的控制器抛出 YourException,则使用 CustomErrorType POJO的JSON表示形式而不是 ErrorAttributes 表示形式。

自定义错误页面

如果要显示给定状态码的自定义HTML错误页面,可以将文件添加到 /error 文件夹。 错误页面可以是静态HTML(即添加到任何静态资源文件夹下),也可以使用模板来构建。文件名应为确切的状态码或系列掩码。

例如,要将 404 映射到静态HTML文件,你的文件夹结构如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

要使用FreeMarker模板映射所有 5xx 错误,你的文件夹结构如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.ftlh
             +- <other templates>

对于更复杂的映射,还可以添加实现 ErrorViewResolver 接口的bean,如以下示例所示:

public class MyErrorViewResolver implements ErrorViewResolver {

    @Override
    public ModelAndView resolveErrorView(HttpServletRequest request,
            HttpStatus status, Map<String, Object> model) {
        // Use the request or status to optionally return a ModelAndView
        return ...
    }

}

你还可以使用常规的Spring MVC功能,例如: @ExceptionHandler 方法@ControllerAdvice。然后,ErrorController 拾取所有未处理的异常。

在Spring MVC之外映射错误页面

对于不使用Spring MVC的应用程序,可以使用 ErrorPageRegistrar 接口直接注册 ErrorPages。 此抽象直接与基础嵌入式servlet容器一起使用,即使你没有Spring MVC DispatcherServlet 它也可以使用。

@Bean
public ErrorPageRegistrar errorPageRegistrar(){
    return new MyErrorPageRegistrar();
}

// ...

private static class MyErrorPageRegistrar implements ErrorPageRegistrar {

    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
    }

}
如果你在 ErrorPage 上注册了一个最终由 Filter 处理的路径(这在某些非Spring Web框架中很常见,如Jersey和Wicket), 则必须将 Filter 显式注册为 ERROR 调度程序,如下面的例子所示:
@Bean
public FilterRegistrationBean myFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new MyFilter());
    ...
    registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
    return registration;
}

请注意,默认的 FilterRegistrationBean 不包含 ERROR 调度程序类型。

当部署到Servlet容器时,Spring Boot使用其错误页面过滤器将具有错误状态的请求转发到适当的错误页面。 如果尚未提交响应,则只能将请求转发到正确的错误页面。缺省情况下,WebSphere Application Server 8.0 及更高版本在成功完成servlet的服务方法后提交响应。 你应该通过将 com.ibm.ws.webcontainer.invokeFlushAfterService 设置为 false 来禁用此行为。
Spring HATEOAS

如果你开发使用超媒体的RESTful API,Spring Boot将为Spring HATEOAS提供自动配置, 该配置可与大多数应用程序很好地兼容。自动配置取代了手动使用 @EnableHypermediaSupport 的需要, 并注册了许多bean来简化基于超媒体的应用程序的构建,其中包括 LinkDiscoverers(用于客户端支持)和 ObjectMapper 其配置为将响应正确地组装为所需的表示形式。通过设置各种 spring.jackson.* 属性, 或通过 Jackson2ObjectMapperBuilder bean(如果存在)来定制 ObjectMapper

你可以使用 @EnableHypermediaSupport 来控制Spring HATEOAS的配置。请注意,这样做会禁用前面所述的 ObjectMapper 定制。

CORS支持

跨域资源共享(CORS)是由 大多数浏览器实施的 W3C 规范,可让你灵活地指定授权哪种类型的跨域请求,而不是使用诸如IFRAME或JSONP之类的安全性较低,功能较弱的方法。

从4.2版本开始,Spring MVC 支持CORS。在Spring Boot应用程序中使用带有 @CrossOrigin 注解的 控制器方法CORS配置不需要任何特定的配置。 可以通过使用自定义的 addCorsMappings(CorsRegistry) 方法注册 WebMvcConfigurer Bean来定义 全局CORS配置,如以下示例所示:

@Configuration(proxyBeanMethods = false)
public class MyConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**");
            }
        };
    }
}

2.7.2. Spring WebFlux框架

Spring WebFlux是Spring Framework 5.0中引入的新响应式Web框架。 与Spring MVC不同,它不需要Servlet API,是完全异步和非阻塞的,并且通过 Reactor项目 实现 Reactive Streams规范。

Spring WebFlux有两种形式:函数式的和基于注解的。基于注解的模型非常类似于Spring MVC模型,如以下示例所示:

@RestController
@RequestMapping("/users")
public class MyRestController {

    @GetMapping("/{user}")
    public Mono<User> getUser(@PathVariable Long user) {
        // ...
    }

    @GetMapping("/{user}/customers")
    public Flux<Customer> getUserCustomers(@PathVariable Long user) {
        // ...
    }

    @DeleteMapping("/{user}")
    public Mono<User> deleteUser(@PathVariable Long user) {
        // ...
    }

}

函数式变体“WebFlux.fn”将路由配置与请求的实际处理分开,如以下示例所示:

@Configuration(proxyBeanMethods = false)
public class RoutingConfiguration {

    @Bean
    public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
        return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
                .andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
                .andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
    }

}

@Component
public class UserHandler {

    public Mono<ServerResponse> getUser(ServerRequest request) {
        // ...
    }

    public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
        // ...
    }

    public Mono<ServerResponse> deleteUser(ServerRequest request) {
        // ...
    }
}

WebFlux是Spring Framework的一部分,其 参考文档中提供了详细信息。

你可以根据需要定义任意数量的 RouterFunction beans,以对路由器的定义进行模块化。如果需要应用优先级,可以排序Beans。

首先将 spring-boot-starter-webflux 模块添加到你的应用程序。

在应用程序中同时添加 spring-boot-starter-webspring-boot-starter-webflux 模块会导致Spring Boot自动配置Spring MVC,而不是WebFlux。之所以选择这种行为,是因为许多Spring开发人员将 spring-boot-starter-webflux 添加到其Spring MVC应用程序中以使用响应式 WebClient。你仍然可以通过将选定的应用程序类型设置为 SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE) 来强制执行选择。
Spring WebFlux自动配置

Spring Boot为Spring WebFlux提供了自动配置,可与大多数应用程序很好地配合使用。

自动配置在Spring的默认设置之上添加了以下功能:

  • HttpMessageReaderHttpMessageWriter 实例配置编解码器(在本文档后面介绍)。

  • 支持服务静态资源,包括对WebJars的支持(在本文档后面介绍)。

如果你想保留Spring Boot WebFlux功能并想要添加其他WebFlux配置,则可以添加自己的类型为 WebFluxConfigurer@Configuration 类,但 添加 @EnableWebFlux

如果要完全控制Spring WebFlux,则可以添加带有 @EnableWebFlux 注解的自己的 @Configuration

带有HttpMessageReaders和HttpMessageWriters的HTTP编解码器

Spring WebFlux使用 HttpMessageReaderHttpMessageWriter 接口转换HTTP请求和响应。 通过查看类路径中可用的库,使用 CodecConfigurer 将它们配置为具有合理的默认值。

Spring Boot为编解码器 spring.codec.* 提供了专用的配置属性。它还通过使用 CodecCustomizer 实例应用进一步的自定义。 例如,将 spring.jackson.* 配置keys应用于Jackson编解码器。

如果需要添加或自定义编解码器,则可以创建一个自定义 CodecCustomizer 组件,如以下示例所示:

import org.springframework.boot.web.codec.CodecCustomizer;

@Configuration(proxyBeanMethods = false)
public class MyConfiguration {

    @Bean
    public CodecCustomizer myCodecCustomizer() {
        return codecConfigurer -> {
            // ...
        };
    }

}
静态内容

默认情况下,Spring Boot从类路径中名为 /static(或 /public/resources/META-INF/resources)的目录中提供静态内容。 它使用Spring WebFlux中的 ResourceWebHandler,以便你可以通过添加自己的 WebFluxConfigurer 并覆盖 addResourceHandlers 方法来修改该行为。

默认情况下,资源映射在 /** 上,但是你可以通过设置 spring.webflux.static-path-pattern 属性来对其进行调整。 例如:将所有资源重定位到 /resources/** 可以实现如下:

spring.webflux.static-path-pattern=/resources/**

你还可以使用 spring.resources.static-locations 自定义静态资源位置。这样做会将默认值替换为目录位置列表。 如果这样做,默认的欢迎页面检测将切换到你的自定义位置。因此,如果启动时你指定的任何位置有 index.html,则它是应用程序的主页。

除了前面列出的“标准”静态资源位置外,https://www.webjars.org/[Webjar内容]有个特殊情况。如果jar文件以Webjars格式打包, 则从jar文件提供带有 /webjars/** 路径的所有资源。

Spring WebFlux应用程序不严格依赖Servlet API,因此不能将它们部署为war文件,也不使用 src/main/webapp 目录。
模板引擎

除了REST Web服务之外,你还可以使用Spring WebFlux来提供动态HTML内容。 Spring WebFlux支持各种模板技术,包括Thymeleaf,FreeMarker和Mustache。

Spring Boot包含对以下模板引擎的自动配置支持:

当你使用默认配置的这些模板引擎之一时,将从 src/main/resources/templates 中自动提取模板。

错误处理

Spring Boot提供了一个 WebExceptionHandler,以一种明智的方式处理所有错误。它在处理顺序中的位置紧靠WebFlux提供的处理程序之前, 后者被认为是最后一个处理程序。对于机器客户端,它将生成一个JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。 对于浏览器客户端,有一个“whitelabel”错误处理程序,以HTML格式呈现相同的数据。你还可以提供自己的HTML模板来显示错误(请参阅 下一节)。

定制此功能的第一步通常涉及使用现有机制,但替换或增加错误内容。为此,你可以添加类型为 ErrorAttributes 的bean。

要更改错误处理行为,可以实现 ErrorWebExceptionHandler 并注册该类型的bean定义。由于 WebExceptionHandler 的级别很低, 因此Spring Boot还提供了一个方便的 AbstractErrorWebExceptionHandler,可让你以WebFlux函数式方式处理错误,如以下示例所示:

public class CustomErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

    // Define constructor here

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {

        return RouterFunctions
                .route(aPredicate, aHandler)
                .andRoute(anotherPredicate, anotherHandler);
    }

}

为了获得更完整的图像,你还可以直接将 DefaultErrorWebExceptionHandler 子类化并重写特定方法。

自定义错误页面

如果要显示给定状态码的自定义HTML错误页面,可以将文件添加到 /error 文件夹。 错误页面可以是静态HTML(即添加到任何静态资源文件夹下),也可以使用模板构建。文件名应为确切的状态码或系列掩码。

例如,要将 404 映射到静态HTML文件,你的文件夹结构如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

要使用Mustache模板映射所有 5xx 错误,你的文件夹结构如下:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.mustache
             +- <other templates>
Web过滤器

Spring WebFlux提供了一个 WebFilter 接口,可以实现该接口来过滤HTTP请求-响应交换。 在应用程序上下文中找到的 WebFilter bean将自动用于过滤每个交换。

如果过滤器的顺序很重要,则可以实现 Ordered 或使用 @Order 进行注解。 Spring Boot自动配置会为你配置Web过滤器。这样做时,将使用下表中显示的顺序:

Web过滤器 顺序

MetricsWebFilter

Ordered.HIGHEST_PRECEDENCE + 1

WebFilterChainProxy (Spring Security)

-100

HttpTraceWebFilter

Ordered.LOWEST_PRECEDENCE - 10

2.7.3. JAX-RS和Jersey

如果你更喜欢REST端点的JAX-RS编程模型,则可以使用可用的实现之一来代替Spring MVC。 JerseyApache CXF开箱即用。 CXF要求你在应用程序上下文中将其 ServletFilter 注册为 @Bean。 Jersey提供了一些native Spring支持,因此我们还在Spring Boot中提供了对它的自动配置支持,以及一个启动器。

要开始使用Jersey,请将 spring-boot-starter-jersey 作为依赖项包括在内,然后需要一个 ResourceConfig 类型的 @Bean,在其中注册所有端点,如以下示例所示:

@Component
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        register(Endpoint.class);
    }

}
Jersey’s对扫描可执行档案的支持非常有限。例如:在运行可执行的war文件时, 它无法扫描在完全可执行的jar文件WEB-INF/classes 中找到的包中的端点。为了避免这种限制,不应该使用 packages 方法, 而应该使用 register 方法分别注册端点,如前面的示例所示。

对于更高级的定制,你还可以注册任意数量的 ResourceConfigCustomizer 实现beans。

所有注册的端点应为具有HTTP资源注解的 @Components@GET 和其他注解),如以下示例所示:

@Component
@Path("/hello")
public class Endpoint {

    @GET
    public String message() {
        return "Hello";
    }

}

由于端点是Spring @Component,因此其生命周期由Spring管理,你可以使用 @Autowired 注解注入依赖项, 并使用 @Value 注解注入外部配置。默认情况下,Jersey servlet被注册并映射到 /*。 你可以通过将 @ApplicationPath 添加到 ResourceConfig 来更改映射。

默认情况下,Jersey在名为 jerseyServletRegistrationServletRegistrationBean 类型的 @Bean 中设置为Servlet。 默认情况下,该Servlet延迟初始化,但是你可以通过设置 spring.jersey.servlet.load-on-startup 来自定义该行为。 你可以通过创建自己的同名bean之一来禁用或覆盖该bean。你还可以通过设置 spring.jersey.type=filter (在这种情况下,要替换或覆盖的 @BeanjerseyFilterRegistration)来使用过滤器而不是servlet。 过滤器具有 @Order,你可以使用 spring.jersey.filter.order 进行设置。可以通过使用 spring.jersey.init.* 来指定属性映射, 从而为servlet和过滤器注册都赋予init参数。

2.7.4. 嵌入式Servlet容器支持

Spring Boot包括对嵌入式 TomcatJetty和 默认情况下,嵌入式服务器在端口8080上侦听HTTP请求。

Servlets, Filters和listeners

使用嵌入式Servlet容器时,可以通过使用Spring beans或扫描Servlet组件来注册Servlet规范中的servlets,过滤器和所有监听器(例如:HttpSessionListener)。

将Servlets, Filters和Listeners注册为Spring Beans

任何作为Spring Bean的 ServletFilter*Listener 实例都向嵌入式容器注册。如果要在配置过程中引用 application.properties 中的值,这可能特别方便。

默认情况下,如果上下文仅包含单个Servlet,则将其映射到 /。对于多个servlet bean,bean名称被用作路径前缀。 过滤器映射到 /*

如果基于约定的映射不够灵活,则可以使用 ServletRegistrationBeanFilterRegistrationBeanServletListenerRegistrationBean 类进行完全控制。

通常可以使无序的过滤器beans处于安全状态。如果需要特定的顺序,则应使用 @Order 注解 Filter 或使其实现 Ordered。 你不能通过使用 @Order 注解 Filter 的bean方法来配置 Filter 的顺序。如果你不能更改 Filter 类以添加 @Order 或实现 Ordered, 则必须为 Filter 定义一个 FilterRegistrationBean 并使用 setOrder(int) 方法设置注册bean的顺序。 避免配置一个在 Ordered.HIGHEST_PRECEDENCE 上读取请求正文的过滤器,因为它可能与应用程序的字符编码配置不符。 如果Servlet过滤器包装了请求,则应使用小于或等于 OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER 的顺序来配置它。

要查看应用程序中每个 Filter 的顺序,请为 web 日志记录组logging.level.web=debug)启用调试级别的日志记录。然后,将在启动时记录已注册过滤器的详细信息,包括其顺序和URL模式。
注册 Filter beans时要小心,因为它们是在应用程序生命周期中很早就初始化的。如果需要注册与其他bean交互的 Filter ,请考虑改用 DelegatingFilterProxyRegistrationBean
Servlet上下文初始化

嵌入式Servlet容器不会直接执行Servlet 3.0+ javax.servlet.ServletContainerInitializer 接口或Spring的 org.springframework.web.WebApplicationInitializer 接口。这是一个有意的设计决定, 旨在降低在war中运行的第三方库可能破坏Spring Boot应用程序的风险。

如果你需要在Spring Boot应用程序中执行Servlet上下文初始化,则应该注册一个实现 org.springframework.boot.web.servlet.ServletContextInitializer 接口的bean。 单个 onStartup 方法提供对 ServletContext 的访问,并且在必要时可以轻松地用作现有 WebApplicationInitializer 的适配器。

扫描Servlets, Filters和Listeners

使用嵌入式容器时,可以使用 @ServletComponentScan 启用自动注册带有 @WebServlet@WebFilter@WebListener 的类。

@ServletComponentScan 在独立容器中无效,而是使用容器的内置发现机制。
ServletWebServerApplicationContext

在后台,Spring Boot使用另一种类型的 ApplicationContext 来支持嵌入式Servlet容器。 ServletWebServerApplicationContextWebApplicationContext 的一种特殊类型, 它通过搜索单个 ServletWebServerFactory bean来自我引导。通常,已经自动配置了 TomcatServletWebServerFactoryJettyServletWebServerFactoryUndertowServletWebServerFactory

通常,你不需要了解这些实现类。大多数应用程序都是自动配置的,并且代表你创建了相应的 ApplicationContextServletWebServerFactory
自定义嵌入式Servlet容器

可以使用Spring Environment 属性来配置常见的servlet容器设置。通常,你将在 application.properties 文件中定义属性。

常用服务器设置包括:

  • 网络设置:监听传入HTTP请求的端口(server.port),绑定到 server.address 的接口地址,等等。

  • 会话设置:会话是否持久(server.servlet.session.persistent),会话超时(server.servlet.session.timeout), 会话数据的位置(server.servlet.session.store-dir)和会话cookie配置(server.servlet.session.cookie.*)。

  • 错误管理:错误页面的位置(server.error.path)等。

  • SSL

  • HTTP压缩

Spring Boot尝试尽可能多地公开通用设置,但这并不总是可能的。对于这些情况, 专用名称空间提供特定服务器的自定义项(请参阅 server.tomcatserver.undertow)。 例如:可以使用嵌入式servlet容器的特定功能配置 访问日志

有关完整列表,请参见 ServerProperties类。
编程定制

如果需要以编程方式配置嵌入式Servlet容器,则可以注册一个实现 WebServerFactoryCustomizer 接口的Spring Bean。WebServerFactoryCustomizer 提供对 ConfigurableServletWebServerFactory 的访问,其中包括许多自定义设置方法。以下示例显示以编程方式设置端口:

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;

@Component
public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {

    @Override
    public void customize(ConfigurableServletWebServerFactory server) {
        server.setPort(9000);
    }

}
TomcatServletWebServerFactoryJettyServletWebServerFactoryUndertowServletWebServerFactoryConfigurableServletWebServerFactory 的专用变体,分别具有针对Tomcat,Jetty和Undertow的其他自定义设置方法。
直接自定义ConfigurableServletWebServerFactory

如果上述定制技术太有限,则可以自己注册 TomcatServletWebServerFactoryJettyServletWebServerFactoryUndertowServletWebServerFactory bean。

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.setPort(9000);
    factory.setSessionTimeout(10, TimeUnit.MINUTES);
    factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
    return factory;
}

提供了许多配置选项的设置器。如果你需要做一些更奇特的操作,还提供了几种受保护的方法“hooks”。有关详细信息,请参见 源代码文档

JSP局限性

运行使用嵌入式servlet容器(并打包为可执行档案)的Spring Boot应用程序时,JSP支持存在一些限制。

  • 对于Jetty和Tomcat,如果使用war包装,它应该可以工作。 一个可执行的war在使用 java -jar 启动时可以工作,并且可以部署到任何标准容器中。使用可执行jar时不支持JSPs。

  • Undertow不支持JSPs。

  • 创建定制的 error.jsp 页面不会覆盖默认视图以进行错误处理。应改用 自定义错误页面

2.7.5. 响应式嵌入服务器支持

Spring Boot包含对以下响应式Web嵌入服务器的支持:Reactor Netty,Tomcat,Jetty和Undertow。 大多数开发人员使用适当的“Starter”来获取完全配置的实例。默认情况下,嵌入式服务器在端口8080上侦听HTTP请求。

2.7.6. 响应式服务器资源配置

当自动配置Reactor Netty或Jetty服务器时,Spring Boot将创建特定的bean,这些bean将向服务器实例提供HTTP资源: ReactorResourceFactoryJettyResourceFactory

默认情况下,这些资源还将与Reactor Netty和Jetty客户端共享,以实现最佳性能,前提是:

  • 服务器和客户端使用相同的技术

  • 客户端实例是使用Spring Boot自动配置的 WebClient.Builder bean构建的

通过提供自定义的 ReactorResourceFactoryJettyResourceFactory bean,开发人员可以覆盖Jetty和Reactor Netty的资源配置 — 这将同时应用于客户端和服务器。

你可以在WebClient Runtime部分中了解有关客户端资源配置的更多信息。

2.8. RSocket

RSocket是用于字节流传输的二进制协议。它通过在单个连接上传递异步消息来支持对称交互模型。

Spring框架的 spring-messaging 模块在客户端和服务器端都支持RSocket请求者和响应者。有关更多详细信息,请参见Spring Framework参考中的 RSocket部分,其中包括RSocket协议的概述。

2.8.1. RSocket策略自动配置

Spring Boot自动配置一个 RSocketStrategies bean,该bean提供了编码和解码RSocket有效载荷所需的所有基础设施。 默认情况下,自动配置将尝试(按顺序)配置以下内容:

  1. Jackson的 CBOR编解码器

  2. Jackson的JSON编解码器

spring-boot-starter-socket 启动器提供了两个依赖项。查阅Jackson支持部分, 了解更多定制的可能性。

开发人员可以通过创建实现 RSocketStrategiesCustomizer 接口的bean来自定义 RSocketStrategies 组件。 请注意,它们的 @Order 很重要,因为它确定编解码器的顺序。

2.8.2. RSocket服务器自动配置

Spring Boot提供了RSocket服务器自动配置。所需的依赖关系由 spring-boot-starter-rsocket 提供。

Spring Boot允许从WebFlux服务器通过WebSocket公开RSocket,或支持独立的RSocket服务器。这取决于应用程序的类型及其配置。

对于WebFlux应用程序(即 WebApplicationType.REACTIVE 类型),RSocket服务器只有在下列属性匹配时才会被插入到Web服务器:

spring.rsocket.server.mapping-path=/rsocket # a mapping path is defined
spring.rsocket.server.transport=websocket # websocket is chosen as a transport
#spring.rsocket.server.port= # no port is defined
只有Reactor Netty才支持将RSocket插入web服务器,因为RSocket本身就是用这个库构建的。

另外,RSocket TCP或Websocket服务器也可以作为独立的嵌入式服务器启动。除了依赖性要求之外,唯一需要的配置是为该服务器定义端口:

spring.rsocket.server.port=9898 # the only required configuration
spring.rsocket.server.transport=tcp # you're free to configure other properties

2.8.3. Spring Messaging RSocket支持

Spring Boot将为RSocket自动配置Spring Messaging基础设施。

这意味着Spring Boot将创建一个 RSocketMessageHandler bean,该bean将处理对你的应用程序的RSocket请求。

2.8.4. 使用 RSocketRequester 调用RSocket服务

在服务器和客户端之间建立RSocket通道后,任何一方都可以向另一方发送或接收请求。

作为服务器,你可以在RSocket @Controller 的任何处理程序方法上注入 RSocketRequester 实例。 作为客户端,你需要首先配置和建立RSocket连接。在这种情况下,Spring Boot会使用预期的编解码器自动配置 RSocketRequester.Builder

RSocketRequester.Builder 实例是一个原型bean,这意味着每个注入点将为你提供一个新实例。 这样做是有目的的,因为此构建器是有状态的,因此你不应使用同一实例创建具有不同设置的请求者。

以下代码显示了一个典型示例:

@Service
public class MyService {

    private final RSocketRequester rsocketRequester;

    public MyService(RSocketRequester.Builder rsocketRequesterBuilder) {
        this.rsocketRequester = rsocketRequesterBuilder
                .connectTcp("example.org", 9898).block();
    }

    public Mono<User> someRSocketCall(String name) {
        return this.requester.route("user").data(name)
                .retrieveMono(User.class);
    }

}

2.9. 安全

如果 Spring Security在类路径上,则默认情况下Web应用程序是安全的。 Spring Boot依靠Spring Security的内容协商策略来确定是使用 httpBasic 还是 formLogin。 要将方法级安全性添加到Web应用程序,还可以使用所需的设置添加 @EnableGlobalMethodSecurity。 可以在 Spring Security参考指南中找到更多信息。

默认的 UserDetailsService 具有单个用户。用户名是 user,密码是随机的,并在应用程序启动时以INFO级别显示,如下例所示:

Using generated security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35
如果你微调日志记录配置,请确保将 org.springframework.boot.autoconfigure.security 类别设置为记录 INFO 级别的消息。否则,不会打印默认密码。

你可以通过提供 spring.security.user.namespring.security.user.password 来更改用户名和密码。

默认情况下,你在Web应用程序中获得的基本功能是:

  • 一个具有内存存储的 UserDetailsService(如果是WebFlux应用程序,则为 ReactiveUserDetailsService)Bean, 一个具有已生成密码的用户(请参阅 SecurityProperties.User以获取用户属性)。

  • 整个应用程序的基于表单的登录或HTTP基本安全性(取决于请求中的 Accept 头部)(包括执行器端点,如果执行器位于类路径上)。

  • 用于发布身份验证事件的 DefaultAuthenticationEventPublisher

你可以通过为它添加一个bean来提供一个不同的 AuthenticationEventPublisher

2.9.1. MVC安全

默认的安全配置在 SecurityAutoConfigurationUserDetailsServiceAutoConfiguration 中实现。 SecurityAutoConfiguration 导入用于Web安全的 SpringBootWebSecurityConfiguration, 而 UserDetailsServiceAutoConfiguration 配置身份验证,这也与非Web应用程序相关。 要完全关闭默认的Web应用程序安全性配置或合并多个Spring Security组件(例如:OAuth 2客户端和资源服务器), 请添加类型为 WebSecurityConfigurerAdapter 的bean(这样做不会禁用 UserDetailsService 配置或Actuator的安全性)。

要关闭 UserDetailsService 配置,你可以添加 UserDetailsServiceAuthenticationProviderAuthenticationManager 类型的bean。

通过添加自定义 WebSecurityConfigurerAdapter 可以覆盖访问规则。 Spring Boot提供了便捷的方法,可用于覆盖actuator端点和静态资源的访问规则。 EndpointRequest 可用于创建基于 management.endpoints.web.base-path 属性的 RequestMatcher。 可以使用 PathRequest 为常用位置的资源创建一个 RequestMatcher

2.9.2. WebFlux安全

与Spring MVC应用程序类似,你可以通过添加 spring-boot-starter-security 依赖项来保护WebFlux应用程序。 默认的安全配置在 ReactiveSecurityAutoConfigurationUserDetailsServiceAutoConfiguration 中实现。 ReactiveSecurityAutoConfiguration 导入 WebFluxSecurityConfiguration 以获得Web安全, 而 UserDetailsServiceAutoConfiguration 配置身份验证,这也与非Web应用程序相关。 要完全关闭默认的Web应用程序安全配置,你可以添加 WebFilterChainProxy 类型的Bean (这样做不会禁用 UserDetailsService 配置或Actuator的安全性)。

要关闭 UserDetailsService 配置,你可以添加类型为 ReactiveUserDetailsServiceReactiveAuthenticationManager 的bean。

可以通过添加自定义 SecurityWebFilterChain bean来配置访问规则以及使用多个Spring Security组件 (例如:OAuth 2 Client和Resource Server)。Spring Boot提供了便捷的方法,可用于覆盖actuator端点和静态资源的访问规则。 EndpointRequest 可用于创建基于 management.endpoints.web.base-path 属性的 ServerWebExchangeMatcher

可以使用 PathRequest 为常用位置的资源创建 ServerWebExchangeMatcher

例如,你可以通过添加以下内容来自定义安全配置:

@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    return http
        .authorizeExchange()
            .matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
            .pathMatchers("/foo", "/bar")
                .authenticated().and()
            .formLogin().and()
        .build();
}

2.9.3. OAuth2

OAuth2是Spring支持的一种广泛使用的授权框架。

客户端

如果你在类路径中具有 spring-security-oauth2-client,则可以利用一些自动配置功能来轻松设置OAuth2/OpenID Connect客户端。 此配置使用 OAuth2ClientProperties 下的属性。相同的属性适用于servlet和响应式应用程序。

你可以在 spring.security.oauth2.client 前缀下注册多个OAuth2客户端和Provider,如以下示例所示:

spring.security.oauth2.client.registration.my-client-1.client-id=abcd
spring.security.oauth2.client.registration.my-client-1.client-secret=password
spring.security.oauth2.client.registration.my-client-1.client-name=Client for user scope
spring.security.oauth2.client.registration.my-client-1.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-1.scope=user
spring.security.oauth2.client.registration.my-client-1.redirect-uri=https://my-redirect-uri.com
spring.security.oauth2.client.registration.my-client-1.client-authentication-method=basic
spring.security.oauth2.client.registration.my-client-1.authorization-grant-type=authorization_code

spring.security.oauth2.client.registration.my-client-2.client-id=abcd
spring.security.oauth2.client.registration.my-client-2.client-secret=password
spring.security.oauth2.client.registration.my-client-2.client-name=Client for email scope
spring.security.oauth2.client.registration.my-client-2.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-2.scope=email
spring.security.oauth2.client.registration.my-client-2.redirect-uri=https://my-redirect-uri.com
spring.security.oauth2.client.registration.my-client-2.client-authentication-method=basic
spring.security.oauth2.client.registration.my-client-2.authorization-grant-type=authorization_code

spring.security.oauth2.client.provider.my-oauth-provider.authorization-uri=https://my-auth-server/oauth/authorize
spring.security.oauth2.client.provider.my-oauth-provider.token-uri=https://my-auth-server/oauth/token
spring.security.oauth2.client.provider.my-oauth-provider.user-info-uri=https://my-auth-server/userinfo
spring.security.oauth2.client.provider.my-oauth-provider.user-info-authentication-method=header
spring.security.oauth2.client.provider.my-oauth-provider.jwk-set-uri=https://my-auth-server/token_keys
spring.security.oauth2.client.provider.my-oauth-provider.user-name-attribute=name

对于支持 OpenID Connect发现的OpenID Connect Providers,可以进一步简化配置。 供应商需要配置一个 issuer-uri,该URI是其声明的Issuer标识符。 例如,如果提供的 issuer-uri 是“https://example.com”,则将向“https://example.com/.well-known/openid-configuration” 发出 OpenID Provider Configuration Request。结果应为 OpenID Provider Configuration Response。 以下示例显示了如何使用 issuer-uri 配置OpenID Connect Provider:

spring.security.oauth2.client.provider.oidc-provider.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/

默认情况下,Spring Security的 OAuth2LoginAuthenticationFilter 仅处理与 /login/oauth2/code/* 匹配的URL。 如果要自定义 redirect-uri 以使用其他模式,则需要提供配置以处理该自定义模式。 例如,对于servlet应用程序,你可以添加自己的类似于以下内容的 WebSecurityConfigurerAdapter

public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .oauth2Login()
                .redirectionEndpoint()
                    .baseUri("/custom-callback");
    }
}
常见供应商的OAuth2客户端注册

对于常见的OAuth2和OpenID供应商,包括Google,Github,Facebook和Okta,我们提供了一组供应商默认值(分别为 googlegithubfacebookokta)。

如果不需要自定义这些供应商,则可以将 provider 属性设置为需要为其推断默认值的属性。 另外,如果用于客户端注册的key与默认支持的供应商匹配,则Spring Boot也会进行推断。

换句话说,以下示例中的两个配置都使用Google供应商:

spring.security.oauth2.client.registration.my-client.client-id=abcd
spring.security.oauth2.client.registration.my-client.client-secret=password
spring.security.oauth2.client.registration.my-client.provider=google

spring.security.oauth2.client.registration.google.client-id=abcd
spring.security.oauth2.client.registration.google.client-secret=password
资源服务器

如果你的类路径上有 spring-security-oauth2-resource-server,则Spring Boot可以设置OAuth2资源服务器。 对于JWT配置,需要指定JWK Set URI或OIDC Issuer URI,如以下示例所示:

spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://example.com/oauth2/default/v1/keys
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/
如果授权服务器不支持JWK Set URI,则可以使用用于验证JWT签名的公钥来配置资源服务器。 可以使用 spring.security.oauth2.resourceserver.jwt.public-key-location 属性来完成此操作, 该属性值需要指向包含PEM-encoded x509格式的公钥的文件。

相同的属性适用于servlet和响应式应用程序。

另外,你可以为Servlet应用程序定义自己的 JwtDecoder Bean,或者为响应式应用程序定义 ReactiveJwtDecoder

如果使用opaque tokens而不是JWT,则可以配置以下属性以通过自省来验证tokens:

spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=https://example.com/check-token
spring.security.oauth2.resourceserver.opaquetoken.client-id=my-client-id
spring.security.oauth2.resourceserver.opaquetoken.client-secret=my-client-secret

同样,相同的属性适用于servlet和响应式应用程序。

另外,你可以为Servlet应用程序定义自己的 OpaqueTokenIntrospector Bean,或者为响应式应用程序定义 ReactiveOpaqueTokenIntrospector

授权服务器

当前,Spring Security不提供对实现OAuth 2.0授权服务器的支持。但是, Spring Security OAuth项目提供了此功能, 最终将被Spring Security完全取代。在此之前,你可以使用 spring-security-oauth2-autoconfigure 模块轻松设置OAuth 2.0授权服务器;有关说明,请参见其 文档

2.9.4. SAML 2.0

依赖方

如果你在类路径中具有 spring-security-saml2-service-provider,则可以利用一些自动配置功能来轻松设置 SAML 2.0依赖方。此配置使用 Saml2RelyingPartyProperties 下的属性。

依赖方注册代表身份供应商IDP和服务供应商SP之间的配对配置。你可以在 spring.security.saml2.relyingparty 前缀下注册多个依赖方,如以下示例所示:

spring.security.saml2.relyingparty.registration.my-relying-party1.signing.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-party1.signing.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-party1.identityprovider.verification.credentials[0].certificate-location=path-to-verification-cert
spring.security.saml2.relyingparty.registration.my-relying-party1.identityprovider.entity-id=remote-idp-entity-id1
spring.security.saml2.relyingparty.registration.my-relying-party1.identityprovider.sso-url=https://remoteidp1.sso.url

spring.security.saml2.relyingparty.registration.my-relying-party2.signing.credentials[0].private-key-location=path-to-private-key
spring.security.saml2.relyingparty.registration.my-relying-party2.signing.credentials[0].certificate-location=path-to-certificate
spring.security.saml2.relyingparty.registration.my-relying-party2.identityprovider.verification.credentials[0].certificate-location=path-to-other-verification-cert
spring.security.saml2.relyingparty.registration.my-relying-party2.identityprovider.entity-id=remote-idp-entity-id2
spring.security.saml2.relyingparty.registration.my-relying-party2.identityprovider.sso-url=https://remoteidp2.sso.url

2.9.5. Actuator安全

为了安全起见,默认情况下禁用 /health/info 以外的所有actuators。 management.endpoints.web.exposure.include 属性可用于启用actuators。

如果Spring Security位于类路径上,并且不存在其他 WebSecurityConfigurerAdapter, 则除 /health/info 以外的所有actuators均由Spring Boot自动配置保护。 如果定义自定义 WebSecurityConfigurerAdapter,则Spring Boot自动配置将退出,你将完全控制actuator访问规则。

在设置 management.endpoints.web.exposure.include 之前,请确保暴露的actuators不包含敏感信息和/或通过将它们放置在防火墙后面或通过诸如 Spring Security之类的方法进行保护。
跨站请求伪造保护

由于Spring Boot依赖于Spring Security的默认设置,因此CSRF保护默认情况下处于启用状态。 这意味着在使用默认安全配置时,需要POST(shutdown和loggers端点),PUT或DELETE的actuator端点将收到403 forbidden错误。

我们建议仅在创建非浏览器客户端使用的服务时完全禁用CSRF保护。

关于CSRF保护的其他信息可以在 Spring Security参考指南中找到。

2.10. 使用SQL数据库

Spring Framework为使用SQL数据库提供了广泛的支持,从使用 JdbcTemplate 的直接JDBC 访问到完整的“对象关系映射”技术(例如:Hibernate)。 Spring Data提供了更高级别的功能:直接从接口创建 Repository 实现,并使用约定从你的方法名称生成查询。

2.10.1. 配置DataSource

Java的 javax.sql.DataSource 接口提供了使用数据库连接的标准方法。传统上,“DataSource”使用 URL 和一些凭据来建立数据库连接。

有关更多高级示例,请参见 "How-to"部分,通常可以完全控制DataSource的配置。
嵌入式数据库支持

使用内存嵌入式数据库来开发应用程序通常很方便。显然,内存数据库不提供持久存储。你需要在应用程序启动时填充数据库,并准备在应用程序结束时丢弃数据。

"How-to"部分包括有关 如何初始化数据库的部分

Spring Boot可以自动配置嵌入式 H2HSQLDerby数据库。你无需提供任何连接URL。你只需要包含要使用的嵌入式数据库的构建依赖项即可。

如果你在测试中使用此功能,则可能会注意到,整个测试套件将重复使用同一数据库,而不管你使用的应用程序上下文有多少。 如果要确保每个上下文都有一个单独的嵌入式数据库,则应将 spring.datasource.generate-unique-name 设置为true。

例如,典型的POM依赖关系如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <scope>runtime</scope>
</dependency>
你需要依赖 spring-jdbc 来自动配置嵌入式数据库。在此示例中,它通过 spring-boot-starter-data-jpa 传递性地传入。
如果出于某种原因确实为嵌入式数据库配置了连接URL,请务必确保禁用了数据库的自动关闭功能。 如果使用H2,则应使用 DB_CLOSE_ON_EXIT=FALSE 进行操作。如果使用HSQLDB,则应确保未使用 shutdown=true。 通过禁用数据库的自动关闭功能,Spring Boot可以控制何时关闭数据库,从而确保一旦不再需要访问数据库时就可以进行自动关闭。
连接到生产数据库

生产数据库连接也可以通过使用池化 DataSource 来自动配置。Spring Boot使用以下算法来选择特定的实现:

  1. 我们更喜欢 HikariCP的性能和并发性。如果有HikariCP,我们总是选择它。

  2. 反之,如果Tomcat池化 DataSource 可用,我们将使用它。

  3. HikariCP和Tomcat池数据源均不可用,如果 Commons DBCP2可用,我们将使用它。

如果你使用 spring-boot-starter-jdbcspring-boot-starter-data-jpastarters”,则会自动获得对 HikariCP 的依赖。

你可以通过设置 spring.datasource.type 属性来完全绕过该算法,并指定要使用的连接池。 如果你在Tomcat容器中运行应用程序,这一点尤其重要,因为默认情况下提供了 tomcat-jdbc
其他连接池始终可以手动配置。如果定义自己的 DataSource bean,则不会进行自动配置。

DataSource配置由 spring.datasource.* 中的外部配置属性控制。例如:你可以在 application.properties 中声明以下部分:

spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
你至少应通过设置 spring.datasource.url 属性来指定URL。否则,Spring Boot会尝试自动配置嵌入式数据库。
你通常不需要指定 driver-class-name 名称,因为Spring Boot可以根据 url 从大多数数据库推断出它。
对于要创建池化 DataSource,我们需要能够验证有效的 Driver 类是否可用,因此我们在进行任何操作之前都要进行检查。 换句话说,如果设置 spring.datasource.driver-class-name=com.mysql.jdbc.Driver,则该类必须是可加载的。

有关更多受支持的选项,请参见 DataSourceProperties。 这些是不管实际实现如何都会起作用的标准选项。也可以使用它们各自的前缀( spring.datasource.hikari.*, spring.datasource.tomcat.*spring.datasource.dbcp2.*) 微调实现特定的设置。有关更多详细信息,请参阅所用连接池实现的文档。

例如,如果使用 Tomcat连接池,则可以自定义许多其他设置,如以下示例所示:

# Number of ms to wait before throwing an exception if no connection is available.
spring.datasource.tomcat.max-wait=10000

# Maximum number of active connections that can be allocated from this pool at the same time.
spring.datasource.tomcat.max-active=50

# Validate the connection before borrowing it from the pool.
spring.datasource.tomcat.test-on-borrow=true
连接到JNDI数据源

如果你将Spring Boot应用程序部署到Application Server,则可能需要使用Application Server的内置功能来配置和管理DataSource,并使用JNDI对其进行访问。

spring.datasource.jndi-name 属性可以用作 spring.datasource.urlspring.datasource.usernamespring.datasource.password 属性的替代方案,以从特定的JNDI位置访问 DataSource。 例如:application.properties 中的以下部分显示了如何访问JBoss AS定义的 DataSource

spring.datasource.jndi-name=java:jboss/datasources/customers

2.10.2. 使用JdbcTemplate

Spring的 JdbcTemplateNamedParameterJdbcTemplate 类是自动配置的,你可以将它们直接 @Autowire 到自己的bean中,如以下示例所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public MyBean(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    // ...

}

你可以使用 spring.jdbc.template.* 属性来自定义模板的某些属性,如以下示例所示:

spring.jdbc.template.max-rows=500
NamedParameterJdbcTemplate 在幕后重用相同的 JdbcTemplate 实例。如果定义了多个 JdbcTemplate 并且不存在主要候选对象,则不会自动配置 NamedParameterJdbcTemplate

2.10.3. JPA和Spring Data JPA

Java Persistence API是一种标准技术,可让你将对象“映射”到关系数据库。 spring-boot-starter-data-jpa POM提供了一种快速入门的方法。它提供以下关键依赖:

  • Hibernate: 最受欢迎的JPA实现之一。

  • Spring Data JPA: 使基于JPA的存储库的实现变得容易。

  • Spring ORMs: Spring框架对ORM的核心支持。

在这里,我们不会过多讨论JPA或 Spring Data。 你可以按照 https://spring.io“使用JPA访问数据”指南进行操作, 并阅读 Spring Data JPAHibernate参考文档。
实体类

传统上,JPA“Entity”类在 persistence.xml 文件中指定。在Spring Boot中,此文件不是必需的,而是使用“实体扫描”。 默认情况下,将搜索主配置类(用 @EnableAutoConfiguration@SpringBootApplication 注解的一个)下的所有软件包。

考虑任何带有 @Entity@Embeddable@MappedSuperclass 注解的类。典型的实体类类似于以下示例:

package com.example.myapp.domain;

import java.io.Serializable;
import javax.persistence.*;

@Entity
public class City implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private String state;

    // ... additional members, often include @OneToMany mappings

    protected City() {
        // no-args constructor required by JPA spec
        // this one is protected since it shouldn't be used directly
    }

    public City(String name, String state) {
        this.name = name;
        this.state = state;
    }

    public String getName() {
        return this.name;
    }

    public String getState() {
        return this.state;
    }

    // ... etc

}
你可以使用 @EntityScan 注解来自定义实体扫描位置。请参见 “从Spring配置中分离@Entity定义”
Spring Data JPA存储库

Spring Data JPA存储库是可以定义以访问数据的接口。JPA查询是根据你的方法名称自动创建的。 例如:CityRepository 接口可能声明了 findAllByState(String state) 方法来查找给定状态下的所有城市。

对于更复杂的查询,你可以使用Spring Data的 Query注解对方法进行注释。

Spring Data存储库通常从 RepositoryCrudRepository接口继承。 如果使用自动配置,则会从包含主配置类(以 @EnableAutoConfiguration@SpringBootApplication 注解的主配置类)的包中搜索存储库。

以下示例显示了典型的Spring Data存储库接口定义:

package com.example.myapp.domain;

import org.springframework.data.domain.*;
import org.springframework.data.repository.*;

public interface CityRepository extends Repository<City, Long> {

    Page<City> findAll(Pageable pageable);

    City findByNameAndStateAllIgnoringCase(String name, String state);

}

Spring Data JPA存储库支持三种不同的引导模式:default, deferred 和 lazy。 要启用deferred引导或lazy引导,请将 spring.data.jpa.repositories.bootstrap-mode 属性分别设置为 deferredlazy。 使用deferred或lazy启动时,自动配置的 EntityManagerFactoryBuilder 将使用上下文的 AsyncTaskExecutor(如果有)作为引导执行器。 如果存在多个,则将使用一个名为 applicationTaskExecutor 的执行器。

我们仅仅触及了Spring Data JPA的皮毛。有关完整的详细信息,请参阅 Spring Data JPA参考文档
创建和删除JPA数据库

默认情况下, 当你使用嵌入式数据库(H2,HSQL或Derby)时,才会自动创建JPA数据库。 你可以使用 spring.jpa.* 属性显式配置JPA设置。 例如:要创建和删除表,可以将以下行添加到 application.properties

spring.jpa.hibernate.ddl-auto=create-drop
为此,Hibernate自己的内部属性名称是 hibernate.hbm2ddl.auto。 你可以使用 spring.jpa.properties.*(将它们添加到实体管理器时,会先剔除前缀)来设置它以及其他Hibernate本地属性。 下面的行显示了为Hibernate设置JPA属性的示例:
spring.jpa.properties.hibernate.globally_quoted_identifiers=true

前面示例中的行将 hibernate.globally_quoted_identifiers 属性值设置为 true 传递给Hibernate实体管理器。

默认情况下,DDL执行(或验证)推迟到 ApplicationContext 启动之后。还有一个 spring.jpa.generate-ddl 标志, 但是如果Hibernate自动配置处于活动状态,则不会使用它,因为 ddl-auto 设置粒度更细。

在视图中打开EntityManager

如果你正在运行Web应用程序,则Spring Boot默认情况下会注册 OpenEntityManagerInViewInterceptor 以应用“在视图中打开EntityManager”模式,以允许在Web视图中进行延迟加载。 如果你不希望出现这种情况,则应在 application.properties 中将 spring.jpa.open-in-view 设置为 false

2.10.4. Spring Data JDBC

Spring Data包括对JDBC的存储库支持,并将为 CrudRepository 上的方法自动生成SQL。对于更高级的查询,提供了 @Query 注解。

当必要的依赖项位于类路径上时,Spring Boot将自动配置Spring Data的JDBC存储库。 可以将它们添加到你的项目中,而只需依赖 spring-boot-starter-data-jdbc。 如有必要,你可以通过在应用程序中添加 @EnableJdbcRepositories 注解或 JdbcConfiguration 子类来控制Spring Data JDBC的配置。

有关Spring Data JDBC的完整详细信息,请参考 参考文档

2.10.5. 使用H2的Web控制台

H2数据库提供了一个 基于浏览器的控制台, Spring Boot可以为你自动配置该控制台。满足以下条件时,将自动配置控制台:

如果你未使用Spring Boot的开发者工具,但仍想使用H2的控制台,则可以将 spring.h2.console.enabled 属性配置为 true
H2控制台仅在开发期间使用,因此应注意确保在生产中未将 spring.h2.console.enabled 设置为 true
更改H2控制台的路径

默认情况下,该控制台在 /h2-console 端点可用。你可以使用 spring.h2.console.path 属性来自定义控制台的路径。

2.10.6. 使用jOOQ

jOOQ Object Oriented Querying (jOOQ)是 Data Geekery 的一种流行产品,它可以从数据库中生成Java代码,并允许你通过其流式API构建类型安全的SQL查询。商业版和开源版都可以与Spring Boot一起使用。

代码生成

为了使用jOOQ类型安全查询,你需要从数据库schema中生成Java类。你可以按照 jOOQ用户手册中的说明进行操作。 如果你使用 jooq-codegen-maven 插件,并且还使用 spring-boot-starter-parent “父POM”, 则可以安全地忽略该插件的 <version> 标签。你还可以使用Spring Boot定义的版本变量(例如:h2.version) 来声明插件的数据库依赖关系。以下清单显示了一个示例:

<plugin>
    <groupId>org.jooq</groupId>
    <artifactId>jooq-codegen-maven</artifactId>
    <executions>
        ...
    </executions>
    <dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>${h2.version}</version>
        </dependency>
    </dependencies>
    <configuration>
        <jdbc>
            <driver>org.h2.Driver</driver>
            <url>jdbc:h2:~/yourdatabase</url>
        </jdbc>
        <generator>
            ...
        </generator>
    </configuration>
</plugin>
使用DSLContext

jOOQ提供的流式API是通过 org.jooq.DSLContext 接口启动的。 Spring Boot将 DSLContext 自动配置为Spring Bean,并将其连接到你的应用程序 DataSource。 要使用 DSLContext,可以使用 @Autowire,如下例所示:

@Component
public class JooqExample implements CommandLineRunner {

    private final DSLContext create;

    @Autowired
    public JooqExample(DSLContext dslContext) {
        this.create = dslContext;
    }

}
jOOQ手册倾向于使用名为 create 的变量来保存 DSLContext

然后,可以使用 DSLContext 构造查询,如以下示例所示:

public List<GregorianCalendar> authorsBornAfter1980() {
    return this.create.selectFrom(AUTHOR)
        .where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))
        .fetch(AUTHOR.DATE_OF_BIRTH);
}
jOOQ SQL方言

除非已配置 spring.jooq.sql-dialect 属性,否则Spring Boot会确定要用于数据源的SQL方言。如果Spring Boot无法检测到方言,则使用 DEFAULT

Spring Boot只能自动配置开源版本的jOOQ支持的方言。
自定义jOOQ

可以通过定义自己的 @Bean 定义来实现更高级的自定义,这在创建jOOQ Configuration 时将使用。你可以为以下jOOQ类型定义bean:

  • ConnectionProvider

  • ExecutorProvider

  • TransactionProvider

  • RecordMapperProvider

  • RecordUnmapperProvider

  • Settings

  • RecordListenerProvider

  • ExecuteListenerProvider

  • VisitListenerProvider

  • TransactionListenerProvider

如果要完全控制jOOQ配置,也可以创建自己的 org.jooq.Configuration @Bean

2.11. 使用NoSQL技术

Spring Data提供了其他项目来帮助你访问各种NoSQL技术,包括:

Spring Boot为Redis,MongoDB,Neo4j,Elasticsearch,Solr Cassandra,Couchbase和LDAP提供自动配置。 你可以使用其他项目,但必须自己进行配置。请参阅 https://spring.io/projects/spring-data 中的相应参考文档。

2.11.1. Redis

Redis是一个缓存,消息代理和功能丰富的键值存储。 Spring Boot为 LettuceJedis 客户端库以及Spring Data Redis提供的基于它们的抽象提供了基本的自动配置。

有一个 spring-boot-starter-data-redis “Starter” 便于收集依赖项。默认情况下,它使用 Lettuce。 该启动器可以处理传统应用程序和响应式应用程序。

我们还提供了一个 spring-boot-starter-data-redis-reactiveStarter”,以与具有响应式支持的其他存储保持一致。
连接到Redis

你可以像注入其他任何Spring Bean一样注入自动配置的 RedisConnectionFactoryStringRedisTemplate 或vanilla RedisTemplate 实例。默认情况下,该实例尝试连接到位于 localhost:6379 的Redis服务器。 下面的清单显示了这种Bean的示例:

@Component
public class MyBean {

    private StringRedisTemplate template;

    @Autowired
    public MyBean(StringRedisTemplate template) {
        this.template = template;
    }

    // ...

}
你还可以注册任意数量的Bean,这些Bean实现 LettuceClientConfigurationBuilderCustomizer 以获得更高级的自定义。 如果使用Jedis,则可以使用 JedisClientConfigurationBuilderCustomizer

如果添加自己的任何自动配置类型的 @Bean,它将替换默认值 (RedisTemplate 除外,除非排除是基于bean名称 redisTemplate 而不是其类型时)。 默认情况下,如果 commons-pool2 在类路径上,则会得到一个池化的连接工厂。

2.11.2. MongoDB

MongoDB是一个开源NoSQL文档数据库,它使用类似JSON的结构而不是传统的基于表的关系数据。 Spring Boot为MongoDB的使用提供了许多便利,包括 spring-boot-starter-data-mongodbspring-boot-starter-data-mongodb-reactive “Starter”。

连接到MongoDB数据库

要访问Mongo数据库,可以注入自动配置的 org.springframework.data.mongodb.MongoDbFactory。 默认情况下,该实例尝试通过 mongodb://localhost/test 连接到MongoDB服务器。 以下示例显示了如何连接到MongoDB数据库:

import org.springframework.data.mongodb.MongoDbFactory;
import com.mongodb.DB;

@Component
public class MyBean {

    private final MongoDbFactory mongo;

    @Autowired
    public MyBean(MongoDbFactory mongo) {
        this.mongo = mongo;
    }

    // ...

    public void example() {
        DB db = mongo.getDb();
        // ...
    }

}

你可以设置 spring.data.mongodb.uri 属性来更改URL并配置其他设置,例如 副本集,如以下示例所示:

spring.data.mongodb.uri=mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test

另外,只要你使用Mongo 2.x,就可以指定 host/port。例如:你可以在 application.properties 中声明以下设置:

spring.data.mongodb.host=mongoserver
spring.data.mongodb.port=27017

如果你定义了自己的 MongoClient,它将用于自动配置合适的 MongoDbFactorycom.mongodb.MongoClientcom.mongodb.client.MongoClient 均受支持。

如果使用Mongo 3.0 Java驱动程序,则不支持 spring.data.mongodb.hostspring.data.mongodb.port。 在这种情况下,应使用 spring.data.mongodb.uri 提供所有配置。
如果未指定 spring.data.mongodb.port,则使用默认值 27017。你可以从前面显示的示例中删除此行。
如果不使用Spring Data Mongo,则可以注入 com.mongodb.MongoClient bean,而不是使用 MongoDbFactory。 如果你想完全控制建立MongoDB连接的方式,还可以声明自己的 MongoDbFactoryMongoClient bean。
如果你使用响应式驱动程序,则SSL需要Netty。如果Netty可用并且尚未自定义要使用的工厂,则自动配置会自动配置该工厂。
MongoTemplate

Spring Data MongoDB提供了一个 MongoTemplate类, 该类的设计与Spring的 JdbcTemplate 非常相似。与 JdbcTemplate 一样,Spring Boot为你自动配置一个Bean来注入模板,如下所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final MongoTemplate mongoTemplate;

    @Autowired
    public MyBean(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    // ...

}

有关完整的详细信息,请参见 MongoOperations Javadoc

Spring Data MongoDB存储库

Spring Data包括对MongoDB的存储库支持。与前面讨论的JPA存储库一样,基本原理是根据方法名称自动构造查询。

实际上,Spring Data JPA和Spring Data MongoDB共享相同的通用基础设施。你可以从以前的JPA示例开始,并假设 City 现在是Mongo数据类,而不是JPA @Entity,它的工作方式相同,如以下示例所示:

package com.example.myapp.domain;

import org.springframework.data.domain.*;
import org.springframework.data.repository.*;

public interface CityRepository extends Repository<City, Long> {

    Page<City> findAll(Pageable pageable);

    City findByNameAndStateAllIgnoringCase(String name, String state);

}
你可以使用 @EntityScan 注解来自定义文档扫描位置。
有关Spring Data MongoDB的完整详细信息,包括其丰富的对象映射技术,请参阅其 参考文档
嵌入式Mongo

Spring Boot为 Embedded Mongo提供自动配置。 要在Spring Boot应用程序中使用它,请添加对 de.flapdoodle.embed:de.flapdoodle.embed.mongo 的依赖。

可以通过设置 spring.data.mongodb.port 属性来配置Mongo监听的端口。要使用随机分配的空闲端口,请使用0值。 MongoAutoConfiguration 创建的 MongoClient 将自动配置为使用随机分配的端口。

如果未配置自定义端口,则默认情况下,嵌入式支持会使用随机端口(而不是27017)。

如果类路径上有SLF4J,则Mongo产生的输出将自动路由到名为 org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongo 的记录器。

你可以声明自己的 IMongodConfigIRuntimeConfig bean,以控制Mongo实例的配置和日志记录路由。 可以通过声明 DownloadConfigBuilderCustomizer bean来定制下载配置。

2.11.3. Neo4j

Neo4j是一个开源NoSQL图形数据库,它使用了由一级关系连接的节点的丰富数据模型, 与传统的RDBMS方法相比,它更适合于连接的大数据。Spring Boot为Neo4j的使用提供了许多便利,包括 spring-boot-starter-data-neo4j “Starter”。

连接到Neo4j数据库

要访问Neo4j服务器,你可以注入自动配置的 org.neo4j.ogm.session.Session。 默认情况下,该实例尝试使用Bolt协议连接到 localhost:7687 处的Neo4j服务器。下面的示例显示如何注入Neo4j Session

@Component
public class MyBean {

    private final Session session;

    @Autowired
    public MyBean(Session session) {
        this.session = session;
    }

    // ...

}

你可以通过设置 spring.data.neo4j.* 属性来配置要使用的uri和凭据,如以下示例所示:

spring.data.neo4j.uri=bolt://my-server:7687
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=secret

通过添加 org.neo4j.ogm.config.Configuration bean或 org.neo4j.ogm.session.SessionFactory bean,可以完全控制会话的创建。

使用嵌入式模式

如果将 org.neo4j:neo4j-ogm-embedded-driver 添加到应用程序的依赖项中, 则Spring Boot会自动配置Neo4j的进程内嵌入式实例,该实例在应用程序关闭时不会保留任何数据。

由于嵌入式Neo4j OGM驱动程序本身不提供Neo4j内核,因此你必须自己声明 org.neo4j:neo4j 为依赖项。 有关兼容版本的列表,请参阅 Neo4j OGM文档

当类路径上有多个驱动程序时,嵌入式驱动程序优先于其他驱动程序。你可以通过设置 spring.data.neo4j.embedded.enabled=false 显式禁用嵌入式模式。

如果嵌入式驱动程序和Neo4j内核位于上述类路径上, 则Data Neo4j Tests会自动使用嵌入式Neo4j实例。

你可以通过在配置中提供数据库文件的路径来启用嵌入式模式的持久性。 例如: spring.data.neo4j.uri=file://var/tmp/graph.db
使用Native类型

Neo4j-OGM可以将某些类型(例如:java.time.* 中的类型)映射到基于String的属性或Neo4j提供的原生类型之一。 出于向后兼容的原因,Neo4j-OGM的默认设置是使用基于字符串的表示形式。要使用原生类型,请添加对 org.neo4j:neo4j-ogm-bolt-native-typesorg.neo4j:neo4j-ogm-embedded-native-types 的依赖关系, 并配置 spring.data.neo4j.use-native-types 属性,如以下示例所示:

spring.data.neo4j.use-native-types=true
Neo4jSession

默认情况下,如果你正在运行Web应用程序,则会话将绑定到线程以进行请求的整个处理(即,它使用“Open Session in View”模式)。 如果你不希望出现这种情况,请将以下行添加到 application.properties 文件中:

spring.data.neo4j.open-in-view=false
Spring Data Neo4j存储库

Spring Data包括对Neo4j的存储库支持。

Spring Data Neo4j与许多其他Spring Data模块一样,与Spring Data JPA共享公共基础设施。 你可以采用前面的JPA示例,并将 City 定义为Neo4j OGM @NodeEntity 而不是JPA @Entity,并且存储库抽象以相同的方式工作,如以下示例所示:

package com.example.myapp.domain;

import java.util.Optional;

import org.springframework.data.neo4j.repository.*;

public interface CityRepository extends Neo4jRepository<City, Long> {

    Optional<City> findOneByNameAndState(String name, String state);

}

spring-boot-starter-data-neo4j “Starter” 可支持存储库以及事务管理。 你可以通过分别在 @Configuration-bean上使用 @EnableNeo4jRepositories@EntityScan 来定制位置以查找存储库和实体。

有关Spring Data Neo4j的完整详细信息,包括其对象映射技术,请参阅 参考文档

2.11.4. Solr

Apache Solr是一个搜索引擎。 Spring Boot为Solr 5客户端库提供了基本的自动配置,并由 Spring Data Solr在其之上提供了抽象。 spring-boot-starter-data-solr “Starter” 用于以方便的方式收集依赖项。

连接到Solr

你可以像插入其他任何Spring Bean一样注入自动配置的 SolrClient 实例。默认情况下,该实例尝试连接到位于 http://localhost:8983/solr 的服务器。以下示例显示如何注入Solr bean:

@Component
public class MyBean {

    private SolrClient solr;

    @Autowired
    public MyBean(SolrClient solr) {
        this.solr = solr;
    }

    // ...

}

如果添加自己的类型为 SolrClient@Bean,它将替换默认值。

Spring Data Solr存储库

Spring Data包括对Apache Solr的存储库支持。与前面讨论的JPA存储库一样,基本原理是根据方法名称自动为你构建查询。

实际上,Spring Data JPA和Spring Data Solr共享相同的通用基础设施。你可以从以前的JPA示例开始,并假设 City 现在是 @SolrDocument 类,而不是JPA @Entity,它的工作方式相同。

有关Spring Data Solr的完整详细信息,请参阅 参考文档

2.11.5. Elasticsearch

Elasticsearch是一个开源,分布式,RESTful搜索和分析引擎。 Spring Boot为Elasticsearch提供了基本的自动配置。

Spring Boot支持多个客户端:

  • 官方Java“低级”和“高级”REST客户端

  • Spring Data Elasticsearch提供的 ReactiveElasticsearchClient

传输客户端仍然可用,但是 Spring Data Elasticsearch和Elasticsearch本身已弃用了它的支持。 它将在未来的版本中删除。Spring Boot提供了专用的 “Starter”, 即 spring-boot-starter-data-elasticsearch

由于Elasticsearch和Spring Data Elasticsearch为REST客户端提供了官方支持,因此 Jest客户端也已被弃用。

使用REST客户端连接到Elasticsearch

Elasticsearch附带了两个可用于查询集群的 REST客户端: “低级”客户端和“高级”客户端。

如果你的类路径具有 org.elasticsearch.client:elasticsearch-rest-client 依赖关系,Spring Boot将自动配置并注册一个 RestClient Bean,默认情况下,它连接到 http://localhost:9200。你可以进一步调整 RestClient 的配置方式,如以下示例所示:

spring.elasticsearch.rest.uris=https://search.example.com:9200
spring.elasticsearch.rest.read-timeout=10s
spring.elasticsearch.rest.username=user
spring.elasticsearch.rest.password=secret

你还可以注册任意数量的Bean,它们实现了 RestClientBuilderCustomizer 来进行更高级的自定义。要完全控制注册,请定义 RestClient bean。

如果你的类路径具有 org.elasticsearch.client:elasticsearch-rest-high-level-client 依赖关系, 则Spring Boot将自动配置 RestHighLevelClient,它将包装任何现有的 RestClient bean,并重用其HTTP配置。

使用响应式REST客户端连接到Elasticsearch

Spring Data Elasticsearch 提供了 ReactiveElasticsearchClient,用于以响应式方式查询Elasticsearch实例。 它基于WebFlux的 WebClient 构建,因此 spring-boot-starter-elasticsearchspring-boot-starter-webflux 依赖关系对于启用此支持都是有用的。

默认情况下,Spring Boot将自动配置并注册一个针对 http://localhost:9200ReactiveElasticsearchClient bean。你可以进一步调整其配置,如以下示例所示:

spring.data.elasticsearch.client.reactive.endpoints=search.example.com:9200
spring.data.elasticsearch.client.reactive.use-ssl=true
spring.data.elasticsearch.client.reactive.socket-timeout=10s
spring.data.elasticsearch.client.reactive.username=user
spring.data.elasticsearch.client.reactive.password=secret

如果配置属性不够,并且你想完全控制客户端配置,则可以注册自定义 ClientConfiguration bean。

使用Jest连接到Elasticsearch

现在,Spring Boot支持官方的 RestHighLevelClient,不再支持Jest。

如果在类路径上有 Jest,则可以注入默认情况下以 http://localhost:9200 为目标的自动配置的 JestClient。 你可以进一步调整客户端的配置,如以下示例所示:

spring.elasticsearch.jest.uris=https://search.example.com:9200
spring.elasticsearch.jest.read-timeout=10000
spring.elasticsearch.jest.username=user
spring.elasticsearch.jest.password=secret

你还可以注册任意数量的实现 HttpClientConfigBuilderCustomizer 的bean,以进行更高级的自定义。以下示例调整其他HTTP设置:

static class HttpSettingsCustomizer implements HttpClientConfigBuilderCustomizer {

    @Override
    public void customize(HttpClientConfig.Builder builder) {
        builder.maxTotalConnection(100).defaultMaxTotalConnectionPerRoute(5);
    }

}

要完全控制注册,请定义 JestClient bean。

使用Spring Data连接到Elasticsearch

要连接到Elasticsearch,必须定义由Spring Boot自动配置或由应用程序手动提供的 RestHighLevelClient bean(请参阅前面的部分)。 有了此配置后,可以像其他任何Spring bean一样注入 ElasticsearchRestTemplate,如以下示例所示:

@Component
public class MyBean {

    private final ElasticsearchRestTemplate template;

    public MyBean(ElasticsearchRestTemplate template) {
        this.template = template;
    }

    // ...

}

在存在 spring-data-elasticsearch 和使用 WebClient 所需的依赖关系(通常是 spring-boot-starter-webflux )的情况下, Spring Boot还可以将 ReactiveElasticsearchClientReactiveElasticsearchTemplate 自动配置为bean。它们与其他REST 客户端是等效的。

Spring Data Elasticsearch存储库

Spring Data包括对Elasticsearch的存储库支持。与前面讨论的JPA存储库一样,基本原理是根据方法名称自动为你构造查询。

实际上,Spring Data JPA和Spring Data Elasticsearch共享相同的通用基础设施。你可以从以前的JPA示例开始,并假设 City 现在是Elasticsearch @Document 类而不是JPA @Entity,它的工作方式相同。

有关Spring Data Elasticsearch的完整详细信息,请参阅 参考文档

Spring Boot使用 ElasticsearchRestTemplateReactiveElasticsearchTemplate bean支持经典和响应式Elasticsearch存储库。如果提供了所需的依赖项,这些bean很可能是通过Spring Boot自动配置的。

如果你希望使用自己的模板来支持Elasticsearch存储库,则可以添加自己的 ElasticsearchRestTemplateElasticsearchOperations @Bean,只要它名为 “elasticsearchTemplate” 即可。同样适用于 ReactiveElasticsearchTemplateReactiveElasticsearchOperations,其bean名称为 “reactiveElasticsearchTemplate”。

你可以选择使用以下属性禁用存储库支持:

spring.data.elasticsearch.repositories.enabled=false

2.11.6. Cassandra

Cassandra 是一个开源的分布式数据库管理系统,旨在处理许多商用服务器上的大量数据。 Spring Boot为Cassandra提供自动配置,并由 Spring Data Cassandra在其之上提供抽象。 有一个 spring-boot-starter-data-cassandra “Starter”,用于以方便的方式收集依赖项。

连接到Cassandra

你可以像使用其他任何Spring Bean一样注入自动配置的 CassandraTemplate 或Cassandra Session 实例。 spring.data.cassandra.* 属性可用于自定义连接。通常,你会提供 keyspace-namecontact-points 属性,如以下示例所示:

spring.data.cassandra.keyspace-name=mykeyspace
spring.data.cassandra.contact-points=cassandrahost1,cassandrahost2

你还可以注册任意数量的Bean,这些Bean实现 ClusterBuilderCustomizer 以获得更高级的自定义。

以下代码清单显示了如何注入Cassandra bean:

@Component
public class MyBean {

    private CassandraTemplate template;

    @Autowired
    public MyBean(CassandraTemplate template) {
        this.template = template;
    }

    // ...

}

如果添加自己的 CassandraTemplate 类型的 @Bean,它将替换默认值。

Spring Data Cassandra存储库

Spring Data包括对Cassandra的基本存储库支持。当前,这比前面讨论的JPA存储库受到更多限制,并且需要使用 @Query 注解finder方法。

有关Spring Data Cassandra的完整详细信息,请参阅 参考文档

2.11.7. Couchbase

Couchbase 是一个开源,分布式,多模型的NoSQL面向文档的数据库,已针对交互式应用程序进行了优化。 Spring Boot为Couchbase提供自动配置,并由 Spring Data Couchbase在其之上提供抽象。 有 spring-boot-starter-data-couchbasespring-boot-starter-data-couchbase-reactive “Starters”,用于以方便的方式收集依赖项。

连接到Couchbase

你可以通过添加Couchbase SDK和一些配置来获取 BucketClusterspring.couchbase.* 属性可用于自定义连接。通常,你会提供引导主机,存储桶名称和密码,如以下示例所示:

spring.couchbase.bootstrap-hosts=my-host-1,192.168.1.123
spring.couchbase.bucket.name=my-bucket
spring.couchbase.bucket.password=secret
至少 需要提供引导主机,在这种情况下,存储桶名称为 default,密码为空字符串。另外,你可以定义自己的 org.springframework.data.couchbase.config.CouchbaseConfigurer @Bean 来控制整个配置。

还可以自定义某些 CouchbaseEnvironment 设置。例如,以下配置更改了用于打开新 Bucket 并启用SSL支持的超时:

spring.couchbase.env.timeouts.connect=3000
spring.couchbase.env.ssl.key-store=/location/of/keystore.jks
spring.couchbase.env.ssl.key-store-password=secret

检查 spring.couchbase.env.* 属性以获取更多详细信息。

Spring Data Couchbase Repositories

Spring Data包括对Couchbase的存储库支持。有关Spring Data Couchbase的完整详细信息,请参阅 参考文档

你可以像使用任何其他Spring Bean一样注入自动配置的 CouchbaseTemplate 实例,前提是提供的 默认 CouchbaseConfigurer 可用 (如前所述,当启用Couchbase支持时会发生这种情况)。

以下示例显示了如何注入Couchbase bean:

@Component
public class MyBean {

    private final CouchbaseTemplate template;

    @Autowired
    public MyBean(CouchbaseTemplate template) {
        this.template = template;
    }

    // ...

}

你可以在自己的配置中定义一些Bean,以覆盖自动配置所提供的那些:

  • 一个名为 couchbaseTemplateCouchbaseTemplate @Bean

  • 一个名为 couchbaseIndexManagerIndexManager @Bean

  • 一个名为 couchbaseCustomConversionsCustomConversions @Bean

为了避免在你自己的配置中对这些名称进行硬编码,你可以重用Spring Data Couchbase提供的 BeanNames。 例如,你可以自定义要使用的转换器,如下所示:

@Configuration(proxyBeanMethods = false)
public class SomeConfiguration {

    @Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
    public CustomConversions myCustomConversions() {
        return new CustomConversions(...);
    }

    // ...

}
如果要完全绕过Spring Data Couchbase的自动配置,请提供自己的 org.springframework.data.couchbase.config.AbstractCouchbaseDataConfiguration 实现。

2.11.8. LDAP

LDAP(轻型目录访问协议)是一种开放的,与供应商无关的行业标准应用协议, 用于通过IP网络访问和维护分布式目录信息服务。Spring Boot为任何兼容的LDAP服务器提供自动配置, 并从 UnboundID支持嵌入式内存LDAP服务器。

LDAP抽象由 Spring Data LDAP提供。 有一个 spring-boot-starter-data-ldap “Starter”,以方便的方式收集依赖项。

连接到LDAP服务器

要连接到LDAP服务器,请确保声明对 spring-boot-starter-data-ldap “Starter” 或 spring-ldap-core 的依赖关系,然后在 application.properties 中声明服务器的URL,如下面的例子所示:

spring.ldap.urls=ldap://myserver:1235
spring.ldap.username=admin
spring.ldap.password=secret

如果需要自定义连接设置,则可以使用 spring.ldap.basespring.ldap.base-environment 属性。

将基于这些设置自动配置 LdapContextSource。如果 DirContextAuthenticationStrategy Bean可用, 则将其与自动配置的 LdapContextSource 关联。如果你需要对其进行自定义(例如:使用 PooledContextSource), 则仍然可以注入自动配置的 LdapContextSource。确保将自定义的 ContextSource 标记为 @Primary,以便自动配置的 LdapTemplate 使用它。

Spring Data LDAP存储库

Spring Data包括对LDAP的存储库支持。有关Spring Data LDAP的完整详细信息,请参阅 参考文档

你还可以像使用其他任何Spring Bean一样注入自动配置的 LdapTemplate 实例,如以下示例所示:

@Component
public class MyBean {

    private final LdapTemplate template;

    @Autowired
    public MyBean(LdapTemplate template) {
        this.template = template;
    }

    // ...

}
嵌入式内存LDAP服务器

出于测试目的,Spring Boot支持从 UnboundID自动配置内存中的LDAP服务器。 要配置服务器,请添加 com.unboundid:unboundid-ldapsdk 依赖项,并声明 spring.ldap.embedded.base-dn 属性,如下所示:

spring.ldap.embedded.base-dn=dc=spring,dc=io

可以定义多个base-dn值,但是,由于可分辨的名称通常包含逗号,因此必须使用正确的符号来定义它们。

在yaml文件中,你可以使用yaml列表符号:

spring.ldap.embedded.base-dn:
  - dc=spring,dc=io
  - dc=pivotal,dc=io

在属性文件中,必须将索引包括在属性名称中:

spring.ldap.embedded.base-dn[0]=dc=spring,dc=io
spring.ldap.embedded.base-dn[1]=dc=pivotal,dc=io

默认情况下,服务器在随机端口上启动并触发常规LDAP支持,无需指定 spring.ldap.urls 属性。

如果你的类路径上有一个 schema.ldif 文件,则该文件用于初始化服务器。如果要从其他资源加载初始化脚本,则也可以使用 spring.ldap.embedded.ldif 属性。

默认情况下,使用标准架构来验证 LDIF 文件。你可以通过设置 spring.ldap.embedded.validation.enabled 属性来完全关闭验证。 如果具有自定义属性,那么可以使用 spring.ldap.embedded.validation.schema 定义自定义属性类型或对象类。

2.11.9. InfluxDB

InfluxDB是一个开放源代码的时间序列数据库,已优化用于在操作监视,应用程序度量, 物联网传感器数据和实时分析等领域中快速,高可用性地存储和检索时间序列数据。

连接到InfluxDB

只要 influxdb-java 客户端位于类路径上并设置了数据库的URL,Spring Boot就会自动配置 InfluxDB 实例,如以下示例所示:

spring.influx.url=https://172.0.0.1:8086

如果与InfluxDB的连接需要用户和密码,则可以相应地设置 spring.influx.userspring.influx.password 属性。

InfluxDB依赖OkHttp。如果需要在后台调整 InfluxDB 使用的http客户端,则可以注册 InfluxDbOkHttpClientBuilderProvider bean。

2.12. 缓存

Spring框架提供了对向应用程序透明添加缓存的支持。从本质上讲,抽象将缓存应用于方法,从而根据缓存中可用的信息减少执行次数。 缓存逻辑是透明应用的,不会对调用者造成任何干扰。只要通过 @EnableCaching 注解启用了缓存支持,Spring Boot就会自动配置缓存基础设施。

检查Spring Framework指南的 相关部分以获取更多详细信息。

简而言之,将缓存添加到服务的操作就像将相关注解添加到其方法一样容易,如以下示例所示:

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

@Component
public class MathService {

    @Cacheable("piDecimals")
    public int computePiDecimal(int i) {
        // ...
    }

}

本示例说明了在潜在的昂贵操作上使用缓存的方法。在调用 computePiDecimal 之前,抽象将在 piDecimals 缓存中查找与 i 参数匹配的条目。 如果找到条目,则高速缓存中的内容会立即返回给调用方,并且不会调用该方法。否则,将调用该方法,并在返回值之前更新缓存。

你还可以透明地使用标准JSR-107(JCache)注解(例如:@CacheResult)。但是,我们强烈建议你不要混合使用Spring Cache和JCache注解。

如果你不添加任何特定的缓存库,Spring Boot会自动配置一个使用内存中concurrent maps的简单供应商。 当需要缓存时(例如:上例中的 piDecimals),此供应商将为你创建它。实际上,不建议将该简单供应商用于生产环境, 但是它对于入门并确保你了解功能非常有用。确定要使用的缓存供应商后,请确保阅读其文档,以了解如何配置应用程序使用的缓存。 几乎所有供应商都要求你显式配置在应用程序中使用的每个缓存。有些提供自定义 spring.cache.cache-names 属性来定义默认缓存的方法。

还可以透明地 更新或从缓存中 驱逐数据。

2.12.1. 支持的缓存供应商

缓存抽象不提供实际的存储,而是依赖于由 org.springframework.cache.Cacheorg.springframework.cache.CacheManager 接口实现的抽象。

如果尚未定义 CacheManager 类型的Bean或名为 cacheResolverCacheResolver (请参阅 CachingConfigurer), 则Spring Boot尝试检测以下供应商(按指示的顺序):

  1. Generic

  2. JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, and others)

  3. EhCache 2.x

  4. Hazelcast

  5. Infinispan

  6. Couchbase

  7. Redis

  8. Caffeine

  9. Simple

也可以通过设置 spring.cache.type 属性来 强制 指定特定的缓存供应商。如果你需要在某些环境(例如测试)中 完全禁用缓存,请使用此属性。
使用 spring-boot-starter-cacheStarter”快速添加基本的缓存依赖项。入门程序提供了 spring-context-support。 如果手动添加依赖项,则必须包括 spring-context-support 才能使用JCache,EhCache 2.x或Caffeine支持。

如果 CacheManager 是由Spring Boot自动配置的,则可以通过公开实现 CacheManagerCustomizer 接口的bean, 在完全初始化之前进一步调整其配置。下面的示例设置一个标志,指示应该将 null 值向下传递到基础映射:

@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
    return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {
        @Override
        public void customize(ConcurrentMapCacheManager cacheManager) {
            cacheManager.setAllowNullValues(false);
        }
    };
}
在前面的示例中,需要一个自动配置的 ConcurrentMapCacheManager。 如果不是这种情况(你提供了自己的配置,或者自动配置了其他缓存供应商),则根本不会调用定制程序。 你可以根据需要拥有任意数量的定制程序,也可以使用 @OrderOrdered 对其进行排序。
泛型

如果上下文定义了 至少一个 org.springframework.cache.Cache bean,则使用泛型缓存。 创建一个包装所有该类型Bean的 CacheManager

JCache (JSR-107)

通过在类路径上存在 javax.cache.spi.CachingProvider 引导 JCache(即,在类路径上存在符合JSR-107的缓存库), 并且 JCacheCacheManagerspring-boot-starter-cacheStarter”提供。 提供了各种兼容的库,Spring Boot为Ehcache 3,Hazelcast和Infinispan提供了依赖管理。也可以添加任何其他兼容的库。

可能会出现多个供应商,在这种情况下,必须明确指定供应商。即使JSR-107标准没有强制采用标准化的方式来定义配置文件的位置, Spring Boot也会尽其最大努力来容纳具有实现细节的缓存,如以下示例所示:

# Only necessary if more than one provider is present
spring.cache.jcache.provider=com.acme.MyCachingProvider
spring.cache.jcache.config=classpath:acme.xml
当缓存库同时提供native实现和JSR-107支持时,Spring Boot会首选JSR-107支持,因此,如果你切换到其他JSR-107实现,则可以使用相同的功能。
Spring Boot对Hazelcast具有常规支持。 如果有单个 HazelcastInstance 可用,则除非指定了 spring.cache.jcache.config 属性,否则它也会自动用于 CacheManager

自定义基础 javax.cache.cacheManager 有两种方法:

  • 可以在启动时通过设置 spring.cache.cache-names 属性来创建缓存。 如果自定义了 javax.cache.configuration.Configuration Bean,则将其用于自定义它们。

  • 使用 CacheManager 的引用调用 org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer Bean以进行完全定制。

如果定义了标准的 javax.cache.CacheManager bean,它将自动包装在抽象期望的 org.springframework.cache .CacheManager 实现中。不再对其应用定制。
EhCache 2.x

如果可以在类路径的根目录下找到名为 ehcache.xml 的文件,则使用 EhCache 2.x。 如果找到EhCache 2.x,则使用 spring-boot-starter-cacheStarter”提供的 EhCacheCacheManager 来引导缓存管理器。 也可以提供备用配置文件,如以下示例所示:

spring.cache.ehcache.config=classpath:config/another-config.xml
Hazelcast

Spring Boot对Hazelcast具有常规支持。 如果已经自动配置了 HazelcastInstance,则将其自动包装在 CacheManager 中。

Infinispan

Infinispan没有默认配置文件位置,因此必须明确指定。否则,将使用默认的引导程序。

spring.cache.infinispan.config=infinispan.xml

可以在启动时通过设置 spring.cache.cache-names 属性来创建缓存。 如果定义了自定义 ConfigurationBuilder bean,则将其用于自定义缓存。

Spring Boot对Infinispan的支持仅限于嵌入式模式,并且非常基础。 如果你需要更多选择,则应该使用官方的Infinispan Spring Boot启动器。有关更多详细信息,请参见 Infinispan的文档
Couchbase

如果可以使用 Couchbase Java客户端和 couchbase-spring-cache 实现,并且已配置Couchbase,则将自动配置 CouchbaseCacheManager。 通过设置 spring.cache.cache-names 属性,还可以在启动时创建其他缓存。 这些缓存在自动配置的 Bucket 上运行。你 可以使用定制程序在另一个 Bucket 上创建其他缓存。 假设你在"main" Bucket 上需要两个缓存(cache1cache2),在"another" Bucket 上需要一个自定义的存活时间为2秒的缓存(cache3)。 你可以通过配置创建前两个缓存,如下所示:

spring.cache.cache-names=cache1,cache2

然后,你可以定义一个 @Configuration 类来配置额外的 Bucketcache3 缓存,如下所示:

@Configuration(proxyBeanMethods = false)
public class CouchbaseCacheConfiguration {

    private final Cluster cluster;

    public CouchbaseCacheConfiguration(Cluster cluster) {
        this.cluster = cluster;
    }

    @Bean
    public Bucket anotherBucket() {
        return this.cluster.openBucket("another", "secret");
    }

    @Bean
    public CacheManagerCustomizer<CouchbaseCacheManager> cacheManagerCustomizer() {
        return c -> {
            c.prepareCache("cache3", CacheBuilder.newInstance(anotherBucket())
                    .withExpiration(2));
        };
    }

}

此示例配置重用了通过自动配置创建的 Cluster

Redis

如果 Redis可用并已配置,则 RedisCacheManager 将自动配置。 通过设置 spring.cache.cache-names 属性可以在启动时创建其他缓存, 并且可以使用 spring.cache.redis.* 属性配置缓存默认值。 例如,以下配置创建的 cache1cache2 缓存的 存活时间 为10分钟:

spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=600000
默认情况下,会添加键前缀,这样,如果两个单独的缓存使用相同的键,则Redis不会有重叠的键,也不会返回无效值。 如果你创建自己的 RedisCacheManager,我们强烈建议将此设置保持启用状态。
你可以通过添加自己的 RedisCacheConfiguration @Bean 来完全控制配置。如果你要自定义序列化策略,这可能会很有用。
Caffeine

Caffeine是对Guava缓存的Java 8重写,取代了对Guava的支持。 如果存在Caffeine,则会自动配置 CaffeineCacheManager(由 spring-boot-starter-cacheStarter”提供)。 缓存可以在启动时通过设置 spring.cache.cache-names 属性来创建,并且可以通过以下方式之一自定义(按指示的顺序):

  1. spring.cache.caffeine.spec 定义的缓存规范

  2. 定义了一个 com.github.benmanes.caffeine.cache.CaffeineSpec bean

  3. 定义了一个 com.github.benmanes.caffeine.cache.Caffeine bean

例如:以下配置将创建最大大小为500,存活时间 为10分钟的 cache1cache2 缓存。

spring.cache.cache-names=cache1,cache2
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s

如果定义了 com.github.benmanes.caffeine.cache.CacheLoader Bean,它将自动与 CaffeineCacheManager 关联。 由于 CacheLoader 将与由缓存管理器管理的 所有 缓存相关联,因此必须将其定义为 CacheLoader<Object, Object>。 自动配置将忽略任何其他泛型类型。

Simple

如果找不到其他供应商,则配置使用 ConcurrentHashMap 作为缓存存储区的简单实现。如果你的应用程序中不存在任何缓存库,则这是默认设置。 默认情况下,将根据需要创建缓存,但是你可以通过设置 cache-names 属性来限制可用缓存的列表。 例如,如果只需要 cache1cache2 高速缓存,请按如下所示设置 cache-names 属性:

spring.cache.cache-names=cache1,cache2

如果这样做,并且你的应用程序使用了未列出的缓存,那么当需要该缓存时,它将在运行时失败,但在启动时不会失败。 这与使用未声明的缓存时“实际”缓存供应商的行为类似。

None

当你的配置中存在 @EnableCaching 时,也需要合适的缓存配置。如果你需要在某些环境中完全禁用缓存, 请强制将缓存类型设置为 none 以使用no-op实现,如以下示例所示:

spring.cache.type=none

2.13. 消息

Spring Framework为与消息传递系统集成提供了广泛的支持,从使用 JmsTemplate 简化JMS API到使用完整的基础设施异步接收消息。 Spring AMQP为高级消息队列协议提供了类似的功能集。Spring Boot还为 RabbitTemplate 和RabbitMQ提供了自动配置选项。 Spring WebSocket本身就包含对STOMP消息的支持,而Spring Boot通过启动器和少量的自动配置对此提供了支持。 Spring Boot还支持Apache Kafka。

2.13.1. JMS

javax.jms.ConnectionFactory 接口提供了创建用于与JMS代理进行交互的 javax.jms.Connection 的标准方法。 尽管Spring需要一个 ConnectionFactory 来与JMS一起使用,但是你通常不需要自己直接使用它,而可以依赖于更高级别的消息传递抽象。 (有关详细信息,请参见Spring Framework参考文档的 相关部分。)Spring Boot还会自动配置必要的基础设施,以发送和接收消息。

ActiveMQ支持

ActiveMQ在类路径上可用时,Spring Boot也可以配置 ConnectionFactory。 如果存在broker,则将自动启动和配置嵌入式broker(前提是未通过配置指定代理URL)。

如果你使用 spring-boot-starter-activemq,则将提供连接或嵌入ActiveMQ实例所需的依赖关系, 以及与JMS集成的Spring基础设施。

ActiveMQ配置由 spring.activemq.* 中的外部配置属性控制。 例如,你可以在 application.properties 中声明以下部分:

spring.activemq.broker-url=tcp://192.168.1.210:9876
spring.activemq.user=admin
spring.activemq.password=secret

默认情况下,CachingConnectionFactory 用适当的设置包装native ConnectionFactory,你可以通过 spring.jms.* 中的外部配置属性来控制这些设置:

spring.jms.cache.session-cache-size=5

如果你想使用native池,则可以通过向 org.messaginghub:pooled-jms 添加依赖项并相应地配置 JmsPoolConnectionFactory 来实现,如以下示例所示:

spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=50
有关更多受支持的选项,请参见 ActiveMQProperties。 你还可以注册任意数量的实现 ActiveMQConnectionFactoryCustomizer 的Bean,以进行更高级的自定义。

默认情况下,如果destination尚不存在ActiveMQ会创建,以便根据其提供的名称来解析destinations。

Artemis支持

当Spring Boot检测到 Artemis在类路径中可用时,它可以自动配置 ConnectionFactory。 如果存在broker,则将自动启动和配置嵌入式broker(除非已明确设置mode属性)。 受支持的模式是 embedded(以明确表明需要嵌入式broker,并且如果类路径上不存在该broker,则将发生错误)和 native(使用Netty传输协议连接到broker)。配置后者后,Spring Boot会配置一个 ConnectionFactory, 该工厂将使用默认设置连接到在本地计算机上运行的broker。

如果你使用 spring-boot-starter-artemis,则将提供连接到现有Artemis实例所需的依赖项,以及与JMS集成的Spring基础设施。 将 org.apache.activemq:artemis-jms-server 添加到你的应用程序中可以使你使用嵌入式模式。

Artemis配置由 spring.artemis.* 中的外部配置属性控制。例如,你可以在 application.properties 中声明以下部分:

spring.artemis.mode=native
spring.artemis.host=192.168.1.210
spring.artemis.port=9876
spring.artemis.user=admin
spring.artemis.password=secret

嵌入broker时,可以选择是否要启用持久性并列出应使其可用的destinations。可以将它们指定为以逗号分隔的列表,以使用默认选项创建它们, 或者你可以定义 org.apache.activemq.artemis.jms.server.config.JMSQueueConfigurationorg.apache.activemq.artemis.jms.server.config.TopicConfiguration 类型的bean,分别用于高级队列和主题配置。

默认情况下,CachingConnectionFactory 用适当的设置包装native ConnectionFactory,你可以通过 spring.jms.* 中的外部配置属性来控制这些设置:

spring.jms.cache.session-cache-size=5

如果你想使用native池,则可以通过向 org.messaginghub:pooled-jms 添加依赖项并相应地配置 JmsPoolConnectionFactory 来实现,如以下示例所示:

spring.artemis.pool.enabled=true
spring.artemis.pool.max-connections=50

有关更多受支持的选项,请参见 ArtemisProperties

使用Artemis配置中的 name 属性或通过配置提供的名称,来根据destinations名称解析destinations,不涉及JNDI查找。

使用JNDI ConnectionFactory

如果你正在应用程序服务器中运行应用程序,Spring Boot会尝试使用JNDI来查找JMS ConnectionFactory。 默认情况下,将检查 java:/JmsXAjava:/XAConnectionFactory 位置。 如果需要指定备用位置,则可以使用 spring.jms.jndi-name 属性,如以下示例所示:

spring.jms.jndi-name=java:/MyConnectionFactory
发送消息

Spring的 JmsTemplate 是自动配置的,你可以将其直接自动注入到自己的bean中,如以下示例所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final JmsTemplate jmsTemplate;

    @Autowired
    public MyBean(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }

    // ...

}
JmsMessagingTemplate可以类似的方式注入。 如果定义了 DestinationResolverMessageConverter bean,则将其自动关联到自动配置的 JmsTemplate
接收消息

存在JMS基础设施时,可以使用 @JmsListener 注解任何bean以创建监听器端点。如果未定义 JmsListenerContainerFactory ,则会自动配置一个默认值。如果定义了 DestinationResolverMessageConverter Bean,则将其自动关联到默认工厂。

默认情况下,默认工厂是事务性的。如果你在存在 JtaTransactionManager 的基础设施中运行,则默认情况下它将与侦听器容器关联。 如果不是,则启用 sessionTransacted 标志。在后一种情况下,你可以通过在监听器方法(或其委托)上添加 @Transactional 来将本地数据存储事务与传入消息的处理相关联。这样可以确保本地事务完成后,接收的消息得到确认。这还包括发送已在同一JMS会话上执行的响应消息。

以下组件在 someQueue 目标上创建一个监听器端点:

@Component
public class MyBean {

    @JmsListener(destination = "someQueue")
    public void processMessage(String content) {
        // ...
    }

}
有关更多详细信息,请参见 @EnableJms 的Javadoc

如果你需要创建更多的 JmsListenerContainerFactory 实例,或者想要覆盖默认实例,Spring Boot提供了一个 DefaultJmsListenerContainerFactoryConfigurer ,你可以使用它来初始化具有与自动配置相同设置的 DefaultJmsListenerContainerFactory

例如,以下示例公开了另一个使用特定 MessageConverter 的工厂:

@Configuration(proxyBeanMethods = false)
static class JmsConfiguration {

    @Bean
    public DefaultJmsListenerContainerFactory myFactory(
            DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        configurer.configure(factory, connectionFactory());
        factory.setMessageConverter(myMessageConverter());
        return factory;
    }

}

然后,可以在任何 @JmsListener 注释的方法中使用工厂,如下所示:

@Component
public class MyBean {

    @JmsListener(destination = "someQueue", containerFactory="myFactory")
    public void processMessage(String content) {
        // ...
    }

}

2.13.2. AMQP

Advanced Message Queuing Protocol (AMQP) 是面向消息中间件的与平台无关的有线级别协议。 Spring AMQP项目将Spring的核心概念应用于基于AMQP的消息传递解决方案的开发。 Spring Boot为通过RabbitMQ使用AMQP提供了许多便利,包括 spring-boot-starter-amqpStarter”。

RabbitMQ支持

RabbitMQ是基于AMQP协议的轻型,可靠,可伸缩和便携式消息broker。 Spring使用 RabbitMQ 通过AMQP协议进行通信。

RabbitMQ配置由 spring.rabbitmq.* 中的外部配置属性控制。例如,你可以在 application.properties 中声明以下部分:

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=secret

另外,你可以使用 addresses 属性配置相同的连接:

spring.rabbitmq.addresses=amqp://admin:secret@localhost

如果上下文中存在 ConnectionNameStrategy Bean,它将自动用于命名由自动配置的 ConnectionFactory 创建的连接。 有关更多受支持的选项,请参见 RabbitProperties

有关更多详细信息,请参阅 了解RabbitMQ使用的AMQP协议
发送消息

Spring的 AmqpTemplateAmqpAdmin 是自动配置的,你可以将它们直接自动注入到自己的bean中,如以下示例所示:

import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final AmqpAdmin amqpAdmin;
    private final AmqpTemplate amqpTemplate;

    @Autowired
    public MyBean(AmqpAdmin amqpAdmin, AmqpTemplate amqpTemplate) {
        this.amqpAdmin = amqpAdmin;
        this.amqpTemplate = amqpTemplate;
    }

    // ...

}
RabbitMessagingTemplate可以类似的方式注入。 如果定义了 MessageConverter bean,它将自动关联到自动配置的 AmqpTemplate

如有必要,任何定义为 org.springframework.amqp.core.Queue 的bean都会自动用于在RabbitMQ实例上声明相应的队列。

要重试操作,可以在 AmqpTemplate 上启用重试(例如,在broker连接丢失的情况下):

spring.rabbitmq.template.retry.enabled=true
spring.rabbitmq.template.retry.initial-interval=2s

默认情况下,重试是禁用的。你也可以通过声明 RabbitRetryTemplateCustomizer bean来以编程方式自定义 RetryTemplate

接收消息

存在Rabbit基础设施时,可以使用 @RabbitListener 注解任何bean以创建监听器端点。 如果未定义 RabbitListenerContainerFactory,则会自动配置默认的 SimpleRabbitListenerContainerFactory, 你可以使用 spring.rabbitmq.listener.type 属性切换到直接容器。 如果定义了 MessageConverterMessageRecoverer Bean,它将自动与默认工厂关联。

以下示例组件在 someQueue 队列上创建一个监听器端点:

@Component
public class MyBean {

    @RabbitListener(queues = "someQueue")
    public void processMessage(String content) {
        // ...
    }

}
有关更多详细信息,请参见 @EnableRabbit 的Javadoc

如果你需要创建更多 RabbitListenerContainerFactory 实例,或者想要覆盖默认实例, Spring Boot提供了一个 SimpleRabbitListenerContainerFactoryConfigurerDirectRabbitListenerContainerFactoryConfigurer, 你可以使用它们来初始化 SimpleRabbitListenerContainerFactoryDirectRabbitListenerContainerFactory ,其设置与自动配置所使用的工厂相同。

选择哪种容器都没有关系。这两个bean通过自动配置公开。

例如,以下配置类公开了另一个使用特定 MessageConverter 的工厂:

@Configuration(proxyBeanMethods = false)
static class RabbitConfiguration {

    @Bean
    public SimpleRabbitListenerContainerFactory myFactory(
            SimpleRabbitListenerContainerFactoryConfigurer configurer) {
        SimpleRabbitListenerContainerFactory factory =
                new SimpleRabbitListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        factory.setMessageConverter(myMessageConverter());
        return factory;
    }

}

然后,你可以在任何 @RabbitListener 注释的方法中使用工厂,如下所示:

@Component
public class MyBean {

    @RabbitListener(queues = "someQueue", containerFactory="myFactory")
    public void processMessage(String content) {
        // ...
    }

}

你可以启用重试来处理监听器引发异常的情况。默认情况下,使用 RejectAndDontRequeueRecoverer, 但是你可以定义自己的 MessageRecoverer。当重试耗尽时,消息将被拒绝,如果将broker配置为这样做,则消息将被丢弃或路由到死信交换器。 默认情况下,重试是禁用的。你也可以通过声明 RabbitRetryTemplateCustomizer bean来以编程方式自定义 RetryTemplate

默认情况下,如果禁用了重试,并且监听器抛出异常,则会无限期地重试传递。你可以通过两种方式修改此行为: 将 defaultRequeueRejected 属性设置为 false,以便尝试零次重新传递,或者引发 AmqpRejectAndDontRequeueException 以指示应拒绝该消息。后者是启用重试并达到最大传递尝试次数时使用的机制。

2.13.3. Apache Kafka支持

通过提供 spring-kafka 项目的自动配置来支持 Apache Kafka

Kafka配置由 spring.kafka.* 中的外部配置属性控制。例如,你可以在 application.properties 中声明以下部分:

spring.kafka.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=myGroup
要在启动时创建主题,请添加 NewTopic 类型的Bean。如果该主题已经存在,则将忽略该Bean。

有关更多受支持的选项,请参见 KafkaProperties

发送消息

Spring的 KafkaTemplate 是自动配置的,你可以直接在自己的bean中自动对其进行注入,如以下示例所示:

@Component
public class MyBean {

    private final KafkaTemplate kafkaTemplate;

    @Autowired
    public MyBean(KafkaTemplate kafkaTemplate) {
        this.kafkaTemplate = kafkaTemplate;
    }

    // ...

}
如果定义了 spring.kafka.producer.transaction-id-prefix 属性,则会自动配置 KafkaTransactionManager。 另外,如果定义了 RecordMessageConverter bean,它将自动关联到自动配置的 KafkaTemplate
接收消息

存在Apache Kafka基础设施时,可以使用 @KafkaListener 注释任何bean以创建监听器端点。 如果未定义 KafkaListenerContainerFactory,则会使用 spring.kafka.listener.* 中定义的键自动配置默认值。

以下组件在 someTopic 主题上创建监听器端点:

@Component
public class MyBean {

    @KafkaListener(topics = "someTopic")
    public void processMessage(String content) {
        // ...
    }

}

如果定义了 KafkaTransactionManager bean,它将自动关联到容器工厂。同样,如果定义了 ErrorHandlerAfterRollbackProcessorConsumerAwareRebalanceListener bean,它将自动与默认工厂关联。

根据监听器类型,将 RecordMessageConverterBatchMessageConverter bean与默认工厂关联。 如果对于批处理监听器仅存在一个 RecordMessageConverter bean,则将其包装在 BatchMessageConverter 中。

自定义 ChainedKafkaTransactionManager 必须标记为 @Primary,因为它通常引用自动配置的 KafkaTransactionManager bean。
Kafka流

用于Apache Kafka的Spring提供了一个工厂bean来创建 StreamsBuilder 对象并管理其流的生命周期。 只要 kafka-streams 在类路径上并且通过 @EnableKafkaStreams 注解启用Kafka Streams, Spring Boot就会自动配置所需的 KafkaStreamsConfiguration bean。

启用Kafka Streams意味着必须设置应用程序ID和引导服务器。 可以使用 spring.kafka.streams.application-id 来配置前者,如果未设置,则默认为 spring.application.name。 后者可以全局设置,也可以仅针对流进行覆盖。

使用专用属性可以获得几个附加属性。可以使用 spring.kafka.streams.properties 命名空间设置其他任意Kafka属性。 另请参见Kafka的其他属性

要使用工厂bean,只需将 StreamsBuilder 连接到你的 @Bean 中,如以下示例所示:

@Configuration(proxyBeanMethods = false)
@EnableKafkaStreams
public static class KafkaStreamsExampleConfiguration {

    @Bean
    public KStream<Integer, String> kStream(StreamsBuilder streamsBuilder) {
        KStream<Integer, String> stream = streamsBuilder.stream("ks1In");
        stream.map((k, v) -> new KeyValue<>(k, v.toUpperCase())).to("ks1Out",
                Produced.with(Serdes.Integer(), new JsonSerde<>()));
        return stream;
    }

}

默认情况下,由它创建的 StreamBuilder 对象管理的流将自动启动。你可以使用 spring.kafka.streams.auto-startup 属性来自定义此行为。

Kafka的其他属性

自动配置支持的属性显示在 通用应用程序属性中。 请注意,在大多数情况下,这些属性(hyphenated或camelCase)直接映射到Apache Kafka dotted属性。有关详细信息,请参阅Apache Kafka文档。

这些属性的前几个属性适用于所有组件(生产者,消费者,管理员和流),但如果你希望使用不同的值,则可以在组件级别上指定。 Apache Kafka指定属性的重要性为HIGH,MEDIUM或LOW。Spring Boot自动配置支持所有HIGH重要性属性,一些选定的MEDIUM和LOW属性以及任何没有默认值的属性。

通过 KafkaProperties 类可以直接使用Kafka支持的属性的子集。如果希望使用不直接支持的其他属性来配置生产者或消费者,请使用以下属性:

spring.kafka.properties.prop.one=first
spring.kafka.admin.properties.prop.two=second
spring.kafka.consumer.properties.prop.three=third
spring.kafka.producer.properties.prop.four=fourth
spring.kafka.streams.properties.prop.five=fifth

这将常见的 prop.one Kafka属性设置为 first(适用于生产者,消费者和管理员),prop.two 管理员属性设置为 secondprop.three 消费者属性设置为 thirdprop.four 生产者属性设置为 fourthprop.five 流属性设置为 fifth

你还可以如下配置Spring Kafka JsonDeserializer

spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer
spring.kafka.consumer.properties.spring.json.value.default.type=com.example.Invoice
spring.kafka.consumer.properties.spring.json.trusted.packages=com.example,org.acme

同样,你可以禁用 JsonSerializer 在头部发送类型信息的默认行为:

spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer
spring.kafka.producer.properties.spring.json.add.type.headers=false
以这种方式设置的属性将覆盖Spring Boot显式支持的任何配置项。
使用嵌入式Kafka进行测试

Spring for Apache Kafka提供了一种使用嵌入式Apache Kafka broker测试项目的便捷方法。 要使用此功能,请在 spring-kafka-test 模块中使用 @EmbeddedKafka 注释测试类。 有关更多信息,请参阅Spring for Apache Kafka 参考手册

要使Spring Boot自动配置与上述嵌入式Apache Kafka broker一起使用,你需要将嵌入式broker地址(由 EmbeddedKafkaBroker 填充) 的系统属性重新映射到Apache Kafka的Spring Boot配置属性中。有几种方法可以做到这一点:

  • 提供一个系统属性,以将嵌入式broker地址映射到测试类中的 spring.kafka.bootstrap-servers 中:

static {
    System.setProperty(EmbeddedKafkaBroker.BROKER_LIST_PROPERTY, "spring.kafka.bootstrap-servers");
}
  • @EmbeddedKafka 注解上配置属性名称:

@EmbeddedKafka(topics = "someTopic",
        bootstrapServersProperty = "spring.kafka.bootstrap-servers")
  • 在配置属性中使用占位符:

spring.kafka.bootstrap-servers=${spring.embedded.kafka.brokers}

2.14. 使用 RestTemplate 调用REST服务

如果你需要从应用程序中调用远程REST服务,则可以使用Spring Framework的 RestTemplate类。 由于 RestTemplate 实例在使用前通常需要自定义,因此Spring Boot不提供任何单个自动配置的 RestTemplate bean。 但是,它确实会自动配置 RestTemplateBuilder,可在需要时将其用于创建 RestTemplate 实例。 自动配置的 RestTemplateBuilder 确保将明智的 HttpMessageConverters 应用于 RestTemplate 实例。

以下代码显示了一个典型示例:

@Service
public class MyService {

    private final RestTemplate restTemplate;

    public MyService(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
    }

    public Details someRestCall(String name) {
        return this.restTemplate.getForObject("/{name}/details", Details.class, name);
    }

}
RestTemplateBuilder 包含许多有用的方法,可用于快速配置 RestTemplate。例如:要添加BASIC身份验证支持, 可以使用 builder.basicAuthentication("user", "password").build()

2.14.1. RestTemplate自定义

RestTemplate 自定义有三种主要方法,具体取决于你要应用自定义的范围。

为了使所有自定义项的作用域尽可能狭窄,请注入自动配置的 RestTemplateBuilder,然后根据需要调用其方法。 每个方法调用都返回一个新的 RestTemplateBuilder 实例,因此自定义项仅影响此builder的使用。

要进行应用程序作用域的附加自定义,请使用 RestTemplateCustomizer bean。 所有此类bean都会自动注册到自动配置的 RestTemplateBuilder 中,并应用于使用它构建的任何模板。

以下示例显示了一个定制程序,该定制程序为除 192.168.0.5 之外的所有主机配置使用代理:

@Service
public class MyService {

    private final RestTemplate restTemplate;

    public MyService(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
    }

    public Details someRestCall(String name) {
        return this.restTemplate.getForObject("/{name}/details", Details.class, name);
    }

}

最后,最极端(很少使用)的选项是创建自己的 RestTemplateBuilder bean。 这样做会关闭 RestTemplateBuilder 的自动配置,并阻止使用任何 RestTemplateCustomizer Bean。

2.15. 使用 WebClient 调用REST服务

如果你的类路径中包含Spring WebFlux,则还可以选择使用 WebClient 调用远程REST服务。 与 RestTemplate 相比,此客户端具有更强的功能性,并且是完全响应性的。 你可以在 Spring Framework文档的专用部分中了解有关 WebClient 的更多信息。

Spring Boot为你创建并预配置了 WebClient.Builder。强烈建议将其注入你的组件中,并使用它来创建 WebClient 实例。 Spring Boot将该builder配置为共享HTTP资源,以与服务器相同的方式反映编解码器的设置 (请参阅WebFlux HTTP codecs自动配置),等等。

以下代码显示了一个典型示例:

@Service
public class MyService {

    private final WebClient webClient;

    public MyService(WebClient.Builder webClientBuilder) {
        this.webClient = webClientBuilder.baseUrl("https://example.org").build();
    }

    public Mono<Details> someRestCall(String name) {
        return this.webClient.get().uri("/{name}/details", name)
                        .retrieve().bodyToMono(Details.class);
    }

}

2.15.1. WebClient运行时

Spring Boot将根据应用程序类路径上可用的库自动检测要使用哪个 ClientHttpConnector 来驱动 WebClient。 目前支持Reactor Netty和Jetty RS客户端。

spring-boot-starter-webflux 启动器默认情况下依赖于 io.projectreactor.netty:reactor-netty, 这带来了服务器和客户端的实现。如果选择使用Jetty作为响应式服务器,则应该添加对Jetty响应式HTTP客户端库 org.eclipse.jetty:jetty-reactive-httpclient 的依赖。 对服务器和客户端使用相同的技术具有优势,因为它将自动在客户端和服务器之间共享HTTP资源。

通过提供自定义的 JettyResourceFactoryReactorResourceFactory bean,开发人员可以覆盖Jetty和Reactor Netty的资源配置 — 这将同时应用于客户端和服务器。

如果你希望为客户端覆盖该选项,则可以定义自己的 ClientHttpConnector bean,并完全控制客户端配置。

2.15.2. WebClient自定义

WebClient 自定义有三种主要方法,具体取决于你希望自定义应用的范围。

为了使所有自定义项的作用域尽可能狭窄,请注入自动配置的 WebClient.Builder,然后根据需要调用其方法。 WebClient.Builder 实例是有状态的:构建器上的任何更改都会反映在随后使用它创建的所有客户端中。 如果要使用同一构建器创建多个客户端,则还可以考虑使用 WebClient.Builder other = builder.clone(); 克隆该构建器。

要对所有 WebClient.Builder 实例进行应用程序作用域的附加自定义,可以声明 WebClientCustomizer bean 并在注入点本地更改 WebClient.Builder

最后,你可以回退到原始API并使用 WebClient.create()。在这种情况下,不会应用任何自动配置或 WebClientCustomizer

2.16. 验证

只要JSR-303实现(例如:Hibernate验证器)位于类路径上,就会自动启用Bean验证1.1支持的方法验证功能。 这使bean方法的参数和/或返回值可以使用 javax.validation 约束进行注解。 具有此类注解方法的目标类需要在类型级别使用 @Validated 注解进行注释,以便在其方法中搜索内联约束注解。

例如:以下服务触发第一个参数的验证,确保其大小在8到10之间:

@Service
@Validated
public class MyBean {

    public Archive findByCodeAndAuthor(@Size(min = 8, max = 10) String code,
            Author author) {
        ...
    }

}

2.17. 发送邮件

Spring Framework通过使用 JavaMailSender 接口提供了用于发送电子邮件的简单抽象,Spring Boot为它提供了自动配置以及starter模块。

有关如何使用 JavaMailSender 的详细说明,请参见 参考文档

如果 spring.mail.host 和相关库(由 spring-boot-starter-mail 定义)可用,且不存在默认 JavaMailSender, 则创建一个。可以通过 spring.mail 命名空间中的配置项进一步自定义sender。 有关更多详细信息,请参见 MailProperties

特别是,某些默认超时值是无限的,你可能需要更改此值,以避免线程被无响应的邮件服务器阻塞,如以下示例所示:

spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=3000
spring.mail.properties.mail.smtp.writetimeout=5000

也可以使用来自JNDI的现有 Session 配置 JavaMailSender

spring.mail.jndi-name=mail/Session

设置 jndi-name 时,它优先于所有其他与Session相关的其他设置。

2.18. JTA的分布式事务

通过使用 AtomikosBitronix嵌入式事务管理器, Spring Boot支持跨多个XA资源的分布式JTA事务。部署到合适的Java EE应用程序服务器时,还支持JTA事务。

当检测到JTA环境时,将使用Spring的 JtaTransactionManager 来管理事务。 自动配置的JMS,DataSource和JPA Bean已升级为支持XA事务。 你可以使用标准的Spring习惯用法(例如:@Transactional)来参与分布式事务。 如果你在JTA环境中,并且仍要使用本地事务,则可以将 spring.jta.enabled 属性设置为 false 以禁用JTA自动配置。

2.18.1. 使用Atomikos事务管理器

Atomikos是一种流行的开源事务管理器,可以嵌入到你的Spring Boot应用程序中。 你可以使用 spring-boot-starter-jta-atomikos 启动器引入相应的Atomikos库。 Spring Boot自动配置Atomikos,并确保将适当的 depends-on 设置应用于Spring Bean,以实现正确的启动和关闭顺序。

默认情况下,Atomikos事务日志将写入应用程序主目录(应用程序jar文件所在的目录)中的 transaction-logs 目录。 你可以通过在 application.properties 文件中设置 spring.jta.log-dir 属性来自定义此目录的位置。 以 spring.jta.atomikos.properties 开头的属性也可以用于自定义Atomikos UserTransactionServiceImp。 有关完整的详细信息,请参见 AtomikosProperties Javadoc

为了确保多个事务管理器可以安全地协调同一资源管理器,必须为每个Atomikos实例配置一个唯一的ID。 默认情况下,此ID是运行Atomikos的计算机的IP地址。为确保生产中的唯一性,应为每个应用程序实例将 spring.jta.transaction-manager-id 属性配置为不同的值。

2.18.2. 使用Bitronix事务管理器

Bitronix是流行的开源JTA事务管理器实现。 你可以使用 spring-boot-starter-jta-bitronix 启动器将适当的Bitronix依赖项添加到项目中。 与Atomikos一样,Spring Boot自动配置Bitronix并对你的bean进行后处理,以确保启动和关闭顺序正确。

默认情况下,Bitronix事务日志文件(part1.btmpart2.btm)被写入应用程序主目录中的 transaction-logs 目录。 你可以通过设置 spring.jta.log-dir 属性来自定义此目录的位置。以 spring.jta.bitronix.properties 开头的属性也绑定到 bitronix.tm.Configuration Bean,从而可以进行完全自定义。 有关详细信息,请参见 Bitronix文档

为了确保多个事务管理器可以安全地协调同一资源管理器,必须为每个Bitronix实例配置唯一的ID。 默认情况下,此ID是运行Bitronix的计算机的IP地址。为确保生产中的唯一性,应为每个应用程序实例将 spring.jta.transaction-manager-id 属性配置为不同的值。

2.18.3. 使用Java EE托管事务管理器

如果将Spring Boot应用程序打包为 warear 文件,并将其部署到Java EE应用程序服务器,则可以使用应用程序服务器的内置事务管理器。 Spring Boot通过查看常见的JNDI位置(java:comp/UserTransaction, java:comp/TransactionManager 等)来尝试自动配置事务管理器。 如果使用应用程序服务器提供的事务服务,通常还需要确保所有资源都由服务器管理并通过JNDI公开。 Spring Boot尝试通过在JNDI路径(java:/JmsXAjava:/XAConnectionFactory)中查找 ConnectionFactory 来自动配置JMS, 并且你可以使用 spring.datasource.jndi-name 属性配置你的 DataSource

2.18.4. 混合XA和非XA JMS连接

使用JTA时,主要的JMS ConnectionFactory bean是XA-aware,并参与分布式事务。 在某些情况下,你可能想通过使用非XA ConnectionFactory 处理某些JMS消息。 例如:你的JMS处理逻辑可能需要比XA超时更长的时间。

如果要使用非XA ConnectionFactory,则可以注入 nonXaJmsConnectionFactory bean, 而不是 @Primary jmsConnectionFactory bean。 为了保持一致性,还可使用bean别名 xaJmsConnectionFactory 提供了 jmsConnectionFactory bean。

以下示例显示如何注入 ConnectionFactory 实例:

// Inject the primary (XA aware) ConnectionFactory
@Autowired
private ConnectionFactory defaultConnectionFactory;

// Inject the XA aware ConnectionFactory (uses the alias and injects the same as above)
@Autowired
@Qualifier("xaJmsConnectionFactory")
private ConnectionFactory xaConnectionFactory;

// Inject the non-XA aware ConnectionFactory
@Autowired
@Qualifier("nonXaJmsConnectionFactory")
private ConnectionFactory nonXaConnectionFactory;

2.18.5. 支持替代嵌入式事务管理器

XAConnectionFactoryWrapperXADataSourceWrapper接口可用于支持其他嵌入式事务管理器。 这些接口负责包装 XAConnectionFactoryXADataSource Bean,并将它们作为常规的 ConnectionFactoryDataSource Bean公开,以透明方式注册分布式事务。如果你在 ApplicationContext 中注册了 JtaTransactionManager bean和适当的XA包装bean,则 DataSource 和JMS自动配置使用JTA变体。

BitronixXAConnectionFactoryWrapperBitronixXADataSourceWrapper 提供了有关如何编写XA包装器的良好示例。

2.19. Hazelcast

如果 Hazelcast位于类路径上,并且找到了合适的配置, 则Spring Boot会自动配置一个 HazelcastInstance,你可以将其注入应用程序中。

如果定义 com.hazelcast.config.Config bean,Spring Boot会使用它。 如果你的配置定义了一个实例名称,Spring Boot会尝试查找现有实例,而不是创建一个新实例。

你还可以通过配置指定使用的Hazelcast配置文件,如以下示例所示:

spring.hazelcast.config=classpath:config/my-hazelcast.xml

否则,Spring Boot会尝试从默认位置查找Hazelcast配置: 工作目录中或类路径根目录中的 hazelcast.xml,或相同位置中的 .yaml 副本。 我们还检查是否设置了 hazelcast.config 系统属性。有关更多详细信息,请参见 Hazelcast文档

如果在类路径中存在 hazelcast-client,Spring Boot首先尝试通过检查以下配置选项来创建客户端:

  • com.hazelcast.client.config.ClientConfig bean的存在。

  • spring.hazelcast.config 属性定义的配置文件。

  • hazelcast.client.config 系统属性的存在。

  • 工作目录中或类路径根目录中的 hazelcast-client.xml

  • 工作目录中或类路径根目录中的 hazelcast-client.yaml

Spring Boot还具有对Hazelcast的显式缓存支持。 如果启用了缓存,则 HazelcastInstance 将自动包装在 CacheManager 实现中。

2.20. Quartz调度器

Spring Boot为使用 Quartz scheduler提供了许多便利,包括 spring-boot-starter-quartz “Starter”。如果Quartz可用,则自动配置 Scheduler(通过 SchedulerFactoryBean 抽象)。

以下类型的Bean将自动被拾取并与 Scheduler 关联:

  • JobDetail: 定义一个特定的Job。 JobDetail 实例可以使用JobBuilder API构建。

  • Calendar.

  • Trigger: 定义何时触发特定job。

默认情况下,使用内存中的 JobStore。但是,如果应用程序中有可用的 DataSource bean,并且相应地配置了 spring.quartz.job-store-type 属性,则可以配置基于JDBC的存储,如以下示例所示:

spring.quartz.job-store-type=jdbc

使用JDBC存储时,可以在启动时初始化schema,如以下示例所示:

spring.quartz.jdbc.initialize-schema=always
默认情况下,使用Quartz库随附的标准脚本检测并初始化数据库。这些脚本将删除现有表,并在每次重新启动时删除所有触发器。 还可以通过设置 spring.quartz.jdbc.schema 属性来提供自定义脚本。

要使Quartz使用应用程序的主 DataSource 以外的 DataSource, 请声明一个 DataSource bean,并用 @QuartzDataSource 注解其 @Bean 方法。 这样可以确保 SchedulerFactoryBean 和Schema初始化都使用特定于Quartz的 DataSource

默认情况下,通过配置创建的jobs将不会覆盖从持久性job存储中读取的已注册jobs。要启用覆盖现有作业定义的功能, 请设置 spring.quartz.overwrite-existing-jobs 属性。

可以使用 spring.quartz 属性和 SchedulerFactoryBeanCustomizer bean来定制Quartz Scheduler配置, 这允许以编程方式进行 SchedulerFactoryBean 定制。可以使用 spring.quartz.properties.* 自定义高级Quartz配置属性。

特别是,Executor bean没有与调度程序关联,因为Quartz提供了一种通过 spring.quartz.properties 配置调度程序的方法。如果需要自定义任务执行程序,请考虑实现 SchedulerFactoryBeanCustomizer

Jobs可以定义设置器以注入数据映射属性。常规beans也可以用类似的方式注入,如以下示例所示:

public class SampleJob extends QuartzJobBean {

    private MyService myService;

    private String name;

    // Inject "MyService" bean
    public void setMyService(MyService myService) { ... }

    // Inject the "name" job data property
    public void setName(String name) { ... }

    @Override
    protected void executeInternal(JobExecutionContext context)
            throws JobExecutionException {
        ...
    }

}

2.21. 任务执行和调度

在上下文中没有 Executor bean的情况下,Spring Boot会使用合理的默认值自动配置 ThreadPoolTaskExecutor, 这些默认值可以自动与异步任务执行(@EnableAsync)和Spring MVC异步请求处理相关联。

如果你在上下文中定义一个自定义 Executor,则常规任务执行(即 @EnableAsync)将透明地使用它, 但是Spring MVC支持将不会被配置,因为它需要一个 AsyncTaskExecutor 实现(名为 applicationTaskExecutor)。 根据你的目标安排,你可以将 Executor 更改为 ThreadPoolTaskExecutor, 或者定义一个 ThreadPoolTaskExecutor 和包装自定义 ExecutorAsyncConfigurer

自动配置的 TaskExecutorBuilder 可让你轻松创建实例,以重用默认情况下自动配置的功能。

线程池使用8个核心线程,这些线程可以根据负载增长和收缩。可以使用 spring.task.execution 命名空间微调这些默认设置,如以下示例所示:

spring.task.execution.pool.max-size=16
spring.task.execution.pool.queue-capacity=100
spring.task.execution.pool.keep-alive=10s

这会将线程池更改为使用有界队列,以便在队列已满(100个任务)时,线程池最多增加到16个线程。 池的收缩更加激进,因为当线程空闲10秒(而不是默认情况下的60秒)时,它们将被回收。

如果需要将 ThreadPoolTaskScheduler 与计划的任务执行(@EnableScheduling)关联,也可以对其进行自动配置。 线程池默认使用一个线程,可以使用 spring.task.scheduling 命名空间对这些设置进行微调。

如果需要创建自定义执行器或调度器,则可以在上下文中使用 TaskExecutorBuilder bean和 TaskSchedulerBuilder bean。

2.22. Spring Integration

Spring Boot为使用 Spring Integration提供了许多便利,包括 spring-boot-starter-integrationStarter”。 Spring Integration提供消息传递以及其他传输(例如:HTTP,TCP等)的抽象。 如果Spring Integration在你的类路径中可用,则通过 @EnableIntegration 注解对其进行初始化。

Spring Boot还配置了一些功能,这些功能由其他Spring Integration模块的存在触发。 如果 spring-integration-jmx 也位于类路径上,则消息处理统计信息将通过JMX发布。 如果 spring-integration-jdbc 可用,则可以在启动时创建默认的数据库schema,如以下行所示:

spring.integration.jdbc.initialize-schema=always

有关更多详细信息,请参见 IntegrationAutoConfigurationIntegrationProperties类。

默认情况下,如果存在Micrometer meterRegistry bean,那么Spring Integration指标将由Micrometer管理。 如果你希望使用旧版Spring Integration指标,请将 DefaultMetricsFactory bean添加到应用程序上下文中。

2.23. Spring Session

Spring Boot为各种数据存储提供了 Spring Session自动配置。在构建Servlet Web应用程序时,可以自动配置以下存储:

  • JDBC

  • Redis

  • Hazelcast

  • MongoDB

构建响应式Web应用程序时,可以自动配置以下存储:

  • Redis

  • MongoDB

如果类路径上存在单个Spring Session模块,则Spring Boot会自动使用该存储实现。 如果你有多个实现,则必须选择要用于存储会话的 StoreType。 例如:要将JDBC用作后端存储,可以按以下方式配置应用程序:

spring.session.store-type=jdbc
你可以通过将 store-type 设置为 none 来禁用Spring Session。

每个存储都有特定的附加设置。例如:可以为JDBC存储定制表的名称,如以下示例所示:

spring.session.jdbc.table-name=SESSIONS

要设置会话的超时时间,可以使用 spring.session.timeout 属性。如果未设置该属性,则自动配置将降级到 server.servlet.session.timeout 的值。

2.24. 通过JMX进行监视和管理

Java Management Extensions (JMX) 提供了监视和管理应用程序的标准机制。 Spring Boot将最合适的 MBeanServer 公开为ID为 mbeanServer 的bean。 带有Spring JMX注解(@ManagedResource@ManagedAttribute@ManagedOperation)的任何bean都可以使用它。

如果你的平台提供了标准的 MBeanServer,则Spring Boot将使用该标准,并在必要时默认使用VM MBeanServer。 如果所有操作失败,将创建一个新的 MBeanServer

有关更多详细信息,请参阅 JmxAutoConfiguration类。

2.25. 测试

请移步 这里

2.26. WebSockets

Spring Boot为嵌入式Tomcat,Jetty和Undertow提供了WebSockets自动配置。 如果将war文件部署到独立容器,Spring Boot会假定该容器负责其WebSocket支持的配置。

Spring Framework为MVC Web应用程序提供了 丰富的WebSocket支持, 可以通过 spring-boot-starter-websocket 模块轻松访问。

WebSocket支持也可用于 响应式Web应用程序, 需要在 spring-boot-starter-webflux 旁包含WebSocket API:

<dependency>
    <groupId>javax.websocket</groupId>
    <artifactId>javax.websocket-api</artifactId>
</dependency>

2.27. Web服务

Spring Boot提供了Web服务自动配置,因此你所要做的就是定义 Endpoints

使用 spring-boot-starter-webservices 模块可以轻松访问 Spring Web Services功能

可以分别为你的WSDL和XSD自动创建 SimpleWsdl11DefinitionSimpleXsdSchema Bean。为此请配置其位置,如以下示例所示:

spring.webservices.wsdl-locations=classpath:/wsdl

2.27.1. 使用 WebServiceTemplate 调用Web服务

如果需要从应用程序中调用远程Web服务,则可以使用 WebServiceTemplate类。 由于 WebServiceTemplate 实例在使用前通常需要自定义,因此Spring Boot不提供任何单个自动配置的 WebServiceTemplate bean。 但是,它会自动配置 WebServiceTemplateBuilder,可在需要时将其用于创建 WebServiceTemplate 实例。

以下代码显示了一个典型示例:

@Service
public class MyService {

    private final WebServiceTemplate webServiceTemplate;

    public MyService(WebServiceTemplateBuilder webServiceTemplateBuilder) {
        this.webServiceTemplate = webServiceTemplateBuilder.build();
    }

    public DetailsResp someWsCall(DetailsReq detailsReq) {
         return (DetailsResp) this.webServiceTemplate.marshalSendAndReceive(detailsReq, new SoapActionCallback(ACTION));
    }

}

默认情况下,WebServiceTemplateBuilder 使用类路径上的可用HTTP客户端库来检测合适的基于HTTP的 WebServiceMessageSender。 你还可以像下面那样自定义读取和连接超时:

@Bean
public WebServiceTemplate webServiceTemplate(WebServiceTemplateBuilder builder) {
    return builder.messageSenders(new HttpWebServiceMessageSenderBuilder()
            .setConnectTimeout(5000).setReadTimeout(2000).build()).build();
}

2.28. 创建自己的自动配置

如果你在开发共享库的公司中工作,或者在开源或商业库中工作,则可能需要开发自己的自动配置。自动配置类可以捆绑在外部jar中,并且仍由Spring Boot拾取。

自动配置可以与“starter”相关联,该“starter”提供自动配置代码以及你将使用的典型库。 我们首先介绍构建自己的自动配置所需的知识,然后继续介绍创建自定义启动器所需的典型步骤

有一个 demo项目可以展示如何逐步创建starter。

2.28.1. 了解自动配置的Bean

在后台,自动配置是通过标准 @Configuration 类实现的。其他 @Conditional 注解用于约束何时应应用自动配置。 通常,自动配置类使用 @ConditionalOnClass@ConditionalOnMissingBean 注解。 这样可以确保仅当找到相关的类并且没有声明自己的 @Configuration 时,才应用自动配置。

你可以浏览 spring-boot-autoconfigure的源代码以查看Spring提供的 @Configuration 类(请参阅 META-INF/spring.factories文件)。

2.28.2. 查找自动配置候选人

Spring Boot检查发布的jar中是否存在 META-INF/spring.factories 文件。 该文件应在 EnableAutoConfiguration 键下列出你的配置类,如以下示例所示:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
自动配置 只能 以这种方式加载。 确保在特定的程序包空间中定义它们,并且决不要将它们作为组件扫描的目标。 此外,自动配置类不应启用组件扫描以查找其他组件。应该使用特定的 @Imports 代替。

如果需要按特定顺序应用配置,则可以使用 @AutoConfigureAfter@AutoConfigureBefore注解。 例如:如果你提供特定于Web的配置,则可能需要在 WebMvcAutoConfiguration 之后应用你的类。

如果要排序某些彼此之间不具有任何直接了解的自动配置,则也可以使用 @AutoConfigureOrder。 该注解与常规 @Order 注解具有相同的语义,但为自动配置类提供了专用的顺序。

2.28.3. 条件注解

你几乎总是希望在自动配置类中包含一个或多个 @Conditional 注解。 @ConditionalOnMissingBean 注解是一个常见示例,用于使开发人员在对默认设置不满意的情况下覆盖自动配置。

Spring Boot包含许多 @Conditional 注解,你可以通过标注 @Configuration 类或单个 @Bean 方法在自己的代码中重用它。 这些注解包括:

Class条件

通过 @ConditionalOnClass@ConditionalOnMissingClass 注解,可以根据是否存在特定类来包含 @Configuration 类。 由于注解元数据是通过使用 ASM进行解析的,因此即使该类可能实际上未出现在正在运行的应用程序类路径上, 你也可以使用 value 属性来引用真实的类。如果你更喜欢通过使用 String 值来指定类名称,则也可以使用 name 属性。

这种机制不适用于通常将返回类型作为该条件目标的 @Bean 方法:在方法上的条件应用之前,JVM将加载该类和可能处理的方法引用,如果类不存在,这些引用将失败。

为了处理这种情况,可以使用单独的 @Configuration 类隔离条件,如以下示例所示:

@Configuration(proxyBeanMethods = false)
// Some conditions
public class MyAutoConfiguration {

    // Auto-configured beans

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(EmbeddedAcmeService.class)
    static class EmbeddedConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public EmbeddedAcmeService embeddedAcmeService() { ... }

    }

}
如果在元注解中使用 @ConditionalOnClass@ConditionalOnMissingClass 来组成自己的组合注解, 则在不处理这种情况下,必须使用 name 来引用该类。
Bean条件

@ConditionalOnBean@ConditionalOnMissingBean 注解允许根据是否存在特定bean来包含bean。 你可以使用 value 属性按类型指定bean或使用 name 属性按名称指定bean。 search 属性使你可以限制在搜索bean时应考虑的 ApplicationContext 层次结构。

当放置在 @Bean 方法上时,目标类型默认为该方法的返回类型,如以下示例所示:

@Configuration(proxyBeanMethods = false)
public class MyAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public MyService myService() { ... }

}

在前面的示例中,如果 ApplicationContext 中没有包含 MyService 类型的bean,将创建 myService bean。

你要特别注意添加bean定义的顺序,因为这些条件是根据到目前为止已处理的内容来评估的。 出于这个原因,我们建议在自动配置类上仅使用 @ConditionalOnBean@ConditionalOnMissingBean 注解 (因为可以保证在添加任何用户定义的bean定义后加载它们)。
@ConditionalOnBean@ConditionalOnMissingBean 不会阻止创建 @Configuration 类。 在类级别使用这些条件与使用注解标记每个包含的 @Bean 方法之间的唯一区别是,如果条件不匹配,则前者会阻止将 @Configuration 类注册为bean。
Property条件

@ConditionalOnProperty 注解允许基于Spring Environment 属性包含的配置,使用 prefixname 属性指定应检查的属性。 默认情况下,将匹配存在且不等于 false 的任何属性。你也可以使用 havingValuematchIfMissing 属性来创建更高级的检查。

Resource条件

@ConditionalOnResource 注解仅在存在特定资源时才包含配置。可以使用常规的Spring约定来指定资源, 如以下示例所示:file:/home/user/test.dat

Web应用条件

@ConditionalOnWebApplication@ConditionalOnNotWebApplication 注解允许根据应用程序是否为“Web应用程序”来包含配置。 基于Servlet的Web应用程序是使用Spring WebApplicationContext,定义 session 作用域或具有 ConfigurableWebEnvironment 的任何应用程序。 响应式Web应用程序是使用 ReactiveWebApplicationContext 或具有 ConfigurableReactiveWebEnvironment 的任何应用程序。

SpEL表达式条件

@ConditionalOnExpression 注解允许基于 SpEL表达式的结果来包含配置。

2.28.4. 测试你的自动配置

自动配置可能受许多因素影响:用户配置(@Bean 定义和 Environment 自定义),条件评估(存在特定库)以及其他因素。 具体而言,每个测试都应创建定义良好的 ApplicationContext,以表示这些自定义项的组合。 ApplicationContextRunner 提供了一种实现此目标的好方法。

通常将 ApplicationContextRunner 定义为测试类的字段,以收集基本的通用配置。 下面的示例确保始终调用 UserServiceAutoConfiguration

private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
        .withConfiguration(AutoConfigurations.of(UserServiceAutoConfiguration.class));
如果必须定义多个自动配置,则无需按照与运行应用程序时完全相同的顺序调用它们的声明。

每个测试都可以使用运行器来表示特定的用例。例如:下面的示例调用一个用户配置(UserConfiguration)并检查自动配置是否正确退出。 调用 run 提供了可与 Assert4J 一起使用的回调上下文。

@Test
void defaultServiceBacksOff() {
    this.contextRunner.withUserConfiguration(UserConfiguration.class).run((context) -> {
        assertThat(context).hasSingleBean(UserService.class);
        assertThat(context).getBean("myUserService").isSameAs(context.getBean(UserService.class));
    });
}

@Configuration(proxyBeanMethods = false)
static class UserConfiguration {

    @Bean
    UserService myUserService() {
        return new UserService("mine");
    }

}

也可以轻松自定义 Environment,如以下示例所示:

@Test
void serviceNameCanBeConfigured() {
    this.contextRunner.withPropertyValues("user.name=test123").run((context) -> {
        assertThat(context).hasSingleBean(UserService.class);
        assertThat(context.getBean(UserService.class).getName()).isEqualTo("test123");
    });
}

运行器还可以用于显示 ConditionEvaluationReport。 可以以 INFODEBUG 级别打印报告。以下示例显示如何使用 ConditionEvaluationReportLoggingListener 在自动配置测试中打印报告。

@Test
public void autoConfigTest {
    ConditionEvaluationReportLoggingListener initializer = new ConditionEvaluationReportLoggingListener(
            LogLevel.INFO);
    ApplicationContextRunner contextRunner = new ApplicationContextRunner()
            .withInitializer(initializer).run((context) -> {
                    // Do something...
            });
}
模拟一个Web上下文

如果你需要测试仅在Servlet或Reactive Web应用程序上下文中运行的自动配置,请分别使用 WebApplicationContextRunnerReactiveWebApplicationContextRunner

覆盖类路径

还可以测试在运行时不存在特定的类和/或程序包时发生的情况。 Spring Boot附带有 FilteredClassLoader,运行器可以轻松使用。 在以下示例中,我们断言,如果不存在 UserService,则会自动禁用自动配置:

@Test
void serviceIsIgnoredIfLibraryIsNotPresent() {
    this.contextRunner.withClassLoader(new FilteredClassLoader(UserService.class))
            .run((context) -> assertThat(context).doesNotHaveBean("userService"));
}

2.28.5. 创建自己的Starter

一个库的完整Spring Boot starter可能包含以下组件:

  • autoconfigure 模块:包含自动配置代码。

  • starter 模块:提供对 autoconfigure 模块以及其库的依赖,和通常有用的任何其他依赖项。 简而言之,添加starter应提供开始使用该库所需的一切。

如果不需要将这两个问题分开,则可以将自动配置代码和依赖管理组合在一起。
命名

你应该确保为启动器提供适当的命名空间。即使你使用其他Maven groupId,也不要以 spring-boot 开头模块名称。 将来,我们可能会为你自动配置的内容提供官方支持。

根据经验,你应该在启动器后命名一个组合模块。例如:假设你要为“acme”创建starter, 并命名自动配置模块 acme-spring-boot-autoconfigure 和启动器 acme-spring-boot-starter。 如果只有一个模块将两者结合在一起,则将其命名为 acme-spring-boot-starter

配置键

如果你的starter提供了配置键,请为其使用唯一的命名空间。 特别是,不要将键包含在Spring Boot使用的名称空间中(例如:server, management, spring 等)。 如果使用相同的命名空间,将来我们可能会以破坏模块的方式修改这些命名空间。 根据经验,所有键都必须拥有自己的命名空间(例如:acme)。

通过为每个属性添加字段javadoc来确保文档化配置键,如以下示例所示:

@ConfigurationProperties("acme")
public class AcmeProperties {

    /**
     * Whether to check the location of acme resources.
     */
    private boolean checkLocation = true;

    /**
     * Timeout for establishing a connection to the acme server.
     */
    private Duration loginTimeout = Duration.ofSeconds(3);

    // getters & setters

}
你仅应将简单文本与 @ConfigurationProperties 字段Javadoc一起使用,因为在将它们添加到JSON之前不会对其进行处理。

这是我们内部遵循的一些规则,以确保描述一致:

  • 请勿以“The”或“A”开头描述。

  • 对于 boolean 类型,请以“Whether”或“Enable”开始描述。

  • 对于基于集合的类型,请以“Comma-separated list”开始描述。

  • 使用 java.time.Duration 而不是 long,如果它不为毫秒,请描述默认单位,例如:“If a duration suffix is not specified, seconds will be used”。

  • 除非必须在运行时确定默认值,否则请不要在描述中提供默认值。

确保触发元数据生成, 以便IDE助手也可用于你的键。你可能需要查看生成的元数据(META-INF/spring-configuration-metadata.json), 以确保正确记录了你的键。在兼容的IDE中使用自己的starter也是验证元数据质量的好主意。

autoconfigure 模块

autoconfigure 模块包含开始使用该库所需的所有内容。它还可能包含配置键定义(例如:@ConfigurationProperties) 和可用于进一步自定义组件初始化方式的任何回调接口。

你应该将对库的依赖项标记为optional,以便可以更轻松地在项目中包括 autoconfigure 模块。 如果这样做,则不提供该库,并且默认情况下,Spring Boot会回退。

Spring Boot使用注解处理器来收集元数据文件(META-INF/spring-autoconfigure-metadata.properties)中自动配置的条件。 如果存在该文件,它将用于急切过滤不匹配的自动配置,这将缩短启动时间。建议在包含自动配置的模块中添加以下依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure-processor</artifactId>
    <optional>true</optional>
</dependency>

对于Gradle 4.5及更早版本,应在配置中使用 compileOnly 声明依赖项,如以下示例所示:

dependencies {
    compileOnly "org.springframework.boot:spring-boot-autoconfigure-processor"
}

对于Gradle 4.6和更高版本,应在配置中使用 annotationProcessor 声明依赖项,如以下示例所示:

dependencies {
    annotationProcessor "org.springframework.boot:spring-boot-autoconfigure-processor"
}
starter模块

Starter确实是一个空jar。其唯一目的是提供必要的依赖关系以使用库。你可以将其视为对入门所需。

不要对添加了启动器的项目做任何假设。如果你要自动配置的库通常需要其他启动器,请同时提及它们。 如果可选依赖项的数量很高,则提供一组适当的 默认 依赖项可能会很困难,因此你应该避免包括对于库的典型用法不必要的依赖项。 换句话说,你不应包括可选的依赖项。

无论哪种方式,你的starter都必须直接或间接引用(即如果你的starter依赖于另一个starter,则无需添加它) 核心Spring Boot starter(spring-boot-starter)。如果仅使用你的自定义starter创建项目, 则会通过使用该核心starter来支持Spring Boot的核心功能。

2.29. 接下来要读什么

如果你想了解有关本节中讨论的任何类的更多信息,可以查看 Spring Boot API文档直接浏览源代码

如果你有特定问题,请查看 how-to部分。

如果你对Spring Boot的核心功能感到满意,则可以继续阅读有关 生产就绪功能的信息。

3. Spring Boot Actuator: 生产就绪功能

Spring Boot包含许多其他功能,可帮助你在将应用程序投入生产时监控和管理你的应用程序。 你可以选择使用HTTP端点或JMX管理和监视你的应用程序。审计,健康状况和指标收集也可以自动应用于你的应用程序。

3.1. 启用生产就绪功能

spring-boot-actuator模块提供了Spring Boot生产就绪的所有功能。 启用这些功能的最简单方法是添加 spring-boot-starter-actuator ‘Starter’ 依赖项。

Actuator的定义

执行器是制造术语,是指用于移动或控制某些物体的机械设备。执行器可以通过很小的变化产生大量的运动。

要将执行器添加到基于Maven的项目中,请添加以下 ‘Starter’ 依赖项:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

对于Gradle,请使用以下声明:

dependencies {
    compile("org.springframework.boot:spring-boot-starter-actuator")
}

3.2. 端点

执行器端点使你可以监视应用程序并与之交互。Spring Boot包含许多内置端点,你可以添加自己的端点。例如:health 端点提供基本的应用程序运行状况信息。

每个端点都可以启用或禁用。这控制了是否创建端点以及它的bean是否在应用程序上下文中存在。 为了可以远程访问,端点还必须通过JMX或HTTP公开。大多数应用程序选择HTTP,其中端点的ID和 /actuator 前缀被映射到一个URL。 例如,默认情况下,health 端点映射到 /actuator/health

可以使用以下与技术无关的端点:

ID 描述

auditevents

公开当前应用程序的审计事件信息。需要一个 AuditEventRepository bean。

beans

显示应用程序中所有Spring Beans的完整列表。

caches

公开可用的缓存。

conditions

显示在配置和自动配置类上评估的条件以及它们匹配或不匹配的原因。

configprops

显示所有 @ConfigurationProperties 的整理列表。

env

公开Spring的 ConfigurableEnvironment 中的属性。

flyway

显示已应用的所有Flyway数据库迁移。需要一个或多个 Flyway beans。

health

显示应用程序运行状况信息。

httptrace

显示HTTP跟踪信息(默认情况下,公开最近100个HTTP请求-响应交换)。需要一个 HttpTraceRepository bean。

info

显示任意应用程序信息。

integrationgraph

显示Spring Integration图。依赖于 spring-integration-core

loggers

显示和修改应用程序中日志记录器的配置。

liquibase

显示已应用的所有Liquibase数据库迁移。需要一个或多个 Liquibase bean。

metrics

显示当前应用程序的度量指标信息。

mappings

显示整理的所有 @RequestMapping 路径列表。

scheduledtasks

显示应用程序中的所有计划任务。

sessions

允许从Spring Session支持的会话存储中检索和删除用户会话。需要使用Spring Session的基于Servlet的Web应用程序。

shutdown

使应用程序正常关闭。默认禁用。

threaddump

执行线程转储。

如果你的应用程序是Web应用程序(Spring MVC,Spring WebFlux或Jersey),则可以使用以下附加端点:

ID 描述

heapdump

返回一个 hprof 堆转储文件。

jolokia

通过HTTP公开JMX bean(当Jolokia在类路径上时,不适用于WebFlux)。需要依赖于 jolokia-core

logfile

返回日志文件的内容(如果已设置 logging.file.namelogging.file.path 属性)。支持使用HTTP Range 标头来检索部分日志文件的内容。

prometheus

以Prometheus服务器可以抓取的格式公开指标。需要依赖于 micrometer-registry-prometheus

要了解有关执行器端点及其请求和响应格式的更多信息,请参阅单独的API文档( HTMLPDF)。

3.2.1. 启用端点

默认情况下,除 shutdown 外的所有端点均处于启用状态。要配置端点的启用,请使用其 management.endpoint.<id>.enabled 属性。以下示例启用 shutdown 端点:

management.endpoint.shutdown.enabled=true

如果你希望端点支持选择加入而不是选择退出,请将 management.endpoints.enabled-by-default 属性设置为 false 并使用单个端点的 enabled 属性重新启用。 以下示例仅启用 info 端点并禁用所有其他端点:

management.endpoints.enabled-by-default=false
management.endpoint.info.enabled=true
禁用的端点将从应用程序上下文中完全删除。如果只想更改公开端点的技术,请改用includeexclude 属性

3.2.2. 暴露端点

由于端点可能包含敏感信息,因此应谨慎考虑何时公开它们。下表显示了默认暴露的内置端点:

ID JMX Web

auditevents

Yes

No

beans

Yes

No

caches

Yes

No

conditions

Yes

No

configprops

Yes

No

env

Yes

No

flyway

Yes

No

health

Yes

Yes

heapdump

N/A

No

httptrace

Yes

No

info

Yes

Yes

integrationgraph

Yes

No

jolokia

N/A

No

logfile

N/A

No

loggers

Yes

No

liquibase

Yes

No

metrics

Yes

No

mappings

Yes

No

prometheus

N/A

No

scheduledtasks

Yes

No

sessions

Yes

No

shutdown

Yes

No

threaddump

Yes

No

要更改暴露哪些端点,请使用以下特定于技术的 includeexclude 属性:

属性 默认值

management.endpoints.jmx.exposure.exclude

management.endpoints.jmx.exposure.include

*

management.endpoints.web.exposure.exclude

management.endpoints.web.exposure.include

info, health

include 属性列出了公开的端点的ID。 exclude 属性列出了不应公开的端点的ID。 exclude 属性优先于 include 属性。 includeexclude 属性都可以使用端点ID列表进行配置。

例如,要停止通过JMX公开所有端点,而仅公开 healthinfo 端点,请使用以下属性:

management.endpoints.jmx.exposure.include=health,info

* 可用于选择所有端点。 例如,要通过HTTP公开除 envbean 端点之外的所有端点,请使用以下属性:

management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=env,beans

* 在YAML中具有特殊含义,因此,如果要包括(或排除)所有端点,请确保添加引号,如以下示例所示:

management:
  endpoints:
    web:
      exposure:
        include: "*"
如果你的应用程序是公开的,我们强烈建议你保护端点
如果你想在端点暴露时实现自己的策略,则可以注册 EndpointFilter bean。

3.2.3. 保护HTTP端点

你应该像对待其他任何敏感URL一样,小心保护HTTP端点的安全。 如果存在Spring Security,则默认情况下将使用Spring Security的内容协商策略保护端点的安全。 例如,如果你希望为HTTP端点配置自定义安全性,只允许具有特定角色的用户访问它们, Spring Boot提供了一些方便的 RequestMatcher 对象,可以将它们与Spring Security结合使用。

典型的Spring Security配置可能类似于以下示例:

@Configuration(proxyBeanMethods = false)
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests((requests) ->
                requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
        http.httpBasic();
    }
}

前面的示例使用 EndpointRequest.toAnyEndpoint() 将请求匹配到任何端点,然后确保所有端点具有 ENDPOINT_ADMIN 角色才可访问。 EndpointRequest 还提供了其他几种匹配器方法。有关详细信息,请参见API文档( HTMLPDF)。

如果将应用程序部署在防火墙后面,则可能希望无需进行身份验证即可访问所有执行器端点。 你可以通过更改 management.endpoints.web.exposure.include 属性来做到这一点,如下所示:

application.properties
management.endpoints.web.exposure.include=*

此外,如果存在Spring Security,则需要添加自定义安全配置,该配置允许未经身份验证的端点访问,如以下示例所示:

@Configuration(proxyBeanMethods = false)
public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests((requests) ->
            requests.anyRequest().permitAll());
    }
}

3.2.4. 配置端点

端点自动缓存不带任何参数的读取操作的响应。要配置端点缓存响应的时间,请使用其 cache.time-to-live 属性。 以下示例将 beans 端点的缓存的生存时间设置为10秒:

application.properties
management.endpoint.beans.cache.time-to-live=10s
前缀 management.endpoint.<name> 用于唯一标识正在配置的端点。
发出经过身份验证的HTTP请求时,将 Principal 视为端点的输入,因此不会缓存响应。

3.2.5. 用于执行器Web端点的超媒体

添加了“发现页面”,其中包含指向所有端点的链接。默认情况下,在 /actuator 上提供“发现页面”。

配置自定义管理上下文路径后,“发现页面”会自动从 /actuator 移至管理上下文的根目录。例如,如果管理上下文路径为 /management,则可以从 /management 访问发现页面。当管理上下文路径设置为 / 时,将禁用发现页面,以防止与其他映射发生冲突的可能性。

3.2.6. CORS支持

跨域资源共享 (CORS) 是 W3C 规范,使你可以灵活地指定授权哪种类型的跨域请求。 如果你使用Spring MVC或Spring WebFlux,则可以将Actuator的Web端点配置为支持这种情况。

默认情况下,CORS支持是禁用的,并且仅在设置了 management.endpoints.web.cors.allowed-origins 属性后才启用。 以下配置允许来自 example.com 域的 GETPOST 调用:

management.endpoints.web.cors.allowed-origins=https://example.com
management.endpoints.web.cors.allowed-methods=GET,POST
有关选项的完整列表,请参见 CorsEndpointProperties

3.2.7. 实现自定义端点

如果添加带 @Endpoint 注解的 @Bean,则带 @ReadOperation@WriteOperation@DeleteOperation 注解的任何方法都将通过JMX以及Web应用程序通过HTTP自动公开。 可以使用Jersey,Spring MVC或Spring WebFlux通过HTTP公开端点。如果同时提供Jersey和Spring MVC,将使用Spring MVC。

你也可以使用 @JmxEndpoint@WebEndpoint 编写特定于技术的端点。这些端点仅限于各自的技术。例如,@WebEndpoint 仅通过HTTP公开,而不通过JMX公开。

你可以使用 @EndpointWebExtension@EndpointJmxExtension 编写特定于技术的扩展。这些注解使你可以提供特定于技术的操作来扩展现有端点。

最后,如果你需要访问特定于Web框架的功能,则可以实现Servlet或Spring @Controller@RestController 端点,但代价是它们在JMX上不可用,或者在使用其他web框架时不可用。

接收输入

端点上的操作通过其参数接收输入。通过网络公开时,这些参数的值取自URL的查询参数和JSON请求正文。 通过JMX公开时,参数将映射到MBean操作的参数。默认情况下,参数是必需的。 可以通过使用 @org.springframework.lang.Nullable 对其进行注释来使它们成为可选的。

JSON请求正文中的每个根属性都可以映射到端点的参数。考虑以下JSON请求正文:

{
    "name": "test",
    "counter": 42
}

这可用于调用采用 String nameint counter 参数的写操作。

由于端点与技术无关,因此只能在方法签名中指定简单类型。特别是不支持使用定义 namecounter 属性的自定义类型声明单个参数。
为了使输入映射到操作方法的参数,实现端点的Java代码应使用 -parameters 进行编译, 而实现端点的Kotlin代码应使用 -java-parameters 进行编译。如果你使用的是Spring Boot的Gradle插件, 或者使用的是Maven和 spring-boot-starter-parent,则此操作会自动发生。
输入类型转换

如有必要,传递给端点操作方法的参数会自动转换为所需的类型。 在调用操作方法之前,使用 ApplicationConversionService 实例以及任何具有 @EndpointConverter 限定的 ConverterGenericConverter Bean,将通过JMX或HTTP请求接收的输入转换为所需的类型。

自定义Web端点

@Endpoint@WebEndpoint@EndpointWebExtension 上的操作会使用Jersey,Spring MVC或Spring WebFlux通过HTTP自动公开。如果同时提供Jersey和Spring MVC,将使用Spring MVC。

Web端点请求谓词

对于在暴露于Web的端点上的每个操作,都会自动生成一个请求谓词。

路径

谓词的路径由端点的ID和暴露于Web的端点的基本路径确定。默认的基本路径是 /actuator。 例如:具有 sessions ID的端点将使用 /actuator/sessions 作为其谓词的路径。

通过使用 @Selector 注解操作方法的一个或多个参数,可以进一步自定义路径。这样的参数作为路径变量添加到路径谓词。 调用端点操作时,变量的值将传递到操作方法中。如果要捕获所有剩余的路径元素,可以将 @Selector(Match=ALL_REMAINING) 添加到最后一个参数,并将其设置为与 String[] 转换兼容的类型。

HTTP方法

谓词的HTTP方法由操作类型决定,如下表所示:

操作

HTTP方法

@ReadOperation

GET

@WriteOperation

POST

@DeleteOperation

DELETE

消费

对于使用请求体的 @WriteOperation (HTTP POST),谓词的消费类型为 application/vnd.spring-boot.actuator.v2+json, application/json。对于所有其他操作,消费类型为空。

生产

谓词的生产类型可以通过 @DeleteOperation@ReadOperation@WriteOperation 注解的 produces 属性来确定。 该属性是可选的。如果未使用,则会自动确定生产类型。

如果操作方法返回 voidVoid,则生产类型为空。如果操作方法返回 org.springframework.core.io.Resource, 则生产类型为 application/octet-stream。对于所有其他操作,生产类型为 application/vnd.spring-boot.actuator.v2+json, application/json

Web端点响应状态

端点操作的默认响应状态取决于操作类型(读,写或删除)以及该操作返回的内容(如果有)。

@ReadOperation 返回一个值,响应状态将为 200 (OK)。如果未返回值,则响应状态将为 404 (Not Found)。

如果 @WriteOperation@DeleteOperation 返回一个值,则响应状态将为 200 (OK)。如果未返回值,则响应状态将为 204 (No Content)。

如果在没有必需参数或无法将参数转换为必需类型的参数的情况下调用操作,则不会调用该操作方法,并且响应状态将为 400 (Bad Request)。

Web端点范围请求

HTTP Range请求可用于请求HTTP资源的一部分。使用Spring MVC或Spring Web Flux时,返回 org.springframework.core.io.Resource 的操作会自动支持范围请求。

使用Jersey时,范围请求不受支持。
Web端点安全

Web端点或Web特定端点扩展上的操作可以接收当前的 java.security.Principalorg.springframework.boot.actuate.endpoint.SecurityContext 作为方法参数。 前者通常与 @Nullable 结合使用,以为经过身份验证和未经身份验证的用户提供不同的行为。 后者通常用于使用其 isUserInRole(String) 方法执行授权检查。

Servlet端点

通过实现带有 @ServletEndpoint 注解的类(也可以实现 Supplier<EndpointServlet>),可以将Servlet公开为端点。 Servlet端点提供了与Servlet容器更深层次的集成,但以牺牲可移植性为代价。它们用于将现有Servlet公开为端点。 对于新的端点,尽可能使用 @Endpoint@WebEndpoint 注解。

控制器端点

@ControllerEndpoint@RestControllerEndpoint 可用于实现仅由Spring MVC或Spring WebFlux公开的端点。 使用Spring MVC和Spring WebFlux的标准注解(例如: @RequestMapping@GetMapping )映射方法,并将端点的ID用作路径的前缀。 控制器端点提供了与Spring Web框架更深层次的集成,但以牺牲可移植性为代价。尽可能使用 @Endpoint@WebEndpoint 注解。

3.2.8. 健康信息

你可以使用运行状况信息来检查正在运行的应用程序的状态。监视软件通常使用它在生产系统出现故障时向某人发出警报。 health 端点公开的信息取决于 management.endpoint.health.show-detailsmanagement.endpoint.health.show-components 属性,可以使用以下值之一配置属性:

名称

描述

never

详细信息永远不会显示。

when-authorized

详细信息仅显示给授权用户。可以使用 management.endpoint.health.roles 配置授权角色。

always

向所有用户显示详细信息。

默认值为 never。当用户担任端点的一个或多个角色时,该用户被视为已授权。如果端点没有配置的角色(默认值), 则所有通过身份验证的用户均被视为已授权。可以使用 management.endpoint.health.roles 属性配置角色。

如果你已保护应用程序安全并希望使用 always,则安全配置必须允许经过身份验证的用户和未经身份验证的用户都可以访问运行状况端点。

运行状况信息是从 HealthContributorRegistry 的内容(默认情况下,在 ApplicationContext 中定义的所有 HealthContributor 实例)中收集的。 Spring Boot包括许多自动配置的 HealthContributor,你也可以编写自己的 HealthContributor

HealthContributor 可以是 HealthIndicatorCompositeHealthContributorHealthIndicator 提供实际的健康信息,包括 StatusCompositeHealthContributor 提供了其他 HealthContributor 的组合。所有贡献者合起来形成一个树形结构来代表整个系统的健康状况。

默认情况下,最终的系统运行状况是由 StatusAggregator 派生的,StatusAggregator 根据状态的有序列表对每个 HealthIndicator 的状态进行排序。 排序列表中的第一个状态用作整体健康状态。如果没有 HealthIndicator 返回 StatusAggregator 已知的状态,则使用 UNKNOWN 状态。

HealthContributorRegistry 可用于在运行时注册和注销健康指标。
自动配置的HealthIndicators

适当时,Spring Boot会自动配置以下 HealthIndicators

名称 描述

CassandraHealthIndicator

检查Cassandra数据库是否已启动。

CouchbaseHealthIndicator

检查Couchbase集群是否已启动。

DiskSpaceHealthIndicator

检查磁盘空间不足。

ElasticSearchRestHealthContributorAutoConfiguration

检查Elasticsearch集群是否已启动。

HazelcastHealthIndicator

检查Hazelcast服务器是否已启动。

InfluxDbHealthIndicator

检查InfluxDB服务器是否已启动。

JmsHealthIndicator

检查JMS代理是否启动。

LdapHealthIndicator

检查LDAP服务器是否已启动。

MailHealthIndicator

检查邮件服务器是否已启动。

MongoHealthIndicator

检查Mongo数据库是否已启动。

Neo4jHealthIndicator

检查Neo4j数据库是否已启动。

PingHealthIndicator

始终以 UP 响应。

RabbitHealthIndicator

检查Rabbit服务器是否已启动。

RedisHealthIndicator

检查Redis服务器是否启动。

SolrHealthIndicator

检查Solr服务器是否已启动。

你可以通过设置 management.health.defaults.enabled 属性来禁用它们。
编写自定义健康指标

为了提供自定义的健康信息,你可以注册实现 HealthIndicator接口的Spring bean。 你需要提供 health() 方法的实现并返回 Health 响应。Health 响应应包括状态,并且可以选择包括要显示的其他详细信息。 以下代码显示了示例 HealthIndicator 实现:

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyHealthIndicator implements HealthIndicator {
    @Override
    public Health health() {
        int errorCode = check(); // perform some specific health check
        if (errorCode != 0) {
            return Health.down().withDetail("Error Code", errorCode).build();
        }
        return Health.up().build();
    }
}
给定 HealthIndicator 的标识符是不带有 HealthIndicator 后缀(如果存在)的bean的名称。在前面的示例中,健康信息在名为 my 的条目中可用。

除了Spring Boot的预定义 Status类型外, Health 还可以返回代表新系统状态的自定义 Status。 在这种情况下,还需要提供 StatusAggregator接口的自定义实现, 或者必须使用 management.endpoint.health.status.order 配置属性来配置默认实现。

例如,假设在你的 HealthIndicator 实现之一中使用了代码为 FATAL 的新 Status。要配置严重性顺序,请将以下属性添加到你的应用程序属性中:

management.endpoint.health.status.order=fatal,down,out-of-service,unknown,up

响应中的HTTP状态码反映了总体健康状态(例如:UP 映射为200,而 OUT_OF_SERVICEDOWN 映射为503)。 如果通过HTTP访问health端点,则可能还需要注册自定义状态映射。例如,以下属性将 FATAL 映射到503 (service unavailable):

management.endpoint.health.status.http-mapping.fatal=503
如果需要更多控制,则可以定义自己的 HttpCodeStatusMapper bean。

下表显示了内置状态的默认HTTP状态映射:

状态 映射

DOWN

SERVICE_UNAVAILABLE (503)

OUT_OF_SERVICE

SERVICE_UNAVAILABLE (503)

UP

默认情况下没有映射,因此http状态为200

UNKNOWN

默认情况下没有映射,因此http状态为200

Reactive健康指标

对于诸如使用Spring WebFlux的响应式应用程序,ReactiveHealthContributor 提供了一个非阻塞契约来获取应用程序的运行状况。 与传统的 HealthContributor 相似,健康信息是从 ReactiveHealthContributorRegistry (默认情况下,在 ApplicationContext 中定义的所有 HealthContributorReactiveHealthContributor实例)的内容中收集的。 不检查reactive API的常规 HealthContributor 在弹性调度器上执行。

在响应式应用程序中,ReactiveHealthContributorRegistry 可用于在运行时注册和注销健康指标。

为了从响应式API提供自定义健康信息,你可以注册实现 ReactiveHealthIndicator 接口的Spring bean。以下代码显示了示例 ReactiveHealthIndicator 实现:

@Component
public class MyReactiveHealthIndicator implements ReactiveHealthIndicator {
    @Override
    public Mono<Health> health() {
        return doHealthCheck() //perform some specific health check that returns a Mono<Health>
            .onErrorResume(ex -> Mono.just(new Health.Builder().down(ex).build()));
    }
}
要自动处理错误,请考虑继承自 AbstractReactiveHealthIndicator
自动配置的ReactiveHealthIndicators

适当时,Spring Boot会自动配置以下 ReactiveHealthIndicators

名称 描述

CassandraReactiveHealthIndicator

检查Cassandra数据库是否已启动。

CouchbaseReactiveHealthIndicator

检查Couchbase集群是否已启动。

MongoReactiveHealthIndicator

检查Mongo数据库是否已启动。

RedisReactiveHealthIndicator

检查Redis服务器是否启动。

如有必要,可用reactive指示器代替常规指示器。另外,任何未明确处理的 HealthIndicator 都会自动包装。
健康组

有时候,将健康指标分为不同的组很有用。例如,如果将应用程序部署到Kubernetes,则可能需要一组不同的运行状况指示器来进行 “liveness” 和 “readiness” 探针。

要创建运行状况指示器组,可以使用 management.endpoint.health.group.<name> 属性, 并指定要 includeexclude 的运行状况指示器ID的列表。例如,要创建仅包含数据库指示符的组,可以定义以下内容:

management.endpoint.health.group.custom.include=db

然后,你可以通过单击 http://localhost:8080/actuator/health/custom 来检查结果。

默认情况下,组将继承与系统运行状况相同的 StatusAggregatorHttpCodeStatusMapper 设置, 但是,这些设置也可以基于每个组进行定义。如果需要,也可以覆盖 show-detailsrole 属性:

management.endpoint.health.group.custom.show-details=when-authorized
management.endpoint.health.group.custom.roles=admin
management.endpoint.health.group.custom.status.order=fatal,up
management.endpoint.health.group.custom.status.http-mapping.fatal=500
如果需要注册自定义 StatusAggregatorHttpCodeStatusMapper Bean以便与该组一起使用,则可以使用 @Qualifier("groupname")

3.2.9. 应用信息

应用程序信息公开了从 ApplicationContext 中定义的所有 InfoContributor Bean收集的各种信息。Spring Boot包含许多自动配置的 InfoContributor Bean,你可以编写自己的bean。

自动配置的InfoContributors

适当时,Spring Boot会自动配置以下 InfoContributor Bean:

名称 描述

EnvironmentInfoContributor

info 键下公开 Environment 中的任何键。

GitInfoContributor

如果 git.properties 文件可用,则公开git信息。

BuildInfoContributor

如果 META-INF/build-info.properties 文件可用,则公开构建信息。

通过设置 management.info.defaults.enabled 属性,可以全部禁用它们。
自定义应用信息

你可以通过设置 info.* Spring属性来自定义 info 端点公开的数据。 info 键下的所有 Environment 属性将自动显示。例如,你可以将以下设置添加到 application.properties 文件:

info.app.encoding=UTF-8
info.app.java.source=1.8
info.app.java.target=1.8

除了对这些值进行硬编码之外,你还可以 在构建时展开信息属性

假设你使用Maven,则可以按如下所示重写前面的示例:

info.app.encoding=@project.build.sourceEncoding@
info.app.java.source=@java.version@
info.app.java.target=@java.version@
Git提交信息

info 端点的另一个有用的功能是它能够在项目构建时发布有关 git 源代码存储库状态的信息。如果有 GitProperties Bean, 则将公开 git.branchgit.commit.idgit.commit.time 属性。

如果 git.properties 文件在类路径的根目录下可用,则会自动配置 GitProperties bean。有关更多详细信息,请参见 生成git信息

如果要显示完整的git信息(即 git.properties 的完整内容),请使用 management.info.git.mode 属性,如下所示:

management.info.git.mode=full
构建信息

如果有 BuildProperties Bean,则 info 端点也可以发布有关你的构建的信息。如果在类路径中有 META-INF/build-info.properties 文件,则会发生这种情况。

Maven和Gradle插件都可以生成该文件。有关更多详细信息,请参见 生成构建信息
编写自定义InfoContributors

为了提供自定义的应用程序信息,你可以注册实现 InfoContributor接口的Spring bean。

以下示例使用单个值提供 example 条目:

import java.util.Collections;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
@Component
public class ExampleInfoContributor implements InfoContributor {
    @Override
    public void contribute(Info.Builder builder) {
        builder.withDetail("example",
                Collections.singletonMap("key", "value"));
    }
}

如果请求 info 端点,则应该看到包含以下附加条目的响应:

{
    "example": {
        "key" : "value"
    }
}

3.3. 通过HTTP进行监视和管理

如果你正在开发Web应用程序,则Spring Boot Actuator会自动配置所有启用的端点以通过HTTP公开。 默认约定是使用带有 /actuator 前缀的端点的ID作为URL路径。例如:health 公开为 /actuator/health

Spring MVC,Spring WebFlux和Jersey本身支持Actuator。如果同时提供Jersey和Spring MVC,将使用Spring MVC。

3.3.1. 自定义管理端点路径

有时,自定义管理端点的前缀很有用。例如,你的应用程序可能已经将 /actuator 用于其他目的。你可以使用 management.endpoints.web.base-path 属性更改管理端点的前缀,如以下示例所示:

management.endpoints.web.base-path=/manage

前面的 application.properties 示例将端点从 /actuator/{id} 更改为 /manage/{id}(例如: /manage/info)。

除非管理端口已配置为使用其他HTTP端口公开端点, 否则 management.endpoints.web.base-path 是相对于 server.servlet.context-path 的。 如果配置了 management.server.port,则 management.endpoints.web.base-path 相对于 management.server.servlet.context-path

如果要将端点映射到其他路径,则可以使用 management.endpoints.web.path-mapping 属性。

以下示例将 /actuator/health 重新映射到 /healthcheck

application.properties
management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=healthcheck

3.3.2. 自定义管理服务器端口

对于基于云的部署,通过使用默认的HTTP端口公开管理端点是明智的选择。但是,如果你的应用程序在自己的数据中心内运行,则你可能更喜欢使用其他HTTP端口公开端点。

你可以设置 management.server.port 属性以更改HTTP端口,如以下示例所示:

management.server.port=8081
在Cloud Foundry上,默认情况下,应用程序仅在端口8080上接收HTTP和TCP路由请求。 如果要在Cloud Foundry上使用自定义管理端口,则需要明确设置应用程序的路由,以将流量转发到自定义端口。

3.3.3. 配置特定于管理的SSL

当配置为使用定制端口时,还可以通过使用各种 management.server.ssl.* 属性将管理服务器配置为其自身的SSL。 例如,这样做可以使管理服务器通过HTTP可用,而主应用程序使用HTTPS,如以下属性设置所示:

server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:store.jks
server.ssl.key-password=secret
management.server.port=8080
management.server.ssl.enabled=false

或者,主服务器和管理服务器都可以使用SSL,但具有不同的密钥库,如下所示:

server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:main.jks
server.ssl.key-password=secret
management.server.port=8080
management.server.ssl.enabled=true
management.server.ssl.key-store=classpath:management.jks
management.server.ssl.key-password=secret

3.3.4. 自定义管理服务器地址

你可以通过设置 management.server.address 属性来自定义管理端点可用的地址。如果你只想在内部或面向操作的网络上侦听或仅侦听来自本地主机的连接,则这样做很有用。

仅当端口与主服务器端口不同时,你才能在其他地址上侦听。

以下示例 application.properties 不允许远程管理连接:

management.server.port=8081
management.server.address=127.0.0.1

3.3.5. 禁用HTTP端点

如果你不想通过HTTP公开端点,则可以将管理端口设置为 -1,如以下示例所示:

management.server.port=-1

也可以使用 management.endpoints.web.exposure.exclude 属性来实现,如以下示例所示:

management.endpoints.web.exposure.exclude=*

3.4. 通过JMX进行监视和管理

Java管理扩展(JMX)提供了监视和管理应用程序的标准机制。默认情况下,此功能未启用, 可以通过将配置属性 spring.jmx.enabled 设置为 true 来启用。默认情况下,Spring Boot将管理端点公开为 org.springframework.boot 域下的JMX MBean。

3.4.1. 自定义MBean名称

MBean的名称通常是根据端点的ID生成的。例如,health 端点显示为 org.springframework.boot:type=Endpoint,name=Health

如果你的应用程序包含多个Spring ApplicationContext,则可能会发现名称冲突。要解决此问题,可以将 spring.jmx.unique-names 属性设置为 true,以便MBean名称始终是唯一的。

你还可以自定义暴露端点的JMX域。以下设置在 application.properties 中显示了如何这样做:

spring.jmx.unique-names=true
management.endpoints.jmx.domain=com.example.myapp

3.4.2. 禁用JMX端点

如果你不想通过JMX公开端点,则可以将 management.endpoints.jmx.exposure.exclude 属性设置为 *,如以下示例所示:

management.endpoints.jmx.exposure.exclude=*

3.4.3. 通过HTTP将Jolokia用于JMX

Jolokia是一个JMX-HTTP桥,它提供了另一种访问JMX bean的方法。要使用Jolokia,请包括对 org.jolokia:jolokia-core 的依赖。例如,使用Maven,你将添加以下依赖项:

<dependency>
    <groupId>org.jolokia</groupId>
    <artifactId>jolokia-core</artifactId>
</dependency>

然后可以通过将 jolokia* 添加到 management.endpoints.web.exposure.include 属性来暴露Jolokia端点。 然后,你可以在管理HTTP服务器上使用 /actuator/jolokia 访问它。

自定义Jolokia

Jolokia具有许多设置,这些设置通常是通过设置servlet参数进行配置的。 通过Spring Boot,你可以使用 application.properties 文件。为此,请在参数前面加上 management.endpoint.jolokia.config。 如以下示例所示:

management.endpoint.jolokia.config.debug=true
禁用Jolokia

如果你使用Jolokia但不希望Spring Boot对其进行配置,则可将 management.endpoint.jolokia.enabled 属性设置为 false,如下所示:

management.endpoint.jolokia.enabled=false

3.5. 日志记录器

Spring Boot Actuator可以在运行时查看和配置应用程序的日志级别。 你可以查看整个列表或单个记录器的配置,该配置由显式配置的日志记录级别以及日志记录框架为其指定的有效日志记录级别组成。 这些级别可以是以下之一:

  • TRACE

  • DEBUG

  • INFO

  • WARN

  • ERROR

  • FATAL

  • OFF

  • null

null 表示没有显式配置。

3.5.1. 配置记录器

要配置给定的记录器,请将部分实体 POST 到资源的URI中,如以下示例所示:

{
    "configuredLevel": "DEBUG"
}
要“重置”日志记录器的特定级别(并使用默认配置),可以传递一个 null 值作为 configuredLevel

3.6. 指标

Spring Boot Actuator为 Micrometer提供依赖项管理和自动配置,Micrometer是一种支持多种监视系统的应用程序指标外观,包括:

要了解有关Micrometer功能的更多信息,请参阅其 参考文档,特别是 概念部分

3.6.1. 入门

Spring Boot自动配置组合的 MeterRegistry,并为其在类路径上找到的每个受支持的实现向组合添加注册表。在运行时类路径中具有对 micrometer-registry-{system} 的依赖足以使Spring Boot配置注册表。

大多数注册表具有共同的特征。例如,即使Micrometer注册表实现位于类路径中,你也可以禁用特定的注册表。例如,禁用Datadog:

management.metrics.export.datadog.enabled=false

Spring Boot还会将任何自动配置的注册表添加到Metrics类的全局静态复合注册表中,除非你明确告诉它不要这么做:

management.metrics.use-global-registry=false

你可以注册任意数量的 MeterRegistryCustomizer Bean来进一步配置注册表,例如在向注册表注册任何度量器之前应用通用标签:

@Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
    return registry -> registry.config().commonTags("region", "us-east-1");
}

你可以应用自定义到特定的注册表实现更具体的泛型类型:

@Bean
MeterRegistryCustomizer<GraphiteMeterRegistry> graphiteMetricsNamingConvention() {
    return registry -> registry.config().namingConvention(MY_CUSTOM_CONVENTION);
}

完成该设置后,你可以将 MeterRegistry 注入组件并注册指标:

@Component
public class SampleBean {

    private final Counter counter;

    public SampleBean(MeterRegistry registry) {
        this.counter = registry.counter("received.messages");
    }

    public void handleMessage(String message) {
        this.counter.increment();
        // handle message implementation
    }

}

Spring Boot还配置了内置工具(即 MeterBinder 实现),你可以通过配置或专用注解标记来控制它们。

3.6.2. 支持的监控系统

AppOptics

默认情况下,AppOptics注册表会定期将指标推送到 https://api.appoptics.com/v1/measurements。 要将指标导出到SaaS AppOptics,必须提供你的API令牌:

management.metrics.export.appoptics.api-token=YOUR_TOKEN
Atlas

默认情况下,度量标准将导出到在本地计算机上运行的 Atlas。 可以使用以下命令提供要使用的 Atlas服务器的位置:

management.metrics.export.atlas.uri=https://atlas.example.com:7101/api/v1/publish
Datadog

Datadog注册表会定期将指标推送到 datadoghq。 要将指标导出到 Datadog,必须提供你的API密钥:

management.metrics.export.datadog.api-key=YOUR_KEY

你还可以更改将度量标准发送到Datadog的时间间隔:

management.metrics.export.datadog.step=30s
Dynatrace

Dynatrace注册表会定期将指标推送到配置的URI。 要将指标导出到 Dynatrace,必须提供你的API令牌,设备ID和URI:

management.metrics.export.dynatrace.api-token=YOUR_TOKEN
management.metrics.export.dynatrace.device-id=YOUR_DEVICE_ID
management.metrics.export.dynatrace.uri=YOUR_URI

你还可以更改将度量标准发送到Dynatrace的时间间隔:

management.metrics.export.dynatrace.step=30s
Elastic

默认情况下,指标会导出到在本地计算机上运行的 Elastic。 可以使用以下属性提供要使用的Elastic服务器的位置:

management.metrics.export.elastic.host=https://elastic.example.com:8086
Ganglia

默认情况下,指标将导出到在本地计算机上运行的 Ganglia。 可以使用以下命令提供要使用的 Ganglia服务器主机和端口:

management.metrics.export.ganglia.host=ganglia.example.com
management.metrics.export.ganglia.port=9649
Graphite

默认情况下,指标会导出到本地计算机上运行的 Graphite。 可以使用以下方式提供要使用的 Graphite服务器主机和端口:

management.metrics.export.graphite.host=graphite.example.com
management.metrics.export.graphite.port=9004

Micrometer提供了默认的 HierarchicalNameMapper,用于控制如何将计量器ID 映射到平面层次结构名称

要控制此行为,请定义 GraphiteMeterRegistry 并提供自己的 HierarchicalNameMapper。除非你定义自己的,否则将提供自动配置的 GraphiteConfigClock Bean:
@Bean
public GraphiteMeterRegistry graphiteMeterRegistry(GraphiteConfig config, Clock clock) {
    return new GraphiteMeterRegistry(config, clock, MY_HIERARCHICAL_MAPPER);
}
Humio

默认情况下,Humio注册表会定期将指标推送到 https://cloud.humio.com。 要将指标导出到SaaS Humio,必须提供你的API令牌:

management.metrics.export.humio.api-token=YOUR_TOKEN

你还应该配置一个或多个tags以标识将度量标准推送到的数据源:

management.metrics.export.humio.tags.alpha=a
management.metrics.export.humio.tags.bravo=b
Influx

默认情况下,指标会导出到本地计算机上运行的 Influx。 可使用以下命令提供要使用的 Influx服务器的位置:

management.metrics.export.influx.uri=https://influx.example.com:8086
JMX

Micrometer提供了到 JMX的层次结构映射,主要是作为一种便宜且可移植的方式在本地查看指标。 默认情况下,度量标准被导出到 metrics JMX域。可以使用以下方式提供要使用的域:

management.metrics.export.jmx.domain=com.example.app.metrics

Micrometer提供了默认的 HierarchicalNameMapper,用于控制如何将计量器ID 映射到平面层次结构名称

要控制此行为,请定义 JmxMeterRegistry 并提供自己的 HierarchicalNameMapper。除非你定义自己的,否则将提供自动配置的 JmxConfigClock Bean。
@Bean
public JmxMeterRegistry jmxMeterRegistry(JmxConfig config, Clock clock) {
    return new JmxMeterRegistry(config, clock, MY_HIERARCHICAL_MAPPER);
}
KairosDB

默认情况下,度量标准将导出到在本地计算机上运行的 KairosDB。 可以使用以下方式提供使用的 KairosDB服务器的位置:

management.metrics.export.kairos.uri=https://kairosdb.example.com:8080/api/v1/datapoints
New Relic

New Relic注册表会定期将指标推送到 New Relic。 要将指标导出到 New Relic,必须提供你的API密钥和帐户ID:

management.metrics.export.newrelic.api-key=YOUR_KEY
management.metrics.export.newrelic.account-id=YOUR_ACCOUNT_ID

你还可以更改将度量标准发送到New Relic的时间间隔:

management.metrics.export.newrelic.step=30s
Prometheus

Prometheus希望抓取或轮询单个应用程序实例以获取指标。 Spring Boot在 /actuator/prometheus 提供了一个执行器端点,以适当的格式显示 Prometheus scrape

端点默认情况下不可用,若需公开,有关更多详细信息,请参见暴露端点

这是添加到 prometheus.yml 的示例 scrape_config

scrape_configs:
  - job_name: 'spring'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['HOST:PORT']

对于短暂的或批处理的jobs,其时间可能不够长,无法被捕获,可以使用 Prometheus Pushgateway支持将其指标暴露给Prometheus。 要启用Prometheus Pushgateway支持,请在项目中添加以下依赖项:

<dependency>
    <groupId>io.prometheus</groupId>
    <artifactId>simpleclient_pushgateway</artifactId>
</dependency>

当在类路径上存在Prometheus Pushgateway依赖项时,Spring Boot会自动配置 PrometheusPushGatewayManager bean。 这可以管理将指标推送到Prometheus Pushgateway。可以使用 management.metrics.export.prometheus.pushgateway 下的属性来调整 PrometheusPushGatewayManager。对于高级配置,你还可以提供自己的 PrometheusPushGatewayManager bean。

SignalFx

SignalFx注册表会定期将指标推送到 SignalFx。 要将指标导出到 SignalFx,必须提供访问令牌:

management.metrics.export.signalfx.access-token=YOUR_ACCESS_TOKEN

你还可以更改将度量标准发送到SignalFx的时间间隔:

management.metrics.export.signalfx.step=30s
Simple

Micrometer附带一个简单的内存后端,如果未配置其他注册表,该后端将自动用作后备。 这使你可以查看在metrics端点中收集了哪些指标。

使用任何其他可用后端时,内存后端都会自动禁用。你也可以显式禁用它:

management.metrics.export.simple.enabled=false
Stackdriver

Stackdriver注册表会定期将指标推送到 Stackdriver。 要将指标导出到SaaS Stackdriver,必须提供你的Google Cloud项目ID:

management.metrics.export.stackdriver.project-id=my-project

你还可以更改将度量标准发送到Stackdriver的时间间隔:

management.metrics.export.stackdriver.step=30s
StatsD

StatsD注册表急切地通过UDP将度量标准推送到StatsD agent。 默认情况下,指标会导出到本地计算机上运行的 StatsD agent。 可以使用以下方式提供要使用的StatsD agent主机和端口:

management.metrics.export.statsd.host=statsd.example.com
management.metrics.export.statsd.port=9125

你还可以更改要使用的StatsD线路协议(默认为Datadog):

management.metrics.export.statsd.flavor=etsy
Wavefront

Wavefront注册表会定期将指标推送到 Wavefront。 如果直接将指标导出到 Wavefront,则必须提供API令牌:

management.metrics.export.wavefront.api-token=YOUR_API_TOKEN

或者,你可以使用在你的环境中设置的Wavefront sidecar或内部代理,将指标数据转发到Wavefront API主机:

management.metrics.export.wavefront.uri=proxy://localhost:2878
如果将指标发布到Wavefront代理(如 文档中所述), 则主机必须采用 proxy://HOST:PORT 格式。

你还可以更改将度量标准发送到Wavefront的时间间隔:

management.metrics.export.wavefront.step=30s

3.6.3. 支持的指标

如果适用,Spring Boot将注册以下核心指标:

  • JVM指标,报告以下各项的利用率:

    • 各种内存和缓冲池

    • 与垃圾收集有关的统计数据

    • 线程利用率

    • 加载/卸载的类数

  • CPU指标

  • 文件描述符指标

  • Kafka消费者指标

  • Log4j2指标: 记录每个级别记录到Log4j2的事件数

  • Logback指标: 记录每个级别记录到Logback的事件数

  • Uptime指标: 报告正常运行时间的量度和代表应用程序绝对启动时间的固定量度

  • Tomcat指标 (必须将 server.tomcat.mbeanregistry.enabled 设置为 true 才能注册所有Tomcat指标)

  • Spring Integration指标

Spring MVC指标

通过自动配置,可以检测由Spring MVC处理的请求。 当 management.metrics.web.server.request.autotime.enabledtrue 时,将对所有请求进行这种检测。 另外,当设置为 false 时,可以通过将 @Timed 添加到请求处理方法来启用检测:

@RestController
@Timed (1)
public class MyController {

    @GetMapping("/api/people")
    @Timed(extraTags = { "region", "us-east-1" }) (2)
    @Timed(value = "all.people", longTask = true) (3)
    public List<Person> listPeople() { ... }
}
1 控制器类,用于对控制器中的每个请求处理程序启用计时。
2 一种启用单个端点的方法。如果你将它放在类中,则不必这样做,但是可以用于进一步为此特定端点自定义计时器。
3 longTask = true 的方法为该方法启用长任务计时器。长任务计时器需要一个单独的度量标准名称,并且可以与短任务计时器堆叠在一起。

默认情况下,使用名称 http.server.requests 生成度量。 可以通过设置 management.metrics.web.server.request.metric-name 属性来自定义名称。

默认情况下,与Spring MVC相关的指标带有以下信息标签:

标签 描述

exception

处理请求时引发的任何异常的简单类名。

method

请求的方法(例如: GETPOST

outcome

请求的结果基于响应的状态码。 1xx是 INFORMATIONAL,2xx是 SUCCESS,3xx是 REDIRECTION,4xx是 CLIENT_ERROR,5xx是 SERVER_ERROR

status

响应的HTTP状态码(例如: 200500

uri

请求在变量替换之前的URI模板,如果可能的话(例如: /api/person/{id})

要自定义标签,请提供实现 WebMvcTagsProvider@Bean

Spring WebFlux指标

通过自动配置,可以检测WebFlux控制器和函数式处理程序处理的所有请求。

默认情况下,度量标准的名称为 http.server.requests。 你可以通过设置 management.metrics.web.server.request.metric-name 属性来自定义名称。

默认情况下,与WebFlux相关的指标带有以下信息标签:

标签 描述

exception

处理请求时引发的任何异常的简单类名。

method

请求的方法(例如: GETPOST

outcome

请求的结果基于响应的状态码。 1xx是 INFORMATIONAL,2xx是 SUCCESS,3xx是 REDIRECTION,4xx是 CLIENT_ERROR,5xx是 SERVER_ERROR

status

响应的HTTP状态码(例如: 200500

uri

请求在变量替换之前的URI模板,如果可能的话(例如: /api/person/{id})

要自定义标签,请提供实现 WebFluxTagsProvider@Bean

Jersey服务器指标

当Micrometer的 micrometer-jersey2 模块位于类路径上时,自动配置将启用对Jersey JAX-RS实现所处理的请求的检测。 当 management.metrics.web.server.request.autotime.enabledtrue 时,将对所有请求进行这种检测。 另外,当设置为 false 时,可以通过将 @Timed 添加到请求处理方法来启用检测:

@Component
@Path("/api/people")
@Timed (1)
public class Endpoint {

    @GET
    @Timed(extraTags = { "region", "us-east-1" }) (2)
    @Timed(value = "all.people", longTask = true) (3)
    public List<Person> listPeople() { ... }
}
1 在资源类上,以对资源中的每个请求处理程序启用计时。
2 关于启用单个端点的方法。如果你将它放在类中,则不必这样做,但是可以用于进一步为此特定端点自定义计时器。
3 longTask = true 的方法上为该方法启用长任务计时器。长任务计时器需要一个单独的度量标准名称,并且可以与短任务计时器堆叠在一起。

默认情况下,使用名称 http.server.requests 生成度量。 可以通过设置 management.metrics.web.server.request.metric-name 属性来自定义名称。

默认情况下,Jersey服务器指标带有以下信息:

标签 描述

exception

处理请求时引发的任何异常的简单类名。

method

请求的方法(例如: GETPOST

outcome

请求的结果基于响应的状态码。 1xx是 INFORMATIONAL,2xx是 SUCCESS,3xx是 REDIRECTION,4xx是 CLIENT_ERROR,5xx是 SERVER_ERROR

status

响应的HTTP状态码(例如: 200500

uri

请求在变量替换之前的URI模板,如果可能的话(例如: /api/person/{id})

要自定义标签,请提供实现 JerseyTagsProvider@Bean

HTTP客户端指标

Spring Boot Actuator管理 RestTemplateWebClient 的工具。为此,你必须注入自动配置的构建器并使用它来创建实例:

  • RestTemplateBuilder for RestTemplate

  • WebClient.Builder for WebClient

也可以手动应用负责此工具的定制程序,即 MetricsRestTemplateCustomizerMetricsWebClientCustomizer

默认情况下,将使用名称 http.client.requests 生成度量。 可以通过设置 management.metrics.web.client.request.metric-name 属性来自定义名称。

默认情况下,通过检测的客户端所生成的指标带有以下信息标签:

标签 描述

clientName

URI的主机部分

method

请求的方法(例如: GETPOST

outcome

请求的结果基于响应的状态码。 1xx是 INFORMATIONAL,2xx是 SUCCESS,3xx是 REDIRECTION,4xx是 CLIENT_ERROR,5xx是 SERVER_ERROR,否则是 UNKNOWN

status

响应的HTTP状态码(例如: 200500),如果有I/O问题,则为 IO_ERROR;否则为 CLIENT_ERROR

uri

请求在变量替换之前的URI模板,如果可能的话(例如: /api/person/{id})

要自定义标签,可以根据你选择的客户端,提供一个实现 RestTemplateExchangeTagsProviderWebClientExchangeTagsProvider@BeanRestTemplateExchangeTagsWebClientExchangeTags 中有便捷的静态函数。

缓存指标

通过自动配置,可以在启动时使用前缀为 cache 的指标来检测所有可用的 Caches。 高速缓存检测针对一组基本指标进行了标准化。还提供其他特定于缓存的指标。

支持以下缓存库:

  • Caffeine

  • EhCache 2

  • Hazelcast

  • 任何兼容的JCache (JSR-107)实现

根据缓存的名称和从bean名称派生的 CacheManager 的名称对指标进行标记。

只有启动时可用的缓存才绑定到注册表。对于在启动阶段后即时或以编程方式创建的缓存,需要显式注册。提供 CacheMetricsRegistrar Bean可简化该过程。
数据源指标

通过自动配置,可以使用前缀为 jdbc.connections 的度量来检测所有可用的 DataSource 对象。 数据源检测产生的指标表示池中当前活动,空闲,最大允许和最小允许的连接。

指标还根据基于bean名称计算的 DataSource 名称进行标记。

默认情况下,Spring Boot为所有支持的数据源提供元数据。如果你喜欢的数据源不支持开箱即用,则可以添加额外的 DataSourcePoolMetadataProvider bean。有关示例,请参见 DataSourcePoolMetadataProvidersConfiguration

另外,使用Hikaricp前缀公开特定于Hikari的指标。每个度量指标都以池的名称标记(可以通过 spring.datasource.name 进行控制)。

Hibernate指标

自动配置启用所有可用的Hibernate EntityManagerFactory 实例的检测,这些实例使用名为 hibernate 的指标启用了统计信息。

指标还使用来自bean名称的 EntityManagerFactory 名称进行标记。

要启用统计信息,必须将标准JPA属性 hibernate.generate_statistics 设置为 true。 你可以在自动配置的 EntityManagerFactory 上启用它,如以下示例所示:

spring.jpa.properties.hibernate.generate_statistics=true
RabbitMQ指标

自动配置将使用名为 rabbitmq 的指标启用所有可用的RabbitMQ连接工厂的检测。

3.6.4. 注册自定义指标

要注册自定义指标,请将 MeterRegistry 注入你的组件,如以下示例所示:

class Dictionary {

    private final List<String> words = new CopyOnWriteArrayList<>();

    Dictionary(MeterRegistry registry) {
        registry.gaugeCollectionSize("dictionary.size", Tags.empty(), this.words);
    }

    // …

}

如果发现重复测量了跨组件或应用程序的一组指标,则可以将此指标封装在 MeterBinder 实现中。 默认情况下,所有 MeterBinder Bean的指标都将自动绑定到Spring管理的 MeterRegistry

3.6.5. 自定义单个指标

如果需要将自定义应用于特定的 Meter 实例,则可以使用 io.micrometer.core.instrument.config.MeterFilter 接口。 默认情况下,所有 MeterFilter bean都将自动应用于micrometer MeterRegistry.Config

例如,如果要将所有以 com.example 开头的计量器ID的 mytag.region 标签重命名为 mytag.area,则可以执行以下操作:

@Bean
public MeterFilter renameRegionTagMeterFilter() {
    return MeterFilter.renameTag("com.example", "mytag.region", "mytag.area");
}
通用标签

通用标签通常用于在操作环境(如主机,实例,区域,堆栈等)上进行维度深入分析。通用标签适用于所有计量器,并可以按以下示例所示进行配置:

management.metrics.tags.region=us-east-1
management.metrics.tags.stack=prod

上面的示例将 region 标签和 stack 标签添加到所有计量器,其值分别为 us-east-1prod

如果使用Graphite,则通用标签的顺序很重要。由于使用这种方法无法保证通用标签的顺序,因此建议Graphite用户定义自定义 MeterFilter
Per-meter属性

除了 MeterFilter bean之外,还可以使用属性在per-meter基础上应用一组有限的自定义设置。 Per-meter定制适用于任何以给定名称开头的所有计量器IDs。例如,以下将禁用所有ID以 example.remote 开头的计量器:

management.metrics.enable.example.remote=false

以下属性允许按per-meter自定义:

Table 8. Per-meter自定义
属性 描述

management.metrics.enable

是否拒绝计量器发出任何指标。

management.metrics.distribution.percentiles-histogram

是否发布适合计算可聚合(跨维度)百分比近似值的直方图。

management.metrics.distribution.minimum-expected-value, configprop:management.metrics.distribution.maximum-expected-value

通过限制期望值的范围来发布较少的直方图桶。

management.metrics.distribution.percentiles

发布在应用程序中计算的百分位值

management.metrics.distribution.sla

发布带有SLAs定义的桶的累积直方图。

有关 percentiles-histogrampercentilessla 背后的概念的更多详细信息,请参阅micrometer文档的 直方图和百分位数部分。

3.6.6. 指标端点

Spring Boot提供了一个 metrics 端点,可用于诊断检查应用程序收集的指标。端点默认情况下不可用,若需公开, 有关更多详细信息,请参见暴露端点

导航到 /actuator/metrics 会显示可用计量器名称的列表。你可以通过提供特定名称作为选择器来深入查看有关特定计量器的信息, 例如: /actuator/metrics/jvm.memory.max

你在此处使用的名称应与代码中使用的名称相匹配,而不是已经针对其附带的监视系统进行了命名约定标准化后的名称。 换句话说,如果 jvm.memory.max 由于其蛇形命名约定而在Prometheus中显示为 jvm_memory_max, 则在检查 metrics 端点中的计量器时,仍应使用 jvm.memory.max 作为选择器。

你还可以在网址末尾添加任意数量的 tag=KEY:VALUE 查询参数,以在维度上更深入地了解计量器,例如: /actuator/metrics/jvm.memory.max?tag=area:nonheap

报告的测量值是与计量器名称和已应用的任何标签相匹配的所有计量器的统计信息的总和。 因此,在上面的示例中,返回的“值”统计量是堆的“代码缓存”,“压缩类空间”和“元空间”区域的最大内存占用量的总和。 如果你只想查看“元空间”的最大大小,则可以添加一个额外的 tag=id:Metaspace, 即 /actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace

3.7. 审计

一旦启动了Spring Security,Spring Boot Actuator将拥有一个灵活的审核框架来发布事件 (默认情况下,“身份验证成功”,“失败”和“拒绝访问”异常)。此功能对于基于身份验证失败的报告和实施锁定策略非常有用。

可以通过在应用程序的配置中提供类型为 AuditEventRepository 的bean来启用审核。为了方便起见,Spring Boot提供了一个 InMemoryAuditEventRepositoryInMemoryAuditEventRepository 具有有限的功能,我们建议仅将其用于开发环境。 对于生产环境,请考虑创建自己的替代 AuditEventRepository 实现。

3.7.1. 自定义审计

要自定义已发布的安全事件,可以提供自己的 AbstractAuthenticationAuditListenerAbstractAuthorizationAuditListener 的实现。

你也可以将审计服务用于自己的业务事件。 为此,可以将 AuditEventRepository bean注入你自己的组件中并直接使用它,或者通过Spring ApplicationEventPublisher(通过实现 ApplicationEventPublisherAware)发布 AuditApplicationEvent

3.8. HTTP追踪

可以通过在应用程序的配置中提供 HttpTraceRepository 类型的Bean来启用HTTP追踪。 为了方便起见,Spring Boot默认提供了一个 InMemoryHttpTraceRepository,用于存储最近100次请求-响应交换的追踪。 与其他追踪解决方案相比,InMemoryHttpTraceRepository 受到限制,我们建议仅将其用于开发环境。 对于生产环境,建议使用可用于生产的追踪或可观察性解决方案, 例如:Zipkin或Spring Cloud Sleuth。或者,创建自己的 HttpTraceRepository 来满足你的需求。

httptrace 端点可用于获取有关存储在 HttpTraceRepository 中的请求-响应交换的信息。

3.8.1. 自定义HTTP追踪

要自定义每个追踪中包含的条目,请使用 management.trace.http.include 配置属性。对于高级定制,请考虑注册自己的 HttpExchangeTracer 实现。

3.9. 进程监控

spring-boot 模块中,你可以找到两个类来创建通常对进程监视有用的文件:

  • ApplicationPidFileWriter 创建一个包含应用程序PID的文件(默认情况下,在应用程序目录中,文件名为 application.pid)。

  • WebServerPortFileWriter 创建一个文件(一个或多个),其中包含正在运行的Web服务器的端口(默认情况下,在应用程序目录中,文件名为 application.port)。

默认情况下,这些写入器不会被激活,但你可以启用:

3.9.1. 扩展配置

META-INF/spring.factories 文件中,你可以激活写入PID文件的监听器,如以下示例所示:

org.springframework.context.ApplicationListener=\
org.springframework.boot.context.ApplicationPidFileWriter,\
org.springframework.boot.web.context.WebServerPortFileWriter

3.9.2. 以编程方式

你还可以通过调用 SpringApplication.addListeners(…​) 方法并传递适当的 Writer 对象来激活监听器。此方法还允许你自定义 Writer 构造函数中的文件名和路径。

3.10. 接下来要读什么

你可能需要阅读有关 Graphite等绘图工具的信息。

否则,你可以继续阅读 部署选项,也可以继续阅读有关Spring Boot的 构建工具插件的详细信息。