RedCloud Help

Spring Boot

您可以复制本文件供自己使用或分发给他人,但不得收取任何费用,而且每份复制件都必须包含本版权声明,无论是以印刷品还是电子方式分发。

2.获取帮助

如果您在使用 Spring Boot 时遇到困难,我们愿意提供帮助。、

  • 试试 "如何操作 "文件。它们为最常见的问题提供了解决方案。

  • 学习 Spring 基础知识。Spring Boot 基于许多其他 Spring 项目。请访问 spring.io 网站,获取大量参考文档。如果你刚开始使用 Spring,可以试试其中的指南。

  • 提出问题。我们监控 stackoverflow.com 中标记为 spring-boot 的问题。

  • 在 github.com/spring-projects/spring-boot/issues 上报告 Spring Boot 的错误。

3 文档概述

本节简介Spring参考文档。它是本文档其余部分的映射。 本文档的最新版本可在github.com/spring-projects/spring-boot/issues 上查询。

3.1 第一步

如果你开始学习Spring Boot或“Spring”,请从一下主题开始

  • 从零开始概述|要求|安装

  • 教程:第一部分|第二部分

  • 运行你的示例:第一部分|第二部分

3.2 从早期版本升级

你应始终确保升级的是受支持的Spring Boot版本。 根据你升级到的版本,你可以在这里找到一些额外的提示:

  • 从1.x:从1.x开始

  • 升级到新功能版本升级到新公共能版本

  • Spring Boot CLI:升级Spring Boot CLI

3.3 使用Spring Boot 开发

准备好真正开始使用Spring Boot了吗?我们将为你提供帮助:

  • 构建系统:Maven|Gradle|Ant|Starters

  • 最佳实践:代码结构|@Configuration|@EnableAutoConfiguration|Beans和依赖注入

  • 运行你的代码:IDE|Packaged|Maven|Gradle

  • 打包你的app:Production jars

  • Spring Boot CLI:使用CLI

3.4 学习Spring Boot功能

需要了解有关Spring Boot核心功能的更多详情?下面的内容就是为你准备的:

  • SpringApplication

  • 外部配置

  • Profiles

  • Logging

3.5 Web

如果你正在开发Spring Boot网络应用程序,请阅读一下内容:

  • Servlet Web应用程序:Spring MVC,Jersey、Embedded Servlet Containers

  • 反应式网络应用:Spring WebFlux、嵌入式Servlet容器

  • 优雅关机

  • Spring Security:默认安全配置、OAuth2的自动配置、SAML

  • Spring Session:自动配置Spring Session

  • Spring HATEOAS:Spring HATEOAS的自动配置

3.6 DATA

如果你的应用程序要处理数据存储,可以在此查看如何配置

  • SQL配置的SQL数据存储、嵌入式数据库支持、连接池等。

  • NOSQL:redis、MongoDB、Neo4j等NOSQL存储自动配置。

3.7 Messaging

如果你的应用程序使用任何报文传输协议,请参阅以下一个或多个章节:

  • JMS:ActiveMQ和Artemis的自动配置,通过JMS发送和接受消息

  • AMQP:RabbitMQ的自动配置

  • Kafka:Spring Kafka的自动配置

  • Pulsar:Spring自动配置Apache Pulsar

  • RSocket:自动配置Spring Framework的RSocket支持

  • Spring Integration:自动配置

3.8 Io

如果你的应用程序需要IO功能,请参阅以下一个或多个章节:

  • caching:通过EhCache、Hazelcast、Infinispan等提供缓存支持。

  • Quartz:Quartz Scheduling

  • Mail:邮箱发送电子邮件

  • Rest Clients:使用RestTemplate和WebClient调用REST服务

  • 网络服务:Spring Web服务的自动配置。

  • JTA:使用JTA进行分布式事务处理。

3.9 容器镜像

Spring Boot为构建高效的容器镜像提供了一流的支持。你可以在此阅读更多相关信息:

  • Efficient Container Images:优化Docker映像等容器映像的技巧。

  • Dokerfiles:使用dockerfiles构建容器镜像

  • 云本地构建包:使用Maven和Gradle支持云本地构建包。

3.10 Moving to Production

当你准备将Spring Boot应用程序推向生产时,我们有一些技巧你可能会喜欢:

  • 管理断电概述

  • Connection Options:http|JMX

  • Monitoring:metrics|Auditing|Http Exchanges|Process

3.11 GraalVM本地镜像

Spring Boot 应用程序可以使用GraalVM转换为本地可执行的文件。你可以在这里了解更多关于本机镜像支持的信息:

  • GraalVM Native Images:介绍|与JVM的主要区别|实时处理

  • 入门:构建包|本地构建工具

  • testing:JVM|本地构建工具

  • 高级主题:嵌套配置属性|转换jar|已知限制

3.12 高级主题

最后,我们为高级用户准备了几个主题:

  • Spring Boot应用程序部署:云部署|操作系统服务

  • 构建工具插件:Maven|Gradle

  • 附录:应用程序属性|配置元数据|自动配置类|测试自动配置注释|可执行文件|依赖关系版本

4 开始

如果你要开始学习Spring Boot或一般意义上的“Spring”,请先阅读本节内容。它回答了“是什么?”、“怎么做?”和为什么?等基本问题。其中包括Spring Boot简介和安装说明。然后,我们将引导你构建第一个Spring Boot应用程序,并讨论一些核心原则。

4.1 Spring Boot简介

Spring Boot可以帮助你创建独立的、基于Spring的生产级别应用程序,并可以运行。我们对Spring平台和第三方库持开放的态度,因此你可以轻松上手。大多数Spring Boot应用程序只需要很少的Spring配置。 你可以使用Spring Boot创建java应用程序,这些应用程序可以通过java -jar或更传统的war部署启动。 我们的主要目标是:

  • 为所有Spring开发提供更快、更广泛的入门体验。

  • 开始时要有主见,单当需求开始偏离默认值时,要迅速摆脱困境。

  • 提供一系列大型项目冲用的非功能性功能(如嵌入式服务,安全性,度量,健康检查和外部化配置)。

  • 完全无需生成代码(当不针对本地图像时),也无需XML配置。

4.2 系统要求

Spring Boot3.2.1需要java17,并兼容java21.还需要Spring Framework 6.1.2或更高版本。 为以下构建工具提供明确的构建支持

构建工具

version版本

Maven

3.6.3 或更高版本

Gradle

7.x(7.5或更高版本)和8.x

4.2.1 Servlet 容器

Spring Boot支持一下嵌入式servlet容器:

名称

ServletVersion

Tomcat10.1

6.0

jetty12.0

6.0

Undertow 2.3

6.0

你还可以将Spring Boot应用程序部署到任何兼容servlet5.0+的容器中。

4.2.2 GraalVM本地镜像

Spring Boot 应用程序可使用GraalVM22.3或更搞版本转换为本地镜像。 可以使用GraalVM提供的本地构建工具Gradle/Maven插件或native-image工具创建镜像。还可以使用原生镜像Paketo构建包创建原生镜像。 支持一下版本

name

version

GraalVM Community

22.3

本地构建工具

0.9.28

4.3 安装SpringBoot

SpringBoot可与经典“java开安防工具一起使用,也可作为命令行工具安装。无论那种方式,你都需要Java SDK V17或更高版本。开始之前,应使用一下命名检查当前的Java安装:

java -version

如果你是Java开发新手或想尝试使用SpringBoot,你可能想先试试SpringBootCLI(命令行界面)。否则,请继续阅读“经典”安装说明。

4.3.1 Java开发人员安装说明

你可以像使用任何标准Java库一样使用SpringBoot。为此,请在类路径中包含相应的spring-boot-* 。jar文件。SpringBoot不需要任何特殊的集成工具,因此你可以使用任何集成开发环境或文本编辑器。此外,SpringBoot应用程序也没有什么特别之处,因此你可以像运行其他Java程序一样运行和调试SpringBoot应用程序。 虽然你可以复制SpringBoot jars,但我们通常建议你使用支持依赖管理的构建工具(如Maven或Gradle)。

Maven安装

SpringBoot与Apache Maven 3.6.3或更高版本兼容。如果你尚未安装Maven,可以按照maven.apache.org上的说明进行操作。

SpringBoot依赖项使用org.springframework.boot组Id。通常,你的Maven POM文件继承自spring-boot-starter-parent项目,并声明对一个或多个“启动器”‘的依赖。SPringBoot还提供了一个可选的Maven插件,用于创建可执行的jar。 有关SpringBoot和Maven入门的更多详情,请参阅Maven插件参考指南的“入门”部分。

Gradle安装

Spring Boot 兼容 Gradle 7.x(7.5 或更高版本)和 8.x。如果尚未安装 Gradle,可以按照 gradle.org 上的说明进行安装。

可以使用 org.springframework.boot group 声明 Spring Boot 依赖关系。通常,您的项目会声明对一个或多个 "启动器 "的依赖。Spring Boot 提供了一个有用的 Gradle 插件,可用于简化依赖关系声明和创建可执行 jar。

有关 Spring Boot 和 Gradle 入门的更多详情,请参阅 Gradle 插件参考指南的 "入门 "部分。

4.3.2 安装SpringBootCLI

SpringBootCLI是一锤石命令行工具,可以快速创建Spring的原型。 你不需要使用CLI来使用SpringBoot,但它是一种无需集成开发环境即可快速启动Spring应用程序的方法。

手动安装

你可以从一下位置下载SpringCLI发行版:

下载后,请按照解压压缩包中的INSTALL.txt说明进行操作。总之,在.zip文件中的bin/目录下有一个spring脚本(windows下为spring.bat) 。另外,你也困出差用java -jar和.jar文件(该脚本可帮助你确保类路径设置正确)。

使用SDKMAN安装

SDKMAN(软件开发工具包管理器)可用于管理各种二进制SDK的多个版本,包括Groovy和SpringBootCLI。从sdkman.io获取SDKMAN! 并使用以下命令安装SpringBoot:

sdk install springboot spring --version

如果你为CLI开发功能,并希望访问你创建的版本,请使用一下命令:

sdk install springboot dev /path/to/spring-boot/spring-boot-cli/target/spring-boot-cli-3.2.1-bin/spring-3.2.1/ sdk default springboot dev spring --verison

前面的说明安装了spring的本地实例,成为dev实例。它指向目标构建位置,因此每次重构springboot时,spring都是最新版本的。 运行一下命令即可查看:

sdk ls springboot
OSX自制安装软件

如果你使用的Mac和Homebrew,可以使用一下命令安装SpringBootCLI

brew tap spring-io/tap brew install spring-boot

Homebrew将spring 安装到/usr/local/bin

安装MacPorts

如果使用Mac并使用MacPorts,则可以使用一下命令安装SpringBootCLI:

sudo port install spring-boot-cli
命令行完成

SpringBootCLI包含了为Bash和zsh shell提供命令完成的脚本。你可以在任何shell中使用source脚本(也被命名为spring),也可以将其放在个人或全系统的bash完成初始化中。在Debian系统中,系统范围的脚本位于 /shell-completion/bash目录中,当新shell启动时,该目录中的所有脚本都会被执行。例如,如果你使用SDKMAN!手动安装,则可使用一下命令运行脚本

. ~/.sdkman/candidates/springboot/current/shell-completion/bash/spring
Windows Scoop Installation

如果你在Windows上使用Scoop,可以使用一下命令安装SpringBootCLI:

scoop bucket add extras scoop install springboot

Scoop 将 spring 安装到 ~/scoop/apps/springboot/current/bin 。

4.4 开发第一个SpringBoot应用程序

本节介绍如何开发一个小型的“hello world”应用程序,以突出SpringBoot的一些关键功能。你可以选择Maven或Gradle作为构建系统。

4.4.1 前提条件

在开始之前,请打开终端并运行一下命令,确保你安装的java版本有效:

java -version
Maven

如何你需要使用Maven,请确保已经安装了Maven:

mvn -v
Gradle

如果要使用Gradle,请确保已安装Gradle:

gradle --version

4.4.2 使用Maven设置项目

我们首先需要创建一个maven pom.xml文件。pom.xml是用于构建项目的配方。打开你喜欢的文本添加器,添加一下内容:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>myproject</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.1</version> </parent> <!-- Additional lines to be added here... --> </project>

前面的列表应该能为你提供一个可用的构建。你可以运行mvn package对其进行测试(目前,你可以忽略“jar将为空-未标记包含内容!”的警告)。

4.4.3 使用Gradle设置项目

我们首先需要创建一个Gradle build.gradle文件。build.gradle是用于构建项目构建脚本。打开你喜欢的文本编辑器,添加一下内容:

plugins { id 'java' id 'org.springframework.boot' version '3.2.1' } apply plugin: 'io.spring.dependency-management' group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' repositories { mavenCentral() } dependencies { }

上面的列表应该能为你提供一个正常运行的构建环境。你可以运行gradle classes.

4.4.4 添加类路径依赖项

Spring Boot提供了许多“启动器”,可让你在类路径中添加jar。“启动器”提供了开发特定类型应用程序时可能需要的依赖项。

Maven

大多数SpringBoot应用程序都在POM的Parent部分使用spring-boot-starter-parent。spring-boot-starter-parent是一个特殊的启动器,提供了有用的Maven默认值。它还提供了一个dependency-management部分,这样你就可以省略version标记,已获得“收祝福的”依赖关系。 由于我们要开发的是网络应用程序,因此要添加spring-boot-starter-web依赖关系。在此之前,我们可以通过运行一下命令来查看当前的情况:

mvn dependecy:tree

mvn dependency:tree 命令会打印出依赖关系的树状图。你可以看到,spring-boot-starter-parent本身没有提供任何依赖项。要添加必要的依赖项,请编辑pom.xml并在parent部分下面添加spring-boot-starter-web依赖项:

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>

如果再次运行mvn dependency:tree ,你会发现现在又多了一些依赖,包括Tomcat web服务器和SpringBoot本身。

Gradle

大多数SpringBoot应用程序都使用org.springframework.boot Gradle插件。该插件提供了有用的默认值和Gradle任务。 io.spring.dependency-management Gradel插件提供了依赖关系管理功能,因此可以省略version标记来处理“受祝福的”依赖关系。 由于我们要开发的是网络应用程序,因此要添加spring-boot-starter-web依赖关系。在此之前,我们可以通过运行以下命令来查看当前的情况:

gradle dependencies

gradle dependencies命令会打印出项目的依赖关系的树状图。现在,项目没有依赖项。要添加必要的依赖项,请编辑build.gradle并在dependencies部分而添加spring-boot-starter-web依赖项:

dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' }

如果再次运行gradle dependencies ,你会发现有多长一些依赖项,包括tomcat web服务器和SpringBoot本身。

4.4.5 编写代码

要完成应用程序,我们需要创建一个java文件。默认情况下,Maven和Gradle从src/main/java编译源代码,因此需要创建该目录结构,然后添加一个名为src/main/java/MyApplication.java的文件,其中包含以下代码:

package com.example; @RestController @SpringBootApplication public class MyApplication { @RequestMapping("/") String home() { return "Hello World!"; } public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
@RestController @SpringBootApplication class MyApplication { @RequestMapping("/") fun home() = "Hello World!" } fun main(args: Array<String>) { runApplication<MyApplication>(*args) }

虽然这里的代码不多,单内容却不少。在接下来的几节中,我们将逐步介绍重要的部分。

@RestController和@RequestMapping注解

MyApplication类的第一个注解是@RestController。这就是所谓的定型注解。他为阅读代码的人和Spring提供提示,说明该类扮演着特定的角色。在本例中,我们的类是一个Web@Controller类,因此Spring在处理传入的Web请求时会考虑该类。 @RequestMapping注解提供了“路由”信息。他告诉spring,任何带有/路径的http请求都应映射到home方法。@RestController注解告诉Spring直接将生成的字符串呈现给调用者。

@SpringBootApplication注解

第二个类级注释是@SpringBootApplication。这个注解被称为元注释,它结合了@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan。 其中,我们最感兴趣的注解是@EnableAutoConfiguration。@EnableAutoConfiguration会告诉SpringBoot根据你添加的jar依赖关系“猜测”你希望如何配置Spring。由于spring-boot-starter-web添加了Tomcat和SpringMVC,因此自动配置会假定你正在开发Web应用程序,并相应地设置Spring。

The “Main”Method

应用程序的最后一部分是main方法。这是一个标准方法,遵循应用程序入口点的java惯例。我们主方法通过调用run委派给SpringBoot的SpringApplication类。SpringApplication引导我们的应用程序,启动Spring,而Spring又会启动自动配置的Tomcat Web服务器。我们需要将MyApplication.class作为参数传递给run方法,以告诉SpringApplication那个是主要的Spring组件。我们还需要传递args数组,以显示任何命令行参数。

4.4.6 运行实例

至此,你的应用程序应该可以正常运行了。由于你使用了spring-boot-starter-parent POM,因此你可以使用一个有用的run目标来启动应用程序。从项目根目录键入 mvn spring-boot:run已启动应用程序。你应该会看到与下面类似的输出:

$ mvn spring-boot:run . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.2.1) ....... . . . ....... . . . (log output here) ....... . . . ........ Started MyApplication in 0.906 seconds (process running for 6.514)

如果打开浏览器访问localhost:8080,应该会看到一下输出:

Hello world!

要优雅地退出应用程序,请按ctrl-c。

Gradle

至此,应用程序应该可以正常运行了。由于你使用了org.springframework.boot Gradle插件,所以你有了一个有用的bootRun目标,可以用来启动应用程序。在项目根目录下键入gradle bootRun启动应用程序。你应该会看到类似下面的输出:

$ gradle bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.2.1) ....... . . . ....... . . . (log output here) ....... . . . ........ Started MyApplication in 0.906 seconds (process running for 6.514)

如果打开浏览器访问 localhost:8080 ,应该会看到以下输出:

Hello World!

要优雅地退出应用程序,请按 ctrl-c 。

4.4.7 创建可执行jar

最后,我们将创建一个完全独立的可执行jar文件,一遍在生产中运行。可执行jar(有时称为“uber jars”或“fat jars”)是包含已编译类一级代码运行时所需的所有jar依赖项的归档文件。

Maven

要创建可执行jar,我们需要将spring-boot-maven-plugin添加到pom.xml中。为此,请在dependencies部分下方插入一下几行:

<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>

保存pom.xml并从命令行运行mvn package如下:

$ mvn package [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building myproject 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] .... .. [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ myproject --- [INFO] Building jar: /Users/developer/example/spring-boot-example/target/myproject-0.0.1-SNAPSHOT.jar [INFO] [INFO] --- spring-boot-maven-plugin:3.2.1:repackage (default) @ myproject --- [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------

在target目录中,你应该可以看到myproject-0.0.1-SNAPSHOT.jar。文件大小应该在18MB左右。如果你想看里面的内容,可以使用jar tvf,如下命令:

$ jar tvf target/myproject-0.0.1-SNAPSHOT.jar

你还应该在target目录中看到一个更小的名为myproject-0.0.1-SNAPSHOT.jar.original的文件。这是Maven在SpringBoot重新打包之前创建的原始jar文件。 要运行应用程序,请使用java -jar命令,如下所示:

$ java -jar target/myproject-0.0.1-SNAPSHOT.jar . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.2.1) ....... . . . ....... . . . (log output here) ....... . . . ........ Started MyApplication in 0.999 seconds (process running for 1.253)

与之前一样,要退出应用程序,请按ctrl-c。

Gradle

要创建一个可执行 jar,我们需要在命令行中运行 gradle bootJar 如下:

$ gradle bootJar BUILD SUCCESSFUL in 639ms 3 actionable tasks: 3 executed

在 build/libs 目录中,您应该可以看到 myproject-0.0.1-SNAPSHOT.jar 。文件大小应该在 18 MB 左右。如果你想偷看里面的内容,可以使用 jar tvf ,如下所示:

$ jar tvf build/libs/myproject-0.0.1-SNAPSHOT.jar

要运行该应用程序,请使用 java -jar 命令,如下所示:

$ java -jar build/libs/myproject-0.0.1-SNAPSHOT.jar . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.2.1) ....... . . . ....... . . . (log output here) ....... . . . ........ Started MyApplication in 0.999 seconds (process running for 1.253)

与之前一样,要退出应用程序,请按 ctrl-c 。

4.5 下一步阅读

希望本节提供的事一些SpringBoot基础知识能帮助你开始编写自己的应用程序。如果你是任务导向型开发人员,你可能需要跳过spring.io,查看一些入门指南,以解决“如何使用spring进行操作”的具体问题。我们还有专门针对SpringBoot的“如果做”参考文档。 否则,下一步就是阅读《使用SpringBoot进行开发》。如果你是在没有耐心,也可以提前阅读有关SpringBoot功能的内容。

5.升级SpringBoot

项目维基上提供了如何从SpringBoot早期版本升级的说明。请点击发行说明部分的链接,查找要升级的版本。 升级说明总是版本说明中的第一个项目。如果你的版本落后一个以上,请确保你也查看了所跳转版本的发型说明。

5.1 从1.x升级

如果你要从SpringBoot的1.x版本升级,请查看项目维基上的“迁移指南”,其中提供了详细的升级说明。还可以查看“发布说明”,了解每个版本的“新功能和值得注意的功能”列表。

5.2 升级到新功能版本

升级到新功能版本时,某些属性可能会被重命名或移除。SpringBoot提供了一种在启动时分析应用程序环境并打印诊断结果的方法,而且还能再运行时为你临时迁移属性。要启用该功能,请在项目中添加一下依赖关系:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-properties-migrator</artifactId> <scope>runtime</scope> </dependency>

5.3 升级SpringBootCLI

要升级现有的CLI安装,请使用相应的软件包管理器命令(例如brew upgrade)。如果你手动安装了CLI,请按照标准说明操作,记住要更新PATH环境变量,以移除任何旧的引用。

5.4 下一步阅读

一旦决定升级应用程序,你可以在本文档的其余部分找到有关具有功能的详细信息。 SpringBoot的文档是针对该版本,因此你在这里找到的任何信息都将包含该版本的最新变更。

6.使用SpringBoot开发

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

6.1 Build Systems

强烈建议你选择一个支持依赖关系管理的构建系统,该系统可以使用发布到MavenCentral“资源库的工件。我们建议你选择Maven或Gradle。SpringBoot也可以与其他构建系统(例如ant)配合使用,但它们的支持并不完善。

6.1.1 依赖关系管理

SpringBoot的每个版本都会提供其支持的依赖项的精选列表。实际上,你无需在构建配置中提供这些依赖项的版本,因为SpringBoot会为你管理这些依赖项。当你升级SpringBoot本身时,这些依赖项也会以一致的方式升级。

这些精选列表包含了可与SpringBoot配合使用的所有spring模块,一级第三方的精选列表。该列表以标准物料清单(spring-boot-dependencies)的形式提供,可与Maven和Gradle一起使用。

6.1.2 Maven

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

6.1.3 Gradle

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

6.1.4 Ant

使用Apache Ant+Lvy可以构建SpringBoot项目。spring-boot-antlib“AntLib”模块也可帮助Ant创建可执行的jar。 要声明依赖关系,典型的ivy.xml文件看起来与下面的示例类似:

<ivy-module version="2.0"> <info organisation="org.springframework.boot" module="spring-boot-sample-ant"/> <configurations> <conf name="compile" description="everything needed to compile this module"/> <conf name="runtime" extends="compile" description="everything needed to run this module"/> </configurations> <dependencies> <dependency org="org.springframework.boot" name="spring-boot-starter" rev="${spring-boot.version}" conf="compile"/> </dependencies> </ivy-module>

典型的build.xml看上去就像下面的示例:

<project xmlns:ivy="antlib:org.apache.ivy.ant" xmlns:spring-boot="antlib:org.springframework.boot.ant" name="myapp" default="build"> <property name="spring-boot.version" value="3.2.1"/> <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>

6.1.5 Starters

启动器是一组方便的依赖关系描述符,你可以将其包含在应用程序中。你可以一站式获得所需的所有Spring和相关技术,而无需翻阅实例代码和复制粘贴大量依赖关系描述符。例如,如果你想开始使用Spring和JPA访问数据库,请在项目中包含spring-boot-starter-data-jpa依赖关系。 启动器包含了大量的依赖项,这些依赖项可以让项目快速启动和运行,并提供一套一致的,受支持的受管传递依赖项。

名字的含义

所有官方启动程序都遵循类似的命名模式:spring-boot-starter-,其中 是特定类型的应用程序。这种命名结构旨在帮助你查找启动程序。许多集成开发环境中的Maven集成可让你按名称搜索依赖项。例如,安装了响应的Eclipse或SpringTools插件后,你可以在POM编辑器中按下ctrl-space建,然后键入“spring-boot-starter”,已查看完整列表。 正如“创建自己的启动程序”不分所述,第三方启动程序不应以spring-boot开头,因为它是SpringBoot官方工件的专用开头。相反,第三方启动程序通常以项目名称开头。例如,名为thirdpartyproject的第三方启动点项目通常会被命名为thirdpartyproject-spring-boot-starter。 SpringBoot在org.springframework.boot组中提供了一下应用程序启动器:

名称

说明

spring-boot-starter

核心启动器,包括自动配置支持、日志和yaml

spring-boot-starter-activemq

使用Apache ActiveMQ发送JMS消息的启动器

spring-boot-starter-amqp

使用SpringAMQP和RabbitMQ的启动器

spring-boot-starter-aop

使用Spring AOP和Aspectj切面变成的入门可成

spring-boot-starter-artemis

使用ApacheArtemis发送JMS消息的启动器

spring-boot-starter-cache

使用SpringFramework缓存支持的启动器

spring-boot-starter-data-cassandra

使用Cassandra分布式数据库和SpringDataCassandra的入门指南

spring-boot-starter-data-couchbase-reactive

使用面向文档的Couchbase数据库和SpringDataCouchbaseReactive的入门课程

spring-boot-starter-data-elasticsearch

使用elasticsearch搜索和分析引擎以及SpringDataElasticsearch的入门可能

spring-boot-starter-data-jdbc

使用SpringDataJDBC的入门指南

spring-boot-starter-jpa

使用SpringDataJPA与Hibernate结合使用的入门指南

spring-boot-starter-data-ldap

使用SpringDataLDAP的入门指南

spring-boot-starter-data-mongodb-reactive

使用MongoDB面向文档的数据库和SpringDataMongoDBReactive的入门可能

spring-boot-starter-data-neo4j

使用Neo4j图形数据库和SpringDataNeo4j的入门可成

spring-boot-starter-data-r2dbc

使用SpringDataR2DBC的入门指南

spring-boot-starter-data-redis

利用SpringDataRedis和Lettuce客户端使用Redis键值数据存储的入门指南

spring-boot-starter-data-redis-reactive

利用SpringDataRedisReactive和Luttuce客户端使用Redis键值数据存储的入门指南

spring-boot-starter-data-rest

使用SpringDataRest和SpringMVC通过Rest公开spring数据存储库的入门课程

spring-boot-starter-freemarker

使用FreeMarker视图投建MVC网络应用程序的入门工具

spring-boot-starter-graphql

使用SpringGraphQL构建GraphQL应用程序的入门指南

spring-boot-starter-groovy-templates

使用Groovy模版视图构建MVC网络应用程序的入门指南

spring-boot-starter-hateoas

使用SpringMVC和SpringHATEOAS构建基于找媒体的RESTful网络应用程序的入门课程

spring-boot-starter-integration

使用SpringIntegration的入门指南

spring-boot-starter-jdbc

与HikariCP连接池一起使用JDBC的启动器

spring-boot-starter-jersey

使用JAX-RS和jersey构建Restful网络应用程序的入门工具。spring-boot-starter-web的替代方案

spring-boot-starter-jooq

使用JOOQ通过JDBC访问SQL数据库的入门工具。spring-boot-starter-data-jpa或spring-boot-starter-jdbc的代替品

spring-boot-starter-json

读写json的启动器

spring-boot-starter-mail

使用JavaMail和SpringFramework电子邮件发送支持的入门课程

spring-boot-starter-mustache

使用Mustache视图构建网络应用程序的入门工具

Spring-boot-starter-oauth2-authorization-server

使用Spring授权服务器功能的入门指南

Spring-boot-starter-oauth2-client

使用Spring Security的OAuth2/OpenID Connect客户端功能的入门指南

Spring-boot-starter-oauth2-resource-server

使用Spring Security的OAuth2资源服务功能的入门指南

spring-boot-starter-pulsar

为Apache Pulsar使用的spring的启动程序

spring-boot-starter-pulsar-reactive

将Spring用于Apache Pulsar Reactive的入门可成

spring-boot-start-quartz

使用任务调度程序的入门指南

spring-boot-starter-rsocket

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

spring-boot-starter-security

用于Spring Security的入门指南

spring-boot-starter-test

用于JUnit Jupiter、Hamcrest和Mockito等库测试SpringBoot应用程序的入门可成

spring-boot-starter-thymeleaf

使用Thymeleaf视图构建MVC网络应用程序的入门课程

spring-boot-starter-validation

使用Hibernate验证器进行java Bean验证的入门指南

spring-boot-starter-web

使用SpringMVC构建网络(包括Restful应用程序的入门工具。使用Tomcat作为默认嵌入式容器

spring-boot-starter-web-services

使用SpringWeb服务的入门指南

spring-boot-starter-webflux

使用SpringFramework的反应式Web支持构建WebFlux应用程序的入门工具

spring-boot-starter-websocket

使用SpringFramework的MVCWebSocket支持构建WebSocket应用程序的入门工具

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

名称

说明

spring-boot-starter-actuator

使用SpringBootActuator的入门课程,该课程提供生产就绪功能,可帮助你监控和管理应用程序

最后,SpringBoot还包括一下启动器,如果你想排除或交换特定的技术层面,可以使用这些启动器:

名称

说明

spring-boot-starter-jetty

将Jetty用作嵌入式servlet容器的启动器。spring-boot-starter-tomcat的替代方案

食品厂ng-boot-starter-log4j2

石笋Log4j2记录日志的启动器。spring-boot-starter-logging的替代方案。

spring-boot-starter-logging

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

spring-boot-starter-reactor-netty

将Reactor Netty用作嵌入式反应式HTTP服务器的启动器。

spring-boot-starter-tomcat

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

spring-boot-starster-undertow

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

要了解如何交换技术层面,请参阅如何交换网络服务器日志系统的文档

6.2 构建代码

SpringBoot的运行不需要任何特定的代码布局。不过,有一些最佳实践会有所帮助。

6.2.1 使用“默认”软件包

如果一个类没有包含package声明,则该类被视为在“默认包”中。通常不鼓励使用“默认包”,应避免使用。它会给使用@ComponentScan、@ConfigurationPropertiesScan、@EntityScan或@SpringBootApplication注解的SpringBoot应用程序带来特殊问题,因为每个jar中的每个类都会被读取。

6.2.2 Locating the Main Application Class

我们通常建议你将主应用程序类放在一个根包中,高于其他类。@SpringBootApplication注解通常放在朱磊中,它隐含地为某些项目定义了一个基础“搜索包”。例如,如果你正在编写一个JPA应用程序,@SpringBootApplication注解类的包将用于搜索@Entity项。使用根包还可以使组件扫描仅适用于你的项目。

下面列出了一个典型的布局:

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

MyApplication.java文件将声明main方法,以及基础的@SpringBootApplication方法,如下所示:

@SpringBootApplication class MyApplication fun main(args: Array<String>) { runApplication<MyApplication>(*args) }

6.3 配置类

SpringBoot偏好基于java的配置。虽然可以在XML源中使用SpringApplication,但我们通常建议主要源为单个@Configuration类。通常,定义main方法的类可以作为主要@Configuration的候选类。

6.3.1 导入其他配置类

你不必将所有的@Configration都放在一个类中。@Import注解可用于导入其他配置类。或者,也可以使用@ComponentScan自动失去所有Spring组件,包括@Configuration类。

6.3.2 导入XML配置

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

6.4 自动配置

SpringBoot自动陪吹会根据你添加的jar依赖关系自动配置的Spring应用程序。例如,如果HSQLDB位于你的classpath上,并且你没有手动配置任何数据库链接Bean,那么SpringBoot就会自动配置内存数据库。 你需要在@Configuration类中添加@EnableAutoConfiguration或@SpringBootApplication注解,选择加入自动配置。

6.4.1 逐步取代自动配置

自动配置是非侵入式的。在任何时候,你都可以开始定义自己的配置,以替换自动配置的特定部分。例如,如果你添加了自己的DataSourceBean,默认的嵌入式数据库支持就会退出。 如果需要了解当前应用的自动配置及其原因,请使用--debug开关启动应用程序。这样做可以为选定的核心日志记录器启用调试日志,并将条件报告记录到控制台。

6.4.2禁用特定自动配置类

如果你发现正在应用你不想要的特定自动配置类别,可以使用@SpringBootApplication的排除属性来禁用他们,如下例所示:

@SpringBootApplication(exclude = [DataSourceAutoConfiguration::class]) class MyApplication

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

6.4.3 自动配置软件包

自动配置包是各种自动配置功能在扫描实体和SpringData资源库等时默认查找的包。@EnableAutoConfiguration注解(直接或通过@SpringBootApplication的存在)确定了默认的自动配置包。可以使用@AutoConfigurationPackage注解配置其他软件包。

6.5 Spring Bean和依赖注入

你可以自由使用任何标准的SpringFramework技术来定义你的Bean及其注入的依赖关系。我们通常建议使用构造器注入来链接依赖关系,并使用@ComponentScan来查找Bean。 如果你按照上面的建议(将应用程序放在顶级包中)构建代码,你可以添加不带任何参数的@ComponentScan或使用隐式包含@SpringBootApplication的注解。你的所有应用程序组件(@Component、@Service、@Repository、@Controller及其他)都会自动注册为SpringBean。 下面的示例显示了一个使用构造器注入获得所需RiskAssessorBean的@Service Bean:

@Service class MyAccountService(private val riskAssessor: RiskAssessor) : AccountService

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

@Service public class MyAccountService implements AccountService { private final RiskAssessor riskAssessor; private final PrintStream out; @Autowired public MyAccountService(RiskAssessor riskAssessor) { this.riskAssessor = riskAssessor; this.out = System.out; } public MyAccountService(RiskAssessor riskAssessor, PrintStream out) { this.riskAssessor = riskAssessor; this.out = out; } // ... }

6.6 使用@SpringBootApplication注解

许多SpringBoot开发人员都希望自己的应用程序能使用自动配置、组件扫描、并能在“应用程序类”上定义额外的配置。只需使用一个@SpringBootApplication注解即可启用这三个功能:

  • EnableAutoConfiguration:启用SpringBoot的自动配置机制。

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

  • @SpringBootApplication:允许上下文中注册额外的Bean或导入额外的配置类。它是Spring标准@Configuration的代替方案,有助于在集成测试中检测配置。

// Same as @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
@SpringBootConfiguration(proxyBeanMethods = false) @EnableAutoConfiguration @Import({ SomeConfiguration.class, AnotherConfiguration.class }) public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }

在此示例中,MyApplication与其他SpringBoot应用程序一样,只是不会自动检测到@Component注释的类和@ConfigurationProperties注释的类,而是显示导入用户定义的Bean(请参阅@Import)。

6.7 运行应用程序

将应用程序打包为jar并使用嵌入式http服务器的最大优势之一是,你可以像运行其他应用程序一样运行应用程序。该示例适用于调试SpringBoot应用程序。你不需要任何特殊的集成开发环境插件或扩展。

6.7.1 从集成开发环境运行

你可以将SpringBoot应用程序作为java应用程序从集成开发环境中运行。不过,你首先需要导入你的项目。导入步骤因集成开发环境和构建系统而异。大多数IDE可以直接导入Maven项目。例如,Eclipse用户可以从File菜单中选择Import...-> Existing Maven Projects。 如果无法直接将项目导入集成开发环境,可以使用构建插件生成集成开发环境元数据。Maven包括用于Eclipse和IDEA的插件。Gradle为各种集成开发环境提供了插件。

6.7.2 作为打包应用程序运行

如果使用SpringBootMaven或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

6.7.3 使用maven插件

SpringBoot Maven插件包含一个run目标,可用于快速编译和运行应用程序。应用程刷会以爆炸形式运行,就像在集成开发环境中一样。下面的示例展示了运行SpringBoot应用程序的典型Maven命令:

mvn spring-boot:run

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

$ export MAVEN_OPTS=-Xmx1024m

6.7.4 使用gradle插件

Spring boot gradle插件还包含了一个bootRun任务,可用于以爆炸形式运行应用程序。只要应用org.springframework.boot和java插件,就会添加bootRun任务,如下示例所示:

gradle bootRun

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

export JAVA_OPTS=-Xmx1024m

6.7.5 热拔插

由于SpringBoot应用程序是纯java应用程序,因此JVM热拔插开箱即用。JVM热拔插所能替换的字节码有限。要获得更完整的解决方案,可以使用JRebel。 spring-boot-devtools模块还支持快速重启应用程序。详细请参阅热拔插“操作方法”。

6.8 开发人员工具

SpringBoot包含一组额外的工具,可让应用程序开发体验更加愉快。spring-boot-devtools模块可包含在任何项目中,以提供额外的开发时间功能。要包含devtools支持,请将模块依赖关系加到你的构建中,如一下针对Maven和Gradle的列表所示:

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies>
dependencies { developmentOnly("org.springframework.boot:spring-boot-devtools") }

6.8.1诊断类加载文件

正如“重启与重载”部分所述,重启功能是通过使用两个类加载器来实现的。对于大多数应用程序来说,这种方法效果很好。但有时也会造成类加载问题,尤其是在多模块项目中。 要诊断类加载问题是否确实由devtools及其两个类加载器引起,请尝试禁用重启。如果问题得到解决,请自定义重启类加载器,使其包含整个项目。

6.8.2 属性默认值

SpringBoot支持的一些库使用缓存来提高性能。例如,模版引擎会缓存以编译的模版,以避免重复解析模版文件。此外,SpringMVC还能再提供静态资源时为响应添加http缓存标头。 虽然缓存在生产中非常有益,但在开发过程中却可能适得其反,让你无法看到刚刚在应用程序中做出的更改。因此,spring-boot-devtools默认禁用缓存选项。 缓存选项通常通过application.properties文件中的设置进行配置。例如Thymeleaf提供了spring.thymeleaf.cache属性。spring-boot-devtools模块会自动应用合理的开发时配置,而无需手动设置这些属性。

名称

默认值

server.error.include-binding-errors

always

server.error.include-message

always

server.error.include-stacktrace

always

server.servlet.jsp.int-parameters.development

true

server.servlet.session.persistent

true

spring.docker.compose.readiness.wait

only-if-started

spring.freemarker.cache

false

spring.graphql.graphiql.enabled

true

spring.groovy.template.cache

false

spring.h2.console.enabled

true

spring.mustache.servlet.cache

false

spring.mvc.log-resolved-exception

true

spring.reactor.netty.shutdown-quiet-period

0s

spring.template.provider.cache

false

spring.thymeleaf.cache

false

spring.web.resources.cache.period

0

spring.web.resources.chain.cache

false

由于你在开发SpringMVC和spring WebFlux应用程序时需要更多有关web请求的信息,开发工具建议你启用debug日志组web的日志记录。这奖提供有关传入请求,处理程序,响应结果和其他详细信息。如果希望记录所有请求的详细信息(包括潜在的敏感信息),可以打开spring.mvc.log-request-details或spring.codec.log-request-details配置属性。

6.8.3 自动重启

使用spring-boot-devtools的应用程序会在类路径上的文件发生变化时自动重新启动。在集成开发环境中工作时,这可能是一项非常有用的功能,因为它能为代码更改提供非常快速的反馈回路。默认情况下,classpath上指向目录的任何条目都会收到监控,以防发生变化。请注意,某些资源(如静态资产和视图模版)不需要重新启动应用程序。

触发重启

由于DevTools会监控类路径资源,因此触发重启唯一的方法就是更新类路径。无论你使用的是集成开发环境还是构建环境,都必须重新编译修改后的文件才能触发重启。更新类路径的方式取决于使用的工具。

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

  • 在Intellij Idea 中,构建项目(Build +->+Build Project)具有相同的效果。

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

重新启动和重新加载

SpringBoot提供的重启技术通过使用两个类加载器来工作。不会更改的类(例如,来自第三方jar的类)会加载到基础类加载器中。正在开发的类会加载到重启类加载器中。重启应用程序时,重启类加载器会被丢弃,然后创建一个新的类加载器。这中方法意味着应用程序重启通常比“冷启动”要快得多,因为基类加载器已经可用并已填充。 如果你发现重启对你的应用程序来说不够快,或者你遇到类加载问题,你可以考虑重载技术,比如ZeroTurnaround的Jrebel。这些技术的工作原理是在加载雷士对其进行重写,使其更易于重载。

记录状态评估中的变化

默认情况下,每次重新启动应用程序时,都会记录一份显示条件评估delta的报告。在你进行添加或删除Bean以及设置配置属性等更改时,该报告会显示应用程序自动配置的更改情况。 要禁用报告记录,请设置以下属性:

spring: devtools: restart: log-condition-evaluation-delta: false
Excluding Resources

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

spring: devtools: restart: exclude: "statics/**,public/**"
观察其他路径

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

禁用重启

如果你不想使用重启功能,可以使用spring.devtools.restart.enabled属性来禁用它。在大多数情况下,你可以在application.properties中设置该属性(这样做仍会初始化重启类加载器,单不会关注文件更改)。 如果需要完全禁用重启支持(例如,因为它无法与特定库配合使用),则需要在调用SpringApplication.run(...)之前将spring.detools.restart.enabled System属性设置为false,如下例所示:

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

如果你使用的集成开发环境会持续编译已更改的文件,那么你可能更希望只在特定时间触发重启。要做到这一点,可以使用“触发文件”,这是一个特殊的文件,必须在实际触发重启检查时进行修改。

要使用触发器文件,请将spring.devtools.restart.trigger-file属性设置为触发文件的名称(不包括任何路径)。触发器文件必须出现在类路径上的某个位置。 例如,如果你有一个结构如下的项目:

src +- main +- resources +- .reloadtrigger

那么,你的trigger-file属性将是

spring: devtools: restart: trigger-file: ".reloadtrigger"

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

有些集成开发环境具有免于手动更新触发器文件的功能。Eclipse Spring Tools和IntelliJ 都支持这种功能。使用SpringTools,你可以使用控制台视图中的“重新加载”按钮(只要你的trigger-file被命名为.reloadtrigger即可)。对于IntelliJ Idea,你可以按照其文档中的说明进行操作。

自定义重启类加载器

如前文“重启与重载”部分所述,重启功能是通过使用两个类加载器实现的。如果这导致了问题,你可能需要自定义那个类加载器加载那些内容。 默认情况下,集成开发环境中任何打开的项目都会使用“restart”类加载器加载,而任何常规的.jar文件都会使用“base”类加载器加载。使用mvn spring-boot:run或gradle bootRun时也是如此:包含@SpringBootApplication的项目将使用“restart”类加载器加载,而其他项目将使用“base”类加载器加载。 你可以通过创建类META-INF/spring-devtools.properties文件,只是SpringBoot使用不同的类加载器加载项目的部分内容。spring-devtools.properties文件可包含以restart.exclude和restart.include为前缀的属性。include元素是应上拉到“重启”类加载器的项目,而exclude元素是应下推到“基本”类加载器的项目。该属性的值是应用于classpath的regex模式,如下例所示:

restart: exclude: companycommonlibs: "/mycorp-common-[\\w\\d-\\.]+\\.jar" include: projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
已知限制

对于使用标准ObjectInputStream反序列化的对象,重新欧功能不能很好地发挥作用。如果需要反序列化数据,则可能需要将Spring的ConfigurableObjectInputStream与Thread.currentThread().getContextClassLoader()结合使用。 遗憾的是,一些第三方库在进行反序列化时没有考虑上下文类加载器。如果发现此类问题,需要向原作者申请修复。

6.8.4 实时重载

spring-boot-devtools模块包含一个嵌入式LiveReload服务器,可用于在资源发生变化时触发浏览器刷新。LiveReload浏览器扩展可免费用于Chrome、Firefox和Safari。你可以在所选浏览器市场或商店中搜索“LiveReload",找到这些扩展。 如果不想在运行应用程序时启动LiveReload服务器,可以将spring.devtools.livereload.enabled属性设置为false。

6.8.5 全局设置

在$HOME/.config/spring-boot目录中添加一下任意文件,即可配置全局devtools设置:

  1. spring-boot-devtools.properties

  2. spring-boot-devtools.yaml

  3. spring-boot-devtools.yml

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

spring: devtools: restart: trigger-file: ".reloadtrigger"

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

配置文件系统监视器

FileSystemWatcher的工作原理是以一定的时间建个轮询类的更改,然后等待预定义的静默期,以确保不在有更改。由于SpringBoot完全依赖集成开发环境来编译文件并将其复制到SpringBoot可以读取的位置,因此你可能会发现,当devtools重新启动应用程序时,有时某些更改无法反映出来。如果你经常发现此类问题,请尝试将spring.devtools.restart.poll-interval和spring.devtools.restart.quiet-periodd参数增加到适合开发环境的值:

spring: devtools: restart: poll-interval: "2s" quiet-period: "1s"

现在,每2秒钟就会轮询一次受监控的类路径目录是否有变化,并保持1s的静默期,以确保没有其他类变化。

6.8.6 远程应用程序

SpringBoot开发人员工具不仅限于本地开发。你还可以再远程运行应用程序时使用多项功能。远程支持是选择性的,因为启用它可能存在安全风险。只有在受信任的网络上运行或使用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支持由两部分组成:一个介绍链接的服务器端端点和一个在集成开发环境中运行的客户端程序。当设置spring.devtools.remote.secret属性时,服务器组件将自动启用。客户端组件必须手动启动。

运行远程客户端的应用程序

远程客户端应用程序可在集成开发环境中运行。运行org.springframework.boot.devtools.RemoteSpringApplication时,需要使用与所链接的远程项目相同的类路径。该应用程序的唯一必要参数是它所链接的远程URL。 例如,如果你使用的是Eclipse或SpringTools,并且你有一个名为my-app的项目已部署到CloudFoundry,你将执行一下操作:

  • 从Run菜单中选择Run Configurations...

  • 创建新的Java Application 启动配置。

  • 浏览my-app项目。

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

  • 在Program arguments(或任何远程URL)中添加https://myapp.cfapps.io

运行中的远程客户端可能与下面的列表相似:

. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ ___ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | | _ \___ _ __ ___| |_ ___ \ \ \ \ \\/ ___)| |_)| | | | | || (_| []::::::[] / -_) ' \/ _ \ _/ -_) ) ) ) ) ' |____| .__|_| |_|_| |_\__, | |_|_\___|_|_|_\___/\__\___|/ / / / =========|_|==============|___/===================================/_/_/_/ :: Spring Boot Remote :: (v3.2.2) 2024-01-19T06:35:46.770Z INFO 37336 --- [ main] o.s.b.devtools.RemoteSpringApplication : Starting RemoteSpringApplication v3.2.2 using Java 17.0.9 with PID 37336 (/Users/myuser/.m2/repository/org/springframework/boot/spring-boot-devtools/3.2.2/spring-boot-devtools-3.2.2.jar started by myuser in /opt/apps/) 2024-01-19T06:35:46.776Z INFO 37336 --- [ main] o.s.b.devtools.RemoteSpringApplication : No active profile set, falling back to 1 default profile: "default" 2024-01-19T06:35:47.205Z INFO 37336 --- [ main] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 2024-01-19T06:35:47.252Z INFO 37336 --- [ main] o.s.b.devtools.RemoteSpringApplication : Started RemoteSpringApplication in 1.025 seconds (process running for 1.443)
远程更新

远程客户端以与本地重启相同的方式监控应用程序类路径的变化。任何更新的资源都会推送到远程应用程序,并(在需要时)触发重启。如果你迭代的功能使用的是本地没有的云服务,这将很有帮助。一般来说,远程更新和重启比完整的重建和部署周期要快得多。 在开发速度较慢的环境中,可能会出现静默期不够的情况,类的更改可能会分成几批进行。第一批类更改上传后,服务器会重启。由于服务器正在重启,下一批更改无法发送到应用程序。 这种情况通常表现为RemoteSpringApplication日志中出现警告,提示无法上传某些类,并随之重试。单它可能导致应用程序代码不一致,以及在上传第一批更改后无法重新启动。如果你经常发现此类问题,请尝试将spring.devtools.restart.poll-interval和spring.devtools.restart.quiet-period参数增加到适合唱开发环境的值。有关配置这些属性的信息,请参阅“配置文件系统监视器”部分。

6.9 为生产打包应用程序

可执行jar可用于生产部署。由于他们是独立的,因此非常适合基于云的部署。 对于其他“生产就绪”功能,如健康、审计和度量REST或JMX端点,请考虑添加spring-boot-actuator。有关详细信息,请参阅生产就绪功能。

6.10 下一步阅读

现在,你应该了解了如何是常用SpringBoot以及应该遵循的一些最佳实践。现在,你可以继续深入了解SpringBoot的具体功能,也可以调到前面阅读SpringBoot的“生产就绪”方面的内容。

7. 核心功能

本节深入介绍SpringBoot的详细信息。在这里,你可以了解可能要使用和定制的关键功能。如果你还没有阅读“入门”和使用SpringBoot进行开发“这两节内容,不妨先阅读这两节内容,以便对基础知识有一个很好的了解。

7.1 SpringApplication

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

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

当应用程序启动时,你应该会看到与下面类似的输出:

. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.2.2) 2024-01-19T06:35:48.282Z INFO 37440 --- [ main] o.s.b.d.f.logexample.MyApplication : Starting MyApplication using Java 17.0.9 with PID 37440 (/opt/apps/myapp.jar started by myuser in /opt/apps/) 2024-01-19T06:35:48.288Z INFO 37440 --- [ main] o.s.b.d.f.logexample.MyApplication : No active profile set, falling back to 1 default profile: "default" 2024-01-19T06:35:49.911Z INFO 37440 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http) 2024-01-19T06:35:49.932Z INFO 37440 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2024-01-19T06:35:49.932Z INFO 37440 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.18] 2024-01-19T06:35:50.025Z INFO 37440 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2024-01-19T06:35:50.027Z INFO 37440 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1662 ms 2024-01-19T06:35:50.548Z INFO 37440 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '' 2024-01-19T06:35:50.572Z INFO 37440 --- [ main] o.s.b.d.f.logexample.MyApplication : Started MyApplication in 2.921 seconds (process running for 3.301)

默认情况下,会显示INFO日志信息,包括一下相关的启动详情信息,如启动应用程序的用户。如果需要INFO以外的日志级别,可以按照日志级别中的说明进行设置。应用程序版本由主应用程序类包中的实现版本决定的。可以通过将spring.main.log-startup-info设置为false关闭启动信息日志记录。这也将关闭应用程序活动配置文件的日志记录。

7.1.1 启动失败

如果你的应用程序无法启动,注册FailureAnalyzers将有机会提供专门的错误消息和解决问题的具体操作。例如,如果你在端口8080上启动网络应用程序,而该端口已在使用中,你应该会看到与下面类似的消息:

*************************** APPLICATION FAILED TO START *************************** Description: Embedded servlet container failed to start. Port 8080 was already in use. Action: Identify and stop the process that is listening on port 8080 or configure this application to listen on another port.

如果没有故障分析器能够处理异常,你仍然可以显示完整的条件报告,以便更好地了解出错的原因。为此,你需要启动debug属性或为org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener启动DEBUG日志。 例如,如果你使用java -jar运行应用程序,则可以按如下方式启用debug属性:

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

7.1.2 懒加载

SpringApplication允许对应用程序进行懒加载。启动懒加载后,将在需要时而不是在应用程序启动时创建Bean。因此,启用懒加载初始化可以缩短应用程序的启动时间。在网络应用程序中,启用懒加载将导致许多与网络相关的Bean在收到Http请求之前不会被初始化。 懒加载的一个缺点是,他可能会延迟发现应用程序的问题。如果对一个配置错误的Bean进行懒加载,那么在启动过程中就不会再发生故障,只有在初始化Bean时问题才会显现出来。此外,还必须注意确保JVM有足够的内存来容纳应用程序的所有Bean,而不仅仅是那些启动过程中初始化的Bean。因此,默认情况下不会启用懒加载,建议在启用懒加载之前对JVM的堆大小进行微调。 可以使用SpringApplicationBuilder中的lazyInitialization方法或SpringApplication中的setLazyInitialization方法以变成方式启用懒加载。或者,也可以使用spring.main.lazy-initialization属性启用懒加载,如下例所示:

spring: main: lazy-initialization: true

7.1.3 自定义banner

可以通过类路径中添加banner.txt文件,或将spring.banner.location属性设置为该文件的位置,从而更改启动时打印的横幅。如果文件的编码不是UTF-8,则可以设置spring.banner.charset。 在banner.txt文件中,你可以使用Environment中的任何键值以及一下任何占位符:

可变

Description

$

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

$

应用程序的版本号,在MANIFEST.MF中声明,格式为显示格式(用括号包围,前缀为v)。例如(V1.0)。

$

你使用的SpringBoot版本。例如3.2.4

$

你正在使用的SpringBoot版本。例如3.2.4

{AnsiColor.NAME), (或 ,${AnsiStyle.NAME)

其中,NAME是ANSI转移码的名称。详见AnsiPropertySource

$

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

你还可以使用spring.main.banner-mode属性来决定是否在System.out上打印banner(console)、发送到配置的日志记录器(log)或不打印(off)。 打印的横幅作为单利Bean注册,名称如下:SpringBootBanner。

7.1.4.定制SpringApplication

如果SpringApplication默认设置不符合你的口味,你可以创建一个本地实例并对其进行自定义。例如,如果关闭banner,可以这样写

@SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(MyApplication.class); application.setBannerMode(Banner.Mode.OFF); application.run(args); } }

也可以通过使用application.properties文件来配置SpringApplication。有关详情,请参阅外部化配置。 有关配置选下来的完整列表,请参阅SpringApplication Javadoc。

7.1.5 流畅生成器API

如果你需要构建ApplicationContext层次结构(具有父/子关系的多个上下文)。或者如果你更喜欢使用流畅的构建器API,则可以使用SpringApplicationBuilder Framework2.0。 SpringApplicationBuilder可让你将多个方法调用串联起来,其中包括parent和child方法,这些方法可让你创建一个层次结构,如下利所示:

new SpringApplicationBuilder().sources(Parent.class) .child(Application.class) .bannerMode(Banner.Mode.OFF) .run(args);

7.1.6 应用程序的可用性

在平台部署应用程序时,应用程序可以使用Kubernetes Pobes等基础架构向平台提供有关其可用性的信息。SpringBoot包对常用“liveness”和“readiness”可用性状态的开箱即用支持。如果你使用的是SpringBoot的“actuator”支持,那么这些状态就会作为健康端点组暴露出来。 此外,你还可以通过在自己的Bean中注入ApplicationAvailability接口获取可用行的状态。

Liveness State 有效状态

应用程序的“活泼”状态说明其内部状态是否允许其正常工作,或在当前失败的情况下自行恢复。坏掉的“Liveness”状态意味着应用程序处于无法恢复的状态,基础架构应重新启动应用程序。

SPringboot应用程序的内部状态主要由SpringApplicationContext表示。如果应用程序上下文已成功启动,则SPringboot认为应用程序处于有效状态。一旦上下被刷新,应用程序即被视为已激活,请参阅SPringBoot应用程序生命周期和相关应用程序事件。

Readiness Sate 装备状态

应用程序的“就绪”状态说明应用程序是否已准备好处理流量。如果“就绪”状态失败,平台就会认为暂时不应将流量路由到应用程序。这种情况通常发生在启动过程中,即正在处理CommandLineRunner和ApplicationRunner组件时,或者在应用程序认为自己忙于处理额外流量的任何时候。 一旦应用程序和命令行运行程序被调用,应用程序被视为准备就绪,请参阅SpringBoot应用程序生命周期和相关应用程序事件。

Managing the Application Availability Sate管理应用程序可用性状态

应用程序组件可以通过注入ApplicationAvailability接口并调用其中的方法,随时检索其中的可用性状态。更常见的情况是,应用程序希望监听状态更新或更新应用程序的状态。 例如,我们可以将应用程序的“就绪”状态导出到文件中,这样kubernetes的“执行探测器”就可以查看该文件。

@Component public class MyReadinessStateExporter { @EventListener public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) { switch (event.getState()) { case ACCEPTING_TRAFFIC -> { // create file /tmp/healthy } case REFUSING_TRAFFIC -> { // remove file /tmp/healthy } } } }

当应用程序发生故障而无法回复时,我们还可以更新应用程序的状态的:

@Component public class MyLocalCacheVerifier { private final ApplicationEventPublisher eventPublisher; public MyLocalCacheVerifier(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } public void checkLocalCache() { try { // ... } catch (CacheCompletelyBrokenException ex) { AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN); } } }

SpringBoot通过Actuator Health Endpoints为“Liveness”和“Readiness”提供了Kubernetes HTTP探测器。有关在Kubernetes上部署SpringBoot应用程序的更多指导,请参阅专门章节。

7.1.7 Application Events and Listeners应用程序时间和监听器

除了常规Spring Framework事件(如ContextRefreshedEvent)外,SpringApplication还会发送一些额外的应用程序事件。

应用程序事件在运行过程中按以下顺序发送:

  1. ApplicationStartingEvent在运行开始时发送,单在任何处理之前发送,监听器和初始化器的注册除外。

  2. 当上下文中使用的Environment已知,但上下文尚未创建时,将发送ApplicationEnvironmentPreparedEvent。

  3. 当ApplicationContext已准备就绪且ApplicationContextInitializers已被调用,但尚未加载任何Bean定义时,将发送ApplicationContextInitializedEvent消息。

  4. ApplicationPreparedEvent会在刷新开始前但在加载Bean定义后发送。

  5. ApplicationStartedEvent会在上下文刷新后、调用任何应用程序和命令行运行程序前发送。

  6. 紧接着发送 AvailabilityChangeEvent 和 LivenessState.CORRECT ,以表示应用程序被认为是实时的。

  7. 在调用任何应用程序和命令行运行程序后,将发送ApplicationReadyEvent。

  8. 紧接着发送 AvailabilityChangeEvent 和 ReadinessState.ACCEPTING_TRAFFIC ,表示应用程序已准备好为请求提供服务。

  9. 如果启动时出现异常,将发送ApplicationFailedEvent消息。

上述列表仅包括与SpringApplication关联的SpringApplicationEvent。除此之外,以下时间也会在ApplicationPreparedEvent之后和ApplicationStartedEvent之前发布:

  • WebServerInitializedEvent在WebServer就绪后发送。ServletWebServerInitializedEvent和ReactiveWebServerInitializedEvent分别是servlet和反应式变体。

  • 刷新ApplicationContext时,将发送ContextRefreshedEvent消息。

应用程序事件是通过SpringFramework的事件发布机制发送的。该机制的部分功能是确保子上下文中的监听器发布的时间也会向任何祖先上下文中的监听器发布。因此,如果你的应用程序使用SpringApplication实例的层次结构,则监听器可能会收到同一个类型应用程序事件的多个实例。 为使你的监听器能够区分其上下文的事件和后代上下文的事件,监听器应请求注入其应用程序上下文,然后注入的上下文与事件的上下文进行比较。可以通过实施ApplicationContextAware来注入上下文,如果监听器是一个Bean,则可以使用@Autowired来注入上下文。

7.1.8 Web Environment 网络环境

SpringApplication视图代表你创建正确类型的ApplicationContext。用于确定WebApplicationType的算法如下:

  • 如果存在SpringMVC,则使用AnnotationConfigServletWebServerApplicationContext

  • 如果不存在SpringMVC而存在SpringWebFlux,则使用AnnotationConfigReactiveWebServerApplicationContext

  • 否则,使用AnnotationConfigApplicationContext

这意味着,如果你在同一应用程序中使用SpringMVC和Spring WebFlux的新WebClient,将默认使用SpringMVC。你可以通过调用setWebApplicationType(WebApplicationType)轻松覆盖。 还可以通过调用setApplicationContextFactory(...)来完全控制所使用的ApplicationContext类型。

7.1.9 Accessing Application Arguments访问应用程序参数

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

import java.util.List; import org.springframework.boot.ApplicationArguments; import org.springframework.stereotype.Component; @Component public class MyBean { public MyBean(ApplicationArguments args) { boolean debug = args.containsOption("debug"); List<String> files = args.getNonOptionArgs(); if (debug) { System.out.println(files); } // if run with "--debug logfile.txt" prints ["logfile.txt"] } }

7.1.10 Using the ApplicationRunner or CommandLineRunner使用应用程序运行程序或命令行运行程序

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

CommandLineRunner接口以字符串数组的形式访问应用程序参数,而ApplicationRunner则使用前面讨论过的ApplicationArguments接口。下面的实例显示了带有run方法的CommandLineRunner:

@Component public class MyCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) { // Do something... } }

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

7.1.11Application Exit 应用程序退出

每个SpringApplication都会向JVM注册一个关闭钩子,以确保ApplicationContext在退出时优雅地关。可以使用所有标准的Spring生命周期回调(如DisposableBean接口或@PreDestroy注解)。 此外,如果希望在调用SpringApplication.exit()时返回特定的退出代码,Bean可以实现org.springframework.boot.ExitCodeGenerator接口。然后,可将此退出代码传递给System.exit()以作为状态代码返回,如下例所示:

@SpringBootApplication public class MyApplication { @Bean public ExitCodeGenerator exitCodeGenerator() { return () -> 42; } public static void main(String[] args) { System.exit(SpringApplication.exit(SpringApplication.run(MyApplication.class, args))); } }

此外,ExitCodeGenerator接口可由异常时间。遇到此类异常时,SpringBoot会返回由实现的getExitCode()方法提供的退出代码。 如果由多个ExitCodeGenerator,则使用第一个生成的非零退出代码。要控制生成器的调用顺序,可额外实现org.springframework.core.Ordered接口或使用org.springframework.core.annotation.Order注解。

7.1.12 Admin Features管理功能

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

7.1.13 Application Startup tracking 应用程序启动跟踪

在应用程序启动期间,SpringApplication和ApplicationContext会执行许多与应用程序生命周期、Bean生命周期甚至是处理应用程序事件相关的任务。通过ApplicationStartup,SpringFramework允许你使用StartupStep对象追踪应用程序启动顺序。手机这些数据可用于剖析目的,或只是为了更好了解应用程序的启动过程。 在设置SpringApplication实例时,你可以选择ApplicationStartup实现。例如要使用BufferingApplicationStartup时,可以这样写

@SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(MyApplication.class); application.setApplicationStartup(new BufferingApplicationStartup(2048)); application.run(args); } }

第一个可用的实现FlightRecorderApplicationStartup由SpringFramework提供。你将spring特有的启动事件添加到Java Flight Recorder会话中,用于剖析应用程序,并将其Spring上下文生命周期与JVM事件(如分配、GC、类加载。。。。)关联起来。配置完成后,启用Flight Recorder运行应用程序即可记录数据:

java -xx:StartFlightRecording:filename=recording.jfr,duration=10s -jar demo.jar

SpringBoot随附BufferingApplicationStartup变体;该实现用于缓冲启动步骤,并将其排入外部度量系统。应用程序可以在任何组件中请求BufferingApplicationStartup类型的Bean。 SpringBoot还可以配置为暴露startup端点,以JSON文档的形式提供此信息。

7.1.14 Virtual threads 虚拟线程

如果运行的是java21或更高版本,则可以通过将属性spring.threads.virtual.enabled设置为true来启用虚拟线程。 在为你的应用程序打开此选项之前,你应该考虑阅读java虚拟线程官方文档。在某些情况下,应用程序可能会因为“钉住的虚拟线程”而降低吞吐量;本页还介绍了如何使用JDK Flight Recorder或jcmd CLI检测此类情况。

7.2 Externalized Configuration 外部化配置

SpringBoot允许你将配置外部化,这样你就可以在不同的环境中使用相同的应用程序代码。你可以使用各种外部配置源,包括java属性文件、yaml文件、环境变量和命令行参数。 属性值可以通过@Value注解直接注入到Bean中,也可以通过Spring的Environment抽象访问,或通过@ConfigurationProperties绑定到结构化对象。 SpringBoot使用一种非常特殊的PropertySource顺序,旨在允许对值进行合理的覆盖。后面的属性源可以覆盖前面属性源中定义的值。源按一下顺序考虑:

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

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

  3. 配置数据(如application.properties文件)。

  4. 仅在random.*中具有属性的RandomValuePropertySource。

  5. 操作系统环境变量。

  6. java系统属性(System.getProperteis())。

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

  8. ServletContext初始参数

  9. ServletConfig初始参数。

  10. 来自SPRING_APPLICATION_JSON的属性(嵌入到环境变量或系统属性中的内联JSON)。

  11. 命令行参数

  12. Properties属性。在@SpringBootTest和测试注释上可用,用于测试应用程序的特定片段。

  13. 测试中的@DynmicPropertySource注解

  14. @TestPropertySource测试注解。

  15. 当devtools处于活动状态时,$HOME/.config/spring-boot目录中的Devtools全局设置属性。

配置数据文件的审议顺序如下:

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

  2. 打包在jar中的特定配置文件应用程序属性(application-.properties和YAML变体。

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

  4. 打包 jar 之外的特定配置文件应用程序属性( application-.properties 和 YAML 变体)。

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

import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class MyBean { @Value("${name}") private String name; // ... }

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

7.2.1 Accessing Command Line Properties访问命令行属性

默认情况下,SpringApplication会将任何命令行选项参数(即以 -- 开头的参数,如--server.port=9000)转换为property并添加到Spring Environment中。如前所述,命令行属性总是优先于基于文件的属性源。 如果不想在Environment中添加命令行属性,可以使用SpringApplication.setAddCommandLineProperties(false)禁用他们。

7.2.2 JSON Application Properties应用程序属性

环境变量和系统属性通常有一些限制,意味着某些属性名称不能使用。为了帮助解决这个问题,SpringBoot允许你将一组属性编码为单一的JSON结构。 应用程序启动时,任何spring.application.json或SPRING_APPLICATION_JSON属性都将被解析并添加到Environment中。 例如,SPRING_APPLICATION_JSON属性可以作为环境变量的UN*X shell的命令行中提供:

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

在前面的实例中,my.name=test最后出现在Spring Environment中。 同样的JSON也可以作为系统属性提供:

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

或者,你也可以使用命令行参数提供JSON:

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

如果要部署到经典应用服务器,也可以使用名为java:comp/env/spring.application.json的JNDI变量。

7.2.3 External Application Properties外部应用程序属性

SpringBoot将在应用程序启动时自动从以下位置查找并加载application.properties和application.yaml文件:

  1. From the classpath从类路径 a.The classpath root 类路径跟目录 b.The classpath /config package 类路径 /config 包

  2. From the current directory 从当前目录 a. the current directory 当前目录 b. the config / subdirectory in the current directory当前目录中的config/子目录 c. immediate child directories of the config / subdirectory config/ 子目录的直接子目录

列表按优先级顺序(较低项目的值优先于较早项目的值)。加载文件中的文件会以PropertySource的形式添加到Spring Environment中。 如果不喜欢application作为配置文件名,可以通过指定spring.config.name环境属性来切换到其他文件名。例如,要查找myproject.properties和myproject.yaml文件,可以按一下方式运行应用程序:

java -jar myproject.jar --srping.config.name=myproject

你也可以通过spring.config.location环境属性来引用明确的位置。该属性接受一个以逗号分隔的列表,其中包含一个或多个要检查的位置。 下面的示例显示了如何指定两个不同的文件:

java -jar myproject.jar --spring.config.location=\ optional:classpath:/default.properties,\ optional:classpath:/override.properties

如果spring.config.location包含目录(而不是文件),则应以/结尾。运行时,在加载这些目录之前,他们将被附加上由spring.config.name生成的名称。在spring.config.location中指定的文件将被直接导入。

在大多数情况下,你添加的每个spring.config.location项都将引用单个文件或目录。位置为按照定义的顺序进行处理,后面的位置可以覆盖前面位置的值。 如果你有复杂的位置设置,并且使用了特定于配置文件的配置文件,你可能需要提供进一步的提示,以便SpringBoot知道应该如何对它们进行分组。位置组是在同一级别考虑的位置的集合。例如,你可能想分组所有classpath位置,然后是所有外部位置。位置组内的项目应以;分隔。更多详情,请参阅“配置文件特定文件”部分的示例。 使用spring.config.location配置的位置将取代默认位置。例如,如果spring.config.location的配置值optional:classpath:/custom-config/,optional:file:./custom-config/,则考虑的整套位置为:

  1. optional:classpath:custom-config/

  2. optional:file:./custom-config/

如果你希望添加其他位置,而不是替换它们,可以使用spring.config.additional-location。从附加位置加载的属性可以覆盖默认位置中的属性。例如,如果spring.config.additional-location的配置值为optional:classpath:/custom-config/,option:file:./custom-config/,则考虑的完整位置集:

  1. optional:classpath:/,optional:classpath:/config/

  2. optional:file:./;optional:file:./config/;optional:file:./config/*/

  3. optional:classpath:custom-config/

  4. optional:file:./custom-config/

这种搜索排序方式可让你在一颗配置文件中指定默认值,然后在另一个配置文件中选择性覆盖这些值。你可以在其中一个默认位置的application.properties(或使用spring.config.name选择的任何其他变量值)中为你的应用程序提供默认值。这些默认值可以在运行时用位于自定义位置之一的不同文件覆盖。

Optional Locations可选地点

默认情况下,当指定的配置数据位置不存在时,SpringBoot将抛出ConfigDataLocationNotFoundException并导致应用程序无法启动。 如果你想指定一个位置,但又不介意它并不总是存在,可以使用optional:前缀。你可以抽到spring.config.location和spring.config.additional-location属性以及spring.config.import声明中使用这个前缀。 例如,spring.config.import值为optional:file:./myconfig.properties时,即使缺少myconfig.properties文件,应用程序也能启动。 如果要忽略所有COnfigDataLocationNotFoundExceptions并始终继续启动应用程序,可以使用spring.config.on-not-found属性。使用SpringApplication.setDefaultProperties(...)或系统/环境变量将值设置我ignore。

Wildcard Locations 通配符位置

如果配置文件位置的最后用车路径段包含字符,则视为通配符位置。通配符会在加载配置时展开,因此也会检查直接子目录。通配符位置在kubernetes等有多个配置属性来源的环境中特别有用。 例如,如果你有一些Redis配置和一些mysql配置,你可能希望将这两项配置分开,同时要求这两项配置都存在于application.properties文件中。这可能会导致两个独立的applicaton.properties文件被挂载到不同的位置,例如/config/redis/application.properties和/config/mysql/application.properties。在这种情况下,如果通配符位置为config/ /,则两个文件都会被处理。 默认情况下,SpringBoot将config/*/包含在默认搜索位置中。这意味着将搜索jar以外/config目录的所有子目录。 你可以通过spring.config.location和spring.config.additional-location属性使用通配符位置。

Profile Specific Files配置文件专用文件

出了application属性文件外,SpringBoot还会尝试使用命名约定application-加载特定于配置文件的文件。例如,如果你的应用程序激活了命名为prod的配置文件并使用YAML文件,那么application.yaml和application-prod.yaml都将被考虑。 配置文件特定属性的加载位置和标准applicaton.properties相同,配置文件特定文件总是优先于非特定文件。如果指定了多个配置文件,则采用后胜策略。例如,如果prod,live配置文件有spring.profiles.active属性指定,则application-prod.properties中的值可被application-live.properties中的值覆盖。

例如,继续上面的prod,live示例,我们可能会有以下文件:

/cfg application-live.properties /ext application-live.properties application-prod.properties

当spring.config.location为classpath:/cfg/,classpath:/ext/时,我们会先处理所有/cfg文件,然后再处理所有/ext文件:

  1. /cfg/application-live.properties

  2. /ext/application-prod.properties

  3. /ext/application-live.properties

当我们使用classpath:/cfg/;classpath:/ext/时(使用;分隔符),我们会在同一级别处理/cfg和/ext:

  1. /ext/application-prod.properties

  2. /cfg/application-live.properties

  3. /ext/application-live.properties

Environment有一组默认配置文件(默认情况下为[default]),如果没有设置激活的配置文件,就会使用这些配置文件。换句话说,如果没有明确激活配置文件,则会考虑使用application-default中的属性。

Importing Additional Data导入其他数据

应用程序属性可使用spring.config.import属性从其他位置导入更多配置数据。导入数据会在发现时进行处理,并被视为紧接在声明导入数据的文件下方插入的附加文件。 例如,你的classpath application.properties文件中可能包含一下内容:

spring: application: name: "myapp" config: import: "optional:file:./dev.properties"

这将触发当前目录中dev.properties文件的导入(如果存在此类文件)。导入的dev.properties中的值将优先于触发导入的文件。在上例中,dev.properties可以将spring.application.name重新定义为不同的值。 无论导入声明多少次,都只能导入一次。导入的properties/yaml文件的单个文档中定义的顺序并重要。例如,下面的两个实例产生的结果是一样的。

spring: config: import: "my.properties" my: property: "value"
my: property: "value" spring: config: import: "my.properties"

在上述两个示例中,来自my.properties文件的值将优于触发导入的文件。 在一颗spring.config.import键下可以指定多个位置。位置将按其定义的顺序进行处理,较晚的导入优先。

Importing Extensionless Files 导入无扩展文件

某些云平台无法为卷加载的文件添加文件扩展名。要导入这些扩展名的文件,需要给SpringBoot一个提示,以便它知道如何加载这些文件。为此,你可以扩展名提示放在方括号中。 例如,假设你有一个/etc/config/myconfig文件,希望以yaml的形式导入。你可以使用一下方法从application.properties中导入该文件。

spring: config: import: "file:/etc/config/myconfig[.yaml]"
Using Configuration Trees使用配置树

在云平台(如Kubernetes)上运行应用程序时,你经常需要读取平台提供的配置值。为此目的使用环境变量的情况并不少见,但这样做可能会有弊端,尤其是当配置值需要保密时。 作为环境变量的替代方案,许多云平台现在都允许你将配置映射到挂载的数据卷中。例如,Kubenetes可以卷挂载ConfigMaps和Secrets。 有两种常见的音量安装模式可选择:

  1. 单个文件包含一整套属性(通常写成YAML)。

  2. 多个文件被写入一个目录树,文件名成为键,内容成为值。

对于第一种情况,你可以如上所述使用spring.config.import直接导入YAML或属性文件。对于第二种情况,你需要使用configtree:前缀,以便springboot知道它需要将所有文件作为属性公开。 举个例子,假设Kubernetes挂载了以下卷:

etc/ config/ myapp/ username password

username文件的内容将是一颗配置值,而password文件的内容将是一颗秘密。 要导入这些属性,可以在application.properties或application.yaml文件中添加以下内容:

spring: config: import: "optional:configtree:/etc/config/"

然后,你可以通过常规方法或注入Environment中的myapp.username和myapp.password属性。

如果要从同一父文件夹导入多个配置树,可以使用通配符快捷方式。任何以/*/结尾的configtree:位置都将以配置树的形式导入所有直接子文件夹。与非通配符导入一样,每个配置树下的文件夹和文件名构成了属性名。 例如,给定以下卷:

etc/ config/ dbconfig/ db/ username password myconfig/ mq/ username password

你可以使用configtree:/etc/config/*/作为导入位置:

spring: config: import: "optional:configtree:/etc/config/*/"

这将添加db.username,db.password,mq.username和mq.password属性。

配置树也可用于Docker。当Docker swarm服务获准访问某个秘钥时,该秘钥就会被挂载到容器中。例如,如果名为db.password的秘密被挂载到位置/run/secrets/上,则可以使用一下命令将db.password提供给spring环境:

spring: config: import: "optional:configtree:/run/secrets/"
property Placeholders属性占位符

在使用application.properties和application.yaml中的值时,会通过现有的Environment进行过滤,因此你可以引用以前定义的值(例如,从系统属性获环境变量中)。标准的使. 有默认值和无默认值占位符的使用示例如下:

app: name: "MyApp" description: "${app.name} is a spring boot application written by ${username:Unknown}"

假设username属性未在其他地方设置,app.description的值将为MyApp is a Spring Boot application written by Unknown.

Working With Multi-Document Files处理多文档文件

springboot允许你将单个物理文件分隔成多个逻辑文档,每个文档都是独立添加的。文档按从上到下的顺序处理。后面的文海可以省的前面文档中定义的属性。 对于application.yaml文件,使用的标准YAML多文档语法。三个连续的连字符代表一个文档的结束和下一个文档的开始。 例如,下面的文件有两个逻辑文档:

spring: application: name: "MyApp" --- spring: application: name: "MyCloudApp" config: activate: on-cloud-platform: "kubernetes"

对于application.properties文件,使用特殊的#---或!---注释来标记文件分隔

spring.application.name=MyApp #--- spring.application.name=MyCloudApp spring.config.activate.on-cloud-platform=kubernetes
Activation Properties 激活特性

有时,只有在满足特定条件时才能激活特定的属性集。例如,可能有一些属性只有再调特定配置文件处于活动状态时才有用。 使用spring.config.activate.*可以有条件地激活属性文件。 激活属性如下: activation properties

on-profile

配置文件表达式,必须匹配表达式,文档才会激活

on-cloud-platform

要是文档处于活动状态,必须检测到的CloudPlatform

例如,下面指定第二个文档只有在kubernetes上运行时才会被激活,而且只有在“prod”或“staging”配置文件激活时才会激活:

myprop: "always-set" --- spring: config: activate: on-cloud-platform: "kubernetes" on-profile: "prod | staging" myotherprop: "sometimes-set"

7.2.4 Encrypting Properties加密属性

SpringBoot不提供任何用于加密属性值的内置支持,但它提供了修改Spring Environment中所含值所需的钩点。EnvironmentPostProcessor接口允许你在应用程序启动前操作Environment。有关详细信息,请参阅启动前自定义环境或ApplicationContext。 如果你需要一种安全的方式来存储凭证和密码,SpringCloudVault项目支持在HashiCorpVault中存储外部化配置。

7.2.5 Working With YAML 使用YAML

YAML是JSON的超集,因此是一种用于指定分层配置数据的便捷格式。只有你的类路径上有SnakeYaml库,SpringApplication类就会自动支持YAML作为属性的替代。

Mapping YAML to Properties将YAML映射到属性

需要将YAML文档从其分层格式转换为可与Spring Environment配合使用的扁平结构。例如,请看下面的YAML文档:

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

为了从Environment访问这些属性,将对它们进行如下扁平化处理:

enviroments.dev.url=https://dev.example.com enviroments.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
Directly Loading YAML直接加载YAML

Spring Framework提供两个方便的类,可用于加载YAML文档。YamlPropertiesFactoryBean以Properties的形式加载YAML,而YamlMapFactoryBean则以Map的形式加载YAML。 如果要将YAML作为SpringPropertySource加载,也可以石笋YamlPropertySourceLoader类。

7.2.6 Configuration Random Values配置随机值

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

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

random.int*语法为OPEN value (,max) CLOSE,其中OPEN,CLOSE为任意字符,value,max为整数。如果提供max,则value为最小值,max为最大值。

7.2.7 Configuring System Environment Properties 配置系统环境属性

03 May 2025