“作方法”指南

1. Spring Boot 应用程序

本节包括与 Spring Boot 应用程序直接相关的主题。spring-doc.cadn.net.cn

1.1. 创建您自己的 FailureAnalyzer

FailureAnalyzer是在启动时拦截异常并将其转换为人类可读的消息的好方法,包装在FailureAnalysis. Spring Boot 为与应用程序上下文相关的异常、JSR-303 验证等提供了这样的分析器。 您也可以创建自己的。spring-doc.cadn.net.cn

AbstractFailureAnalyzerFailureAnalyzer,该命令检查要处理的异常中是否存在指定的异常类型。 您可以从该 API 进行扩展,以便您的 implementation 仅在实际存在异常时才有机会处理异常。 如果由于某种原因无法处理异常,则返回null为另一个 implementation 提供处理异常的机会。spring-doc.cadn.net.cn

FailureAnalyzerimplementations 必须在META-INF/spring.factories. 以下示例 registersProjectConstraintViolationFailureAnalyzer:spring-doc.cadn.net.cn

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
如果您需要访问BeanFactoryEnvironment,在FailureAnalyzer实现。

1.2. 自动配置故障排除

Spring Boot 自动配置会尽最大努力“做正确的事情”,但有时事情会失败,而且很难说出原因。spring-doc.cadn.net.cn

有一个非常有用的ConditionEvaluationReport在任何 Spring Boot 中可用ApplicationContext. 如果您启用DEBUGlogging 输出。 如果您使用spring-boot-actuator(参见 Actuator 章节),还有一个conditions以 JSON 格式呈现报告的终端节点。 使用该端点调试应用程序并查看 Spring Boot 在运行时添加了哪些功能(以及尚未添加哪些功能)。spring-doc.cadn.net.cn

通过查看源代码和 Javadoc 可以回答更多问题。 阅读代码时,请记住以下经验法则:spring-doc.cadn.net.cn

  • 查找名为*AutoConfiguration并阅读他们的来源。 请特别注意@Conditional*annotations 来了解它们启用的功能以及何时启用。 加--debug添加到命令行或 System 属性-Ddebug在控制台上获取在您的应用程序中做出的所有自动配置决策的日志。 在启用了 actuator 的正在运行的应用程序中,查看conditions端点 (/actuator/conditions或 JMX 等效项)获取相同的信息。spring-doc.cadn.net.cn

  • 查找@ConfigurationProperties(例如ServerProperties),然后从那里读取可用的外部配置选项。 这@ConfigurationPropertiesannotation 具有name属性,该属性充当外部属性的前缀。 因此ServerProperties具有prefix="server",其配置属性为server.port,server.address等。 在启用了 actuator 的正在运行的应用程序中,查看configprops端点。spring-doc.cadn.net.cn

  • 查找bind方法上的Binder要将配置值显式地从Environment以轻松的方式。 它通常与前缀一起使用。spring-doc.cadn.net.cn

  • 查找@Value直接绑定到Environment.spring-doc.cadn.net.cn

  • 查找@ConditionalOnExpression为响应 SPEL 表达式而打开和关闭功能的注释,通常使用从Environment.spring-doc.cadn.net.cn

1.3. 在启动之前自定义 Environment 或 ApplicationContext

一个SpringApplication具有ApplicationListenersApplicationContextInitializers,用于将自定义项应用于上下文或环境。 Spring Boot 加载了许多这样的自定义,以便在内部使用META-INF/spring.factories. 有多种方法可以注册其他自定义项:spring-doc.cadn.net.cn

  • 以编程方式,每个应用程序通过调用addListenersaddInitializers方法SpringApplication在运行它之前。spring-doc.cadn.net.cn

  • 以声明方式,每个应用程序,通过设置context.initializer.classescontext.listener.classes性能。spring-doc.cadn.net.cn

  • 以声明方式,对于所有应用程序,通过添加META-INF/spring.factories以及打包应用程序都用作库的 jar 文件。spring-doc.cadn.net.cn

SpringApplication发送一些特殊的ApplicationEvents传递给侦听器(有些甚至在创建上下文之前),然后为ApplicationContext也。 有关完整列表,请参阅“Spring Boot 功能”部分中的“应用程序事件和侦听器”。spring-doc.cadn.net.cn

还可以自定义Environment在使用EnvironmentPostProcessor. 每个实现都应该在META-INF/spring.factories,如以下示例所示:spring-doc.cadn.net.cn

org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor

该实现可以加载任意文件并将它们添加到Environment. 例如,以下示例从 Classpath 加载 YAML 配置文件:spring-doc.cadn.net.cn

Java
import java.io.IOException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;

public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {

    private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        Resource path = new ClassPathResource("com/example/myapp/config.yml");
        PropertySource<?> propertySource = loadYaml(path);
        environment.getPropertySources().addLast(propertySource);
    }

    private PropertySource<?> loadYaml(Resource path) {
        Assert.isTrue(path.exists(), () -> "Resource " + path + " does not exist");
        try {
            return this.loader.load("custom-resource", path).get(0);
        }
        catch (IOException ex) {
            throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
        }
    }

}
Kotlin
import org.springframework.boot.SpringApplication
import org.springframework.boot.env.EnvironmentPostProcessor
import org.springframework.boot.env.YamlPropertySourceLoader
import org.springframework.core.env.ConfigurableEnvironment
import org.springframework.core.env.PropertySource
import org.springframework.core.io.ClassPathResource
import org.springframework.core.io.Resource
import org.springframework.util.Assert
import java.io.IOException

class MyEnvironmentPostProcessor : EnvironmentPostProcessor {

    private val loader = YamlPropertySourceLoader()

    override fun postProcessEnvironment(environment: ConfigurableEnvironment, application: SpringApplication) {
        val path: Resource = ClassPathResource("com/example/myapp/config.yml")
        val propertySource = loadYaml(path)
        environment.propertySources.addLast(propertySource)
    }

    private fun loadYaml(path: Resource): PropertySource<*> {
        Assert.isTrue(path.exists()) { "Resource $path does not exist" }
        return try {
            loader.load("custom-resource", path)[0]
        } catch (ex: IOException) {
            throw IllegalStateException("Failed to load yaml configuration from $path", ex)
        }
    }

}
Environment已经准备好了 Spring Boot 默认加载的所有常用属性源。 因此,可以从环境中获取文件的位置。 前面的示例将custom-resourceproperty source 放在列表的末尾,以便在任何通常的其他位置定义的键优先。 自定义实现可以定义另一个 order。
使用@PropertySource在您的@SpringBootApplication似乎是在Environment,我们不建议这样做。 此类属性源不会添加到Environment直到刷新应用程序上下文。 现在配置某些属性(例如logging.*spring.main.*,这些 API 将在刷新开始之前读取。

1.4. 构建ApplicationContext层次结构(添加父上下文或根上下文)

您可以使用ApplicationBuilder类创建 parent/childApplicationContext层次 结构。 有关更多信息,请参阅“Spring Boot 功能”部分中的“features.html”。spring-doc.cadn.net.cn

1.5. 创建非 Web 应用程序

并非所有 Spring 应用程序都必须是 Web 应用程序(或 Web 服务)。 如果要在main方法,但也引导一个 Spring 应用程序来设置要使用的基础设施,你可以使用SpringApplicationSpring Boot 的功能。 一个SpringApplication更改其ApplicationContext类,具体取决于它是否认为它需要一个 Web 应用程序。 为了帮助它,您可以做的第一件事是将与服务器相关的依赖项(例如 servlet API)从 Classpath 中排除。 如果您无法执行此作(例如,您从同一代码库运行两个应用程序),则可以显式调用setWebApplicationType(WebApplicationType.NONE)在您的SpringApplication实例或将applicationContextClass属性(通过 Java API 或使用外部属性)。 您希望作为业务逻辑运行的应用程序代码可以作为CommandLineRunner并作为@Bean定义。spring-doc.cadn.net.cn

2. 属性和配置

本节包括有关设置和读取属性和配置设置以及它们与 Spring Boot 应用程序的交互的主题。spring-doc.cadn.net.cn

2.1. 在构建时自动扩展属性

您可以使用现有的构建配置来自动扩展这些属性,而不是对项目的构建配置中指定的某些属性进行硬编码。 这在 Maven 和 Gradle 中都是可能的。spring-doc.cadn.net.cn

2.1.1. 使用 Maven 自动扩展属性

您可以使用资源筛选自动扩展 Maven 项目中的属性。 如果您使用spring-boot-starter-parent,然后,您可以使用@..@placeholders,如以下示例所示:spring-doc.cadn.net.cn

Yaml
app:
  encoding: "@project.build.sourceEncoding@"
  java:
    version: "@java.version@"
仅以这种方式过滤生产配置(换句话说,不应用过滤src/test/resources).
如果启用addResourcesflag 中,spring-boot:rungoal 可以添加src/main/resources直接发送到 Classpath (用于热重载目的)。 这样做会规避资源筛选和此功能。 相反,您可以使用exec:javagoal 或自定义插件的配置。 有关更多详细信息,请参阅插件使用页面

如果您不使用 starter parent,则需要在<build/>元素的pom.xml:spring-doc.cadn.net.cn

<resources>
    <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
    </resource>
</resources>

您还需要在<plugins/>:spring-doc.cadn.net.cn

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.7</version>
    <configuration>
        <delimiters>
            <delimiter>@</delimiter>
        </delimiters>
        <useDefaultDelimiters>false</useDefaultDelimiters>
    </configuration>
</plugin>
useDefaultDelimiters如果您使用标准的 Spring 占位符(例如${placeholder}) 在您的配置中。 如果该属性未设置为false,这些可能会通过构建进行扩展。

2.1.2. 使用 Gradle 自动扩展属性

您可以通过配置 Java 插件的processResourcestask 执行此作,如以下示例所示:spring-doc.cadn.net.cn

tasks.named('processResources') {
    expand(project.properties)
}

然后,您可以使用占位符引用 Gradle 项目的属性,如以下示例所示:spring-doc.cadn.net.cn

性能
app.name=${name}
app.description=${description}
Yaml
app:
  name: "${name}"
  description: "${description}"
Gradle 的expand方法使用 Groovy 的SimpleTemplateEngine,它将${..}令 牌。 这${..}style 与 Spring 自己的属性占位符机制冲突。 要将 Spring 属性占位符与自动扩展一起使用,请按如下方式转义 Spring 属性占位符:\${..}.

2.2. 外部化 SpringApplication 的配置

一个SpringApplication具有 Bean 属性 setter,因此您可以在创建应用程序时使用其 Java API 来修改其行为。 或者,您可以通过在spring.main.*. 例如,在application.properties,您可能具有以下设置:spring-doc.cadn.net.cn

性能
spring.main.web-application-type=none
spring.main.banner-mode=off
Yaml
spring:
  main:
    web-application-type: "none"
    banner-mode: "off"

然后,Spring Boot 横幅不会在启动时打印,并且应用程序不会启动嵌入式 Web 服务器。spring-doc.cadn.net.cn

在外部配置中定义的属性将覆盖并替换使用 Java API 指定的值,但主源除外。 主要来源是提供给SpringApplication构造 函数:spring-doc.cadn.net.cn

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

@SpringBootApplication
public class MyApplication {

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

}
Kotlin
import org.springframework.boot.Banner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication

@SpringBootApplication
object MyApplication {

    @JvmStatic
    fun main(args: Array<String>) {
        val application = SpringApplication(MyApplication::class.java)
        application.setBannerMode(Banner.Mode.OFF)
        application.run(*args)
    }

}

或更改为sources(…​)方法SpringApplicationBuilder:spring-doc.cadn.net.cn

Java
import org.springframework.boot.Banner;
import org.springframework.boot.builder.SpringApplicationBuilder;

public class MyApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder()
            .bannerMode(Banner.Mode.OFF)
            .sources(MyApplication.class)
            .run(args);
    }

}
Kotlin
import org.springframework.boot.Banner
import org.springframework.boot.builder.SpringApplicationBuilder

object MyApplication {

    @JvmStatic
    fun main(args: Array<String>) {
        SpringApplicationBuilder()
            .bannerMode(Banner.Mode.OFF)
            .sources(MyApplication::class.java)
            .run(*args)
    }

}

鉴于上面的示例,如果我们有以下配置:spring-doc.cadn.net.cn

性能
spring.main.sources=com.example.MyDatabaseConfig,com.example.MyJmsConfig
spring.main.banner-mode=console
Yaml
spring:
  main:
    sources: "com.example.MyDatabaseConfig,com.example.MyJmsConfig"
    banner-mode: "console"

实际应用程序将显示横幅(被配置覆盖),并使用三个源进行ApplicationContext. 应用程序源包括:spring-doc.cadn.net.cn

  1. MyApplication(来自代码)spring-doc.cadn.net.cn

  2. MyDatabaseConfig(来自外部配置)spring-doc.cadn.net.cn

  3. MyJmsConfig(来自外部配置)spring-doc.cadn.net.cn

2.3. 更改应用程序的外部属性的位置

默认情况下,来自不同源的属性会添加到 Spring 中Environment按定义的顺序(有关确切顺序,请参阅“Spring Boot 功能”部分中的“features.html”)。spring-doc.cadn.net.cn

您还可以提供以下 System 属性(或环境变量)来更改行为:spring-doc.cadn.net.cn

  • spring.config.name (SPRING_CONFIG_NAME):默认为application作为文件名的根目录。spring-doc.cadn.net.cn

  • spring.config.location (SPRING_CONFIG_LOCATION):要加载的文件(例如类路径资源或 URL)。 单独的EnvironmentProperty Source 已为此文档设置,并且可以被 System Properties、Environment Variables 或 Command Line 覆盖。spring-doc.cadn.net.cn

无论你在环境中设置什么,Spring Boot 总是加载application.properties如上所述。 默认情况下,如果使用 YAML,则扩展名为 '.yaml' 和 '.yml的文件也会添加到列表中。spring-doc.cadn.net.cn

如果需要有关正在加载的文件的详细信息,可以将日志记录级别设置为org.springframework.boot.context.configtrace.

2.4. 使用 'short' 命令行参数

有些人喜欢使用 (例如)--port=9000而不是--server.port=9000在命令行中设置配置属性。 您可以通过在application.properties,如以下示例所示:spring-doc.cadn.net.cn

性能
server.port=${port:8080}
Yaml
server:
  port: "${port:8080}"
如果您继承自spring-boot-starter-parentPOM,则maven-resources-plugins已从 更改为 (即${*}@@maven.token@而不是${maven.token}) 以防止与 Spring 样式的占位符发生冲突。 如果您为application.properties直接,您可能还希望更改 Default Filter 令牌以使用其他分隔符
在此特定情况下,端口绑定在 PaaS 环境(如 Heroku 或 Cloud Foundry)中工作。 在这两个平台中,PORT环境变量会自动设置,并且 Spring 可以绑定到Environment性能。

2.5. 将 YAML 用于外部属性

YAML 是 JSON 的超集,因此,它是以分层格式存储外部属性的便捷语法,如以下示例所示:spring-doc.cadn.net.cn

spring:
  application:
    name: "cruncher"
  datasource:
    driver-class-name: "com.mysql.jdbc.Driver"
    url: "jdbc:mysql://localhost/test"
server:
  port: 9000

创建一个名为application.yaml并将其放在 Classpath 的根目录中。 然后添加snakeyaml添加到您的依赖项(Maven 坐标org.yaml:snakeyaml,如果您使用spring-boot-starter). 将 YAML 文件解析为 JavaMap<String,Object>(就像一个 JSON 对象一样),并且 Spring Boot 会展平 Map,使其深度为一层,并且具有句点分隔的键,就像许多人习惯的那样Properties文件。spring-doc.cadn.net.cn

前面的示例 YAML 对应于以下内容application.properties文件:spring-doc.cadn.net.cn

spring.application.name=cruncher
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/test
server.port=9000

有关 YAML 的更多信息,请参阅“Spring Boot 功能”部分中的“features.html”。spring-doc.cadn.net.cn

2.6. 设置活动的 Spring 配置文件

SpringEnvironment有一个 API,但您通常会将 System 属性 (spring.profiles.active) 或 OS 环境变量 (SPRING_PROFILES_ACTIVE). 此外,您还可以使用-D参数(记得放在主类或 jar 存档之前),如下所示:spring-doc.cadn.net.cn

$ java -jar -Dspring.profiles.active=production demo-0.0.1-SNAPSHOT.jar

在 Spring Boot 中,您还可以在application.properties,如以下示例所示:spring-doc.cadn.net.cn

性能
spring.profiles.active=production
Yaml
spring:
  profiles:
    active: "production"

以这种方式设置的值将替换为 System 属性或环境变量设置,而不是SpringApplicationBuilder.profiles()方法。 因此,后一个 Java API 可用于在不更改默认值的情况下扩充配置文件。spring-doc.cadn.net.cn

有关更多信息,请参阅“Spring Boot 功能”部分中的“features.html”。spring-doc.cadn.net.cn

2.7. 设置默认配置文件名称

默认配置文件是在没有活动配置文件时启用的配置文件。 默认情况下,默认配置文件的名称为default,但可以使用 System 属性 (spring.profiles.default) 或 OS 环境变量 (SPRING_PROFILES_DEFAULT).spring-doc.cadn.net.cn

在 Spring Boot 中,您还可以在application.properties,如以下示例所示:spring-doc.cadn.net.cn

性能
spring.profiles.default=dev
Yaml
spring:
  profiles:
    default: "dev"

有关更多信息,请参阅“Spring Boot 功能”部分中的“features.html”。spring-doc.cadn.net.cn

2.8. 根据环境更改配置

Spring Boot 支持多文档 YAML 和属性文件(有关详细信息,请参见features.html),这些文件可以根据活动配置文件有条件地激活。spring-doc.cadn.net.cn

如果文档包含spring.config.activate.on-profile键,则 profiles 值(以逗号分隔的 profiles 列表或 profile 表达式)被馈送到 Spring 中Environment.acceptsProfiles()方法。 如果配置文件表达式匹配,则该文档将包含在最终合并中(否则,它不是),如以下示例所示:spring-doc.cadn.net.cn

性能
server.port=9000
#---
spring.config.activate.on-profile=development
server.port=9001
#---
spring.config.activate.on-profile=production
server.port=0
Yaml
server:
  port: 9000
---
spring:
  config:
    activate:
      on-profile: "development"
server:
  port: 9001
---
spring:
  config:
    activate:
      on-profile: "production"
server:
  port: 0

在前面的示例中,默认端口为 9000。 但是,如果名为 'development' 的 Spring 配置文件处于活动状态,则端口为 9001。 如果 'production' 处于活动状态,则端口为 0。spring-doc.cadn.net.cn

文档将按遇到它们的顺序进行合并。 较晚的值将覆盖较早的值。

2.9. 发现外部属性的内置选项

Spring Boot 将外部属性从application.properties(或 YAML 文件和其他地方)下载到应用程序中。 没有(从技术上讲也不可能)在一个位置包含所有受支持属性的详尽列表,因为贡献可能来自 Classpath 上的其他 jar 文件。spring-doc.cadn.net.cn

具有 Actuator 功能的正在运行的应用程序具有configprops端点,该端点显示所有可通过@ConfigurationProperties.spring-doc.cadn.net.cn

附录包括一个application.propertiesexample 中列出了 Spring Boot 支持的最常见属性。 最终列表来自搜索源代码@ConfigurationProperties@Value注释以及偶尔使用Binder. 有关加载属性的确切顺序的更多信息,请参阅“features.html”。spring-doc.cadn.net.cn

3. 嵌入式 Web 服务器

每个 Spring Boot Web 应用程序都包含一个嵌入式 Web 服务器。 此功能会导致许多作问题,包括如何更改嵌入式服务器以及如何配置嵌入式服务器。 本节将回答这些问题。spring-doc.cadn.net.cn

3.1. 使用其他 Web 服务器

许多 Spring Boot Starters包括默认的嵌入式容器。spring-doc.cadn.net.cn

  • 对于 servlet 堆栈应用程序,spring-boot-starter-web包括 Tomcat,包括spring-boot-starter-tomcat,但您可以使用spring-boot-starter-jettyspring-boot-starter-undertow相反。spring-doc.cadn.net.cn

  • 对于反应式堆栈应用程序,spring-boot-starter-webflux包括 Reactor Netty,包括spring-boot-starter-reactor-netty,但您可以使用spring-boot-starter-tomcat,spring-boot-starter-jettyspring-boot-starter-undertow相反。spring-doc.cadn.net.cn

切换到其他 HTTP 服务器时,您需要将默认依赖项交换为所需的依赖项。 为了帮助完成此过程, Spring Boot 为每个受支持的 HTTP 服务器提供了一个单独的Starters。spring-doc.cadn.net.cn

下面的 Maven 示例展示了如何排除 Tomcat 并包括 Jetty for Spring MVC:spring-doc.cadn.net.cn

<properties>
    <jakarta-servlet.version>5.0.0</jakarta-servlet.version>
</properties>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <!-- Exclude the Tomcat dependency -->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- Use Jetty instead -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
Jakarta Servlet API 的版本已被覆盖,因为与 Tomcat 10 和 Undertow 2.3 不同,Jetty 11 不支持 Servlet 6.0。

将 Servlet API 降级到 5.0 会破坏 Spring Framework 的 Servlet 相关 mock!spring-doc.cadn.net.cn

由于 Jetty 需要 Servlet API 5.0,因此您有两种工作安排:spring-doc.cadn.net.cn

  • 测试使用 Servlet 5.0 API,并且仅使用成熟的 Web 环境来避免使用 Framework 的 Servlet 模拟spring-doc.cadn.net.cn

  • 测试使用 Servlet 6.0 API,并避免仅使用模拟 Web 环境来启动 Jettyspring-doc.cadn.net.cn

如果您的应用程序的测试需要混合使用 Web 环境,则您的测试设置可能需要进行一些结构更改,以严格分离这两个 Web 环境。spring-doc.cadn.net.cn

下面的 Gradle 示例配置了必要的依赖项和模块替换,以使用 Undertow 代替 Spring WebFlux 的 Reactor Netty:spring-doc.cadn.net.cn

dependencies {
    implementation "org.springframework.boot:spring-boot-starter-undertow"
    implementation "org.springframework.boot:spring-boot-starter-webflux"
    modules {
        module("org.springframework.boot:spring-boot-starter-reactor-netty") {
            replacedBy("org.springframework.boot:spring-boot-starter-undertow", "Use Undertow instead of Reactor Netty")
        }
    }
}
spring-boot-starter-reactor-netty需要使用WebClient类,因此即使需要包含不同的 HTTP 服务器,也可能需要保持对 Netty 的依赖。

3.2. 禁用 Web 服务器

如果你的 Classpath 包含启动 Web 服务器所需的位,Spring Boot 将自动启动它。 要禁用此行为,请配置WebApplicationTypeapplication.properties,如以下示例所示:spring-doc.cadn.net.cn

性能
spring.main.web-application-type=none
Yaml
spring:
  main:
    web-application-type: "none"

3.3. 更改 HTTP 端口

在独立应用程序中,主 HTTP 端口默认为8080但可以使用server.port(例如,在application.properties或作为 System 属性)。 得益于Environment值,您还可以使用SERVER_PORT(例如,作为 OS 环境变量)。spring-doc.cadn.net.cn

要完全关闭 HTTP 端点,但仍创建一个WebApplicationContextserver.port=-1(这样做有时对测试很有用)。spring-doc.cadn.net.cn

有关更多详细信息,请参阅“Spring Boot 功能”部分中的“web.html”,或者ServerProperties源代码。spring-doc.cadn.net.cn

3.4. 使用随机未分配的 HTTP 端口

要扫描空闲端口(使用 OS 本机来防止冲突),请使用server.port=0.spring-doc.cadn.net.cn

3.5. 在运行时发现 HTTP 端口

您可以从日志输出或WebServerApplicationContext通过其WebServer. 获取该 ID 并确保它已初始化的最佳方法是添加一个@Bean的类型ApplicationListener<WebServerInitializedEvent>并在发布事件时将容器从事件中拉出。spring-doc.cadn.net.cn

使用@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)也可以使用@LocalServerPortannotation 中,如以下示例所示:spring-doc.cadn.net.cn

Java
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.server.LocalServerPort;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyWebIntegrationTests {

    @LocalServerPort
    int port;

    // ...

}
Kotlin
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.boot.test.web.server.LocalServerPort

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyWebIntegrationTests {

    @LocalServerPort
    var port = 0

    // ...

}

@LocalServerPort@Value("${local.server.port}"). 请勿尝试在常规应用程序中注入端口。 正如我们刚才看到的,只有在初始化容器后才会设置该值。 与测试相反,应用程序代码回调会提前处理(在值实际可用之前)。spring-doc.cadn.net.cn

3.6. 启用 HTTP 响应压缩

Jetty、Tomcat、Reactor Netty 和 Undertow 支持 HTTP 响应压缩。 可以在application.properties如下:spring-doc.cadn.net.cn

性能
server.compression.enabled=true
Yaml
server:
  compression:
    enabled: true

默认情况下,响应的长度必须至少为 2048 字节才能执行压缩。 您可以通过设置server.compression.min-response-size财产。spring-doc.cadn.net.cn

默认情况下,仅当响应的内容类型为以下之一时,才会压缩响应:spring-doc.cadn.net.cn

您可以通过设置server.compression.mime-types财产。spring-doc.cadn.net.cn

3.7. 配置 SSL

SSL 可以通过设置各种server.ssl.*属性,通常位于application.propertiesapplication.yaml. 以下示例显示了使用 Java KeyStore 文件设置 SSL 属性:spring-doc.cadn.net.cn

性能
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret
Yaml
server:
  port: 8443
  ssl:
    key-store: "classpath:keystore.jks"
    key-store-password: "secret"
    key-password: "another-secret"

使用如上例所示的配置意味着应用程序不再支持端口 8080 上的纯 HTTP 连接器。 Spring Boot 不支持通过 HTTP 连接器和 HTTPS 连接器的配置application.properties. 如果要同时拥有两者,则需要以编程方式配置其中一个。 我们建议使用application.properties配置 HTTPS,因为 HTTP 连接器是两者中更容易以编程方式配置的。spring-doc.cadn.net.cn

3.7.1. 使用 PEM 编码的文件

您可以使用 PEM 编码的文件,而不是 Java KeyStore 文件。 您应该尽可能使用 PKCS#8 密钥文件。 PEM 编码的 PKCS#8 密钥文件以-----BEGIN PRIVATE KEY----------BEGIN ENCRYPTED PRIVATE KEY-----页眉。spring-doc.cadn.net.cn

如果您有其他格式的文件,例如 PKCS#1 (-----BEGIN RSA PRIVATE KEY-----) 或 SEC 1 (-----BEGIN EC PRIVATE KEY-----),您可以使用 OpenSSL 将它们转换为 PKCS#8:spring-doc.cadn.net.cn

openssl pkcs8 -topk8 -nocrypt -in <input file> -out <output file>

以下示例显示了使用 PEM 编码的证书和私钥文件设置 SSL 属性:spring-doc.cadn.net.cn

性能
server.port=8443
server.ssl.certificate=classpath:my-cert.crt
server.ssl.certificate-private-key=classpath:my-cert.key
server.ssl.trust-certificate=classpath:ca-cert.crt
Yaml
server:
  port: 8443
  ssl:
    certificate: "classpath:my-cert.crt"
    certificate-private-key: "classpath:my-cert.key"
    trust-certificate: "classpath:ca-cert.crt"

或者,可以在 SSL 捆绑包中配置 SSL 信任材料并应用于 Web 服务器,如以下示例所示:spring-doc.cadn.net.cn

性能
server.port=8443
server.ssl.bundle=example
Yaml
server:
  port: 8443
  ssl:
    bundle: "example"
server.ssl.bundle属性不能与server.ssl.

Ssl,了解所有受支持属性的详细信息。spring-doc.cadn.net.cn

3.8. 配置 HTTP/2

您可以在 Spring Boot 应用程序中使用server.http2.enabledconfiguration 属性。 双h2(基于 TLS 的 HTTP/2)和h2c(HTTP/2 over TCP) 支持。 要使用h2,还必须启用 SSL。 未启用 SSL 时,h2c将被使用。 例如,您可能希望使用h2c当您的应用程序在执行 TLS 终止的代理服务器后面运行时spring-doc.cadn.net.cn

3.8.1. 使用 Tomcat 的 HTTP/2

Spring Boot 默认随 Tomcat 10.1.x 一起提供,它支持h2ch2开箱即用。 或者,您可以使用libtcnativeh2如果库及其依赖项安装在主机作系统上,则为 SUPPORT。spring-doc.cadn.net.cn

库目录必须可用于 JVM 库路径(如果尚未可用)。 您可以使用 JVM 参数(例如-Djava.library.path=/usr/local/opt/tomcat-native/lib. 更多相关信息,请参阅 Tomcat 官方文档spring-doc.cadn.net.cn

3.8.2. 使用 Jetty 的 HTTP/2

对于 HTTP/2 支持,Jetty 需要额外的org.eclipse.jetty.http2:http2-serverDependency。 要使用h2c不需要其他依赖项。 要使用h2,您还需要根据您的部署选择以下依赖项之一:spring-doc.cadn.net.cn

3.8.3. 使用 Reactor Netty 的 HTTP/2

spring-boot-webflux-starter默认使用 Reactor Netty 作为服务器。 Reactor Netty 支持h2ch2开箱即用。 为了实现最佳的运行时性能,此服务器还支持h2使用本机库。 要启用此功能,您的应用程序需要具有额外的依赖项。spring-doc.cadn.net.cn

Spring Boot 管理io.netty:netty-tcnative-boringssl-static“uber jar”,包含适用于所有平台的本机库。 开发人员可以选择使用分类器仅导入所需的依赖项(参见 Netty 官方文档)。spring-doc.cadn.net.cn

3.8.4. 使用 Undertow 的 HTTP/2

Undertow 支架h2ch2开箱即用。spring-doc.cadn.net.cn

3.9. 配置 Web 服务器

通常,您应该首先考虑使用众多可用配置键之一,并通过在application.propertiesapplication.yaml文件。 请参阅“发现外部属性的内置选项”)。 这server.*namespace 在这里非常有用,它包括server.tomcat.*,server.jetty.*和其他 API 的服务器特定功能。 请参阅application-properties.html列表。spring-doc.cadn.net.cn

前面的部分已经涵盖了许多常见使用案例,例如压缩、SSL 或 HTTP/2。 但是,如果您的使用案例不存在配置键,则应查看WebServerFactoryCustomizer. 您可以声明这样的组件并访问与您选择的相关的服务器工厂:您应该为所选服务器(Tomcat、Jetty、Reactor Netty、Undertow)和所选的 Web 堆栈(servlet 或 reactive)选择变体。spring-doc.cadn.net.cn

以下示例适用于 Tomcat,其中spring-boot-starter-web(Servlet 堆栈):spring-doc.cadn.net.cn

Java
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;

@Component
public class MyTomcatWebServerCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        // customize the factory here
    }

}
Kotlin
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.stereotype.Component

@Component
class MyTomcatWebServerCustomizer : WebServerFactoryCustomizer<TomcatServletWebServerFactory?> {

    override fun customize(factory: TomcatServletWebServerFactory?) {
        // customize the factory here
    }

}
Spring Boot 在内部使用该基础结构来自动配置服务器。 自动配置WebServerFactoryCustomizerbean 的顺序为0,并将在任何用户定义的定制器之前进行处理,除非它具有另有说明的明确顺序。

一旦您可以访问WebServerFactory使用定制器,您可以使用它来配置特定部分,如连接器、服务器资源或服务器本身 - 所有这些都使用特定于服务器的 API。spring-doc.cadn.net.cn

此外,Spring Boot 还提供:spring-doc.cadn.net.cn

服务器 Servlet 堆栈 反应式堆栈

Tomcatspring-doc.cadn.net.cn

TomcatServletWebServerFactoryspring-doc.cadn.net.cn

TomcatReactiveWebServerFactoryspring-doc.cadn.net.cn

Jettyspring-doc.cadn.net.cn

JettyServletWebServerFactoryspring-doc.cadn.net.cn

JettyReactiveWebServerFactoryspring-doc.cadn.net.cn

Undertowspring-doc.cadn.net.cn

UndertowServletWebServerFactoryspring-doc.cadn.net.cn

UndertowReactiveWebServerFactoryspring-doc.cadn.net.cn

反应器spring-doc.cadn.net.cn

不适用spring-doc.cadn.net.cn

NettyReactiveWebServerFactoryspring-doc.cadn.net.cn

作为最后的手段,您也可以声明自己的WebServerFactorybean,它将覆盖 Spring Boot 提供的 bean。 执行此作时,自动配置的定制器仍会应用于您的自定义工厂,因此请谨慎使用该选项。spring-doc.cadn.net.cn

3.10. 向应用程序添加 Servlet、Filter 或 Listener

在 servlet 堆栈应用程序中,即使用spring-boot-starter-web,有两种方法可以添加Servlet,Filter,ServletContextListener以及 Servlet API 支持的其他侦听器添加到应用程序中:spring-doc.cadn.net.cn

3.10.1. 使用 Spring bean 添加 servlet、过滤器或侦听器

要添加Servlet,Filter或 Servlet*Listener通过使用 Spring Bean,您必须提供@Bean定义。 当您想要注入配置或依赖项时,这样做可能非常有用。 但是,您必须非常小心,不要让它们引起太多其他 bean 的急切初始化,因为它们必须在应用程序生命周期的早期就安装在容器中。 (例如,让它们依赖于您的DataSource或 JPA 配置。 您可以通过在首次使用时而不是在初始化时延迟初始化 bean 来解决此类限制。spring-doc.cadn.net.cn

对于过滤器和 servlet,您还可以通过添加FilterRegistrationBeanServletRegistrationBean而不是基础组件或除了基础组件之外。spring-doc.cadn.net.cn

如果没有dispatcherType在筛选器注册上指定,REQUEST被使用。 这与 Servlet 规范的默认 dispatcher 类型一致。spring-doc.cadn.net.cn

与任何其他 Spring bean 一样,您可以定义 servlet 过滤器 bean 的顺序;请务必查看“web.html”部分。spring-doc.cadn.net.cn

禁用 Servlet 或过滤器的注册

如前所述,任何ServletFilterBean 会自动注册到 Servlet 容器中。 要禁用特定FilterServletbean,为其创建一个注册 bean 并将其标记为已禁用,如以下示例所示:spring-doc.cadn.net.cn

Java
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyFilterConfiguration {

    @Bean
    public FilterRegistrationBean<MyFilter> registration(MyFilter filter) {
        FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>(filter);
        registration.setEnabled(false);
        return registration;
    }

}
Kotlin
import org.springframework.boot.web.servlet.FilterRegistrationBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyFilterConfiguration {

    @Bean
    fun registration(filter: MyFilter): FilterRegistrationBean<MyFilter> {
        val registration = FilterRegistrationBean(filter)
        registration.isEnabled = false
        return registration
    }

}

3.10.2. 使用 Classpath 扫描添加 servlet、过滤器和侦听器

@WebServlet,@WebFilter@WebListener带注释的类可以自动注册到嵌入式 servlet 容器中,方法是将@Configurationclass 替换为@ServletComponentScan并指定包含要注册的组件的包。 默认情况下,@ServletComponentScan从 Annotated 类的包中扫描。spring-doc.cadn.net.cn

3.11. 配置 Access Logging

可以通过 Tomcat、Undertow 和 Jetty 各自的命名空间为 Tomcat、Undertow 和 Jetty 配置访问日志。spring-doc.cadn.net.cn

例如,以下设置使用自定义模式记录对 Tomcat 的访问。spring-doc.cadn.net.cn

性能
server.tomcat.basedir=my-tomcat
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%t %a %r %s (%D microseconds)
Yaml
server:
  tomcat:
    basedir: "my-tomcat"
    accesslog:
      enabled: true
      pattern: "%t %a %r %s (%D microseconds)"
日志的默认位置是logs目录。 默认情况下,logsdirectory 是一个临时目录,因此您可能希望修复 Tomcat 的基目录或使用日志的绝对路径。 在前面的示例中,日志位于my-tomcat/logs相对于应用程序的工作目录。

Undertow 的访问日志记录可以采用类似的方式进行配置,如以下示例所示:spring-doc.cadn.net.cn

性能
server.undertow.accesslog.enabled=true
server.undertow.accesslog.pattern=%t %a %r %s (%D milliseconds)
server.undertow.options.server.record-request-start-time=true
Yaml
server:
  undertow:
    accesslog:
      enabled: true
      pattern: "%t %a %r %s (%D milliseconds)"
    options:
      server:
        record-request-start-time: true

请注意,除了启用访问日志记录和配置其模式之外,还启用了记录请求开始时间。 当包含响应时间 (%D) 在 Access Log 模式中。 日志存储在logs目录。 您可以通过设置server.undertow.accesslog.dir财产。spring-doc.cadn.net.cn

最后,Jetty 的访问日志记录也可以按如下方式配置:spring-doc.cadn.net.cn

性能
server.jetty.accesslog.enabled=true
server.jetty.accesslog.filename=/var/log/jetty-access.log
Yaml
server:
  jetty:
    accesslog:
      enabled: true
      filename: "/var/log/jetty-access.log"

默认情况下,日志会重定向到System.err. 有关更多详细信息,请参阅 Jetty 文档。spring-doc.cadn.net.cn

3.12. 在前端代理服务器后面运行

如果您的应用程序在代理、负载均衡器或云中运行,则请求信息(如主机、端口、方案等)可能会在此过程中发生变化。 您的应用程序可能正在 上运行10.10.10.10:8080,但 HTTP 客户端应该只能看到example.org.spring-doc.cadn.net.cn

RFC7239 “Forwarded Headers” 定义ForwardedHTTP 标头;代理可以使用此标头提供有关原始请求的信息。 您可以将应用程序配置为读取这些标头,并在创建链接并将其发送到 HTTP 302 响应、JSON 文档或 HTML 页面中的客户端时自动使用该信息。 还有一些非标准的标头,例如X-Forwarded-Host,X-Forwarded-Port,X-Forwarded-Proto,X-Forwarded-SslX-Forwarded-Prefix.spring-doc.cadn.net.cn

如果代理添加了常用的X-Forwarded-ForX-Forwarded-Proto标题, 设置server.forward-headers-strategyNATIVE就足以支持这些。 使用此选项,Web 服务器本身本身支持此功能;您可以查看他们的特定文档以了解特定行为。spring-doc.cadn.net.cn

如果这还不够,Spring 框架为 servlet 堆栈提供了一个ForwardedHeaderFilter,为反应堆栈提供了一个ForwardedHeaderTransformer。 您可以通过设置server.forward-headers-strategyFRAMEWORK.spring-doc.cadn.net.cn

如果您使用 Tomcat 并在代理处终止 SSL,则server.tomcat.redirect-context-root应设置为false. 这允许X-Forwarded-Proto标头。
如果您的应用程序在 Cloud Foundry、Heroku 或 Kubernetes 中运行,则server.forward-headers-strategyproperty 默认为NATIVE. 在所有其他实例中,它默认为NONE.

3.12.1. 自定义 Tomcat 的代理配置

如果使用 Tomcat,还可以配置用于携带“转发”信息的标头的名称,如以下示例所示:spring-doc.cadn.net.cn

性能
server.tomcat.remoteip.remote-ip-header=x-your-remote-ip-header
server.tomcat.remoteip.protocol-header=x-your-protocol-header
Yaml
server:
  tomcat:
    remoteip:
      remote-ip-header: "x-your-remote-ip-header"
      protocol-header: "x-your-protocol-header"

Tomcat 还配置了一个正则表达式,该表达式与要信任的内部代理匹配。 请参阅server.tomcat.remoteip.internal-proxies附录中的条目作为其默认值。 您可以通过在application.properties,如以下示例所示:spring-doc.cadn.net.cn

性能
server.tomcat.remoteip.internal-proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}
Yaml
server:
  tomcat:
    remoteip:
      internal-proxies: "192\\.168\\.\\d{1,3}\\.\\d{1,3}"
您可以通过设置internal-proxies清空(但在生产环境中不要这样做)。

您可以完全控制 Tomcat 的RemoteIpValve通过关闭 automatic one(为此,请将server.forward-headers-strategy=NONE) 并使用WebServerFactoryCustomizer豆。spring-doc.cadn.net.cn

3.13. 使用 Tomcat 启用多个连接器

您可以添加org.apache.catalina.connector.ConnectorTomcatServletWebServerFactory,该连接器可以允许多个连接器,包括 HTTP 和 HTTPS 连接器,如以下示例所示:spring-doc.cadn.net.cn

Java
import org.apache.catalina.connector.Connector;

import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyTomcatConfiguration {

    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> connectorCustomizer() {
        return (tomcat) -> tomcat.addAdditionalTomcatConnectors(createConnector());
    }

    private Connector createConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setPort(8081);
        return connector;
    }

}
Kotlin
import org.apache.catalina.connector.Connector
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyTomcatConfiguration {

    @Bean
    fun connectorCustomizer(): WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
        return WebServerFactoryCustomizer { tomcat: TomcatServletWebServerFactory ->
            tomcat.addAdditionalTomcatConnectors(
                createConnector()
            )
        }
    }

    private fun createConnector(): Connector {
        val connector = Connector("org.apache.coyote.http11.Http11NioProtocol")
        connector.port = 8081
        return connector
    }

}

3.14. 启用 Tomcat 的 MBean 注册表

默认情况下,Embedded Tomcat 的 MBean 注册表处于禁用状态。 这样可以最大程度地减少 Tomcat 的内存占用。 例如,如果您想使用 Tomcat 的 MBean,以便 Micrometer 可以使用它们来公开度量,则必须使用server.tomcat.mbeanregistry.enabled属性执行此作,如以下示例所示:spring-doc.cadn.net.cn

性能
server.tomcat.mbeanregistry.enabled=true
Yaml
server:
  tomcat:
    mbeanregistry:
      enabled: true

3.15. 使用 Undertow 启用多个侦听器

添加UndertowBuilderCustomizerUndertowServletWebServerFactory并将侦听器添加到Builder,如以下示例所示:spring-doc.cadn.net.cn

Java
import io.undertow.Undertow.Builder;

import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyUndertowConfiguration {

    @Bean
    public WebServerFactoryCustomizer<UndertowServletWebServerFactory> undertowListenerCustomizer() {
        return (factory) -> factory.addBuilderCustomizers(this::addHttpListener);
    }

    private Builder addHttpListener(Builder builder) {
        return builder.addHttpListener(8080, "0.0.0.0");
    }

}
Kotlin
import io.undertow.Undertow
import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyUndertowConfiguration {

    @Bean
    fun undertowListenerCustomizer(): WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
        return WebServerFactoryCustomizer { factory: UndertowServletWebServerFactory ->
            factory.addBuilderCustomizers(
                UndertowBuilderCustomizer { builder: Undertow.Builder -> addHttpListener(builder) })
        }
    }

    private fun addHttpListener(builder: Undertow.Builder): Undertow.Builder {
        return builder.addHttpListener(8080, "0.0.0.0")
    }

}

3.16. 使用 @ServerEndpoint 创建 WebSocket 端点

如果您想使用@ServerEndpoint在使用嵌入式容器的 Spring Boot 应用程序中,您必须声明一个ServerEndpointExporter @Bean,如以下示例所示:spring-doc.cadn.net.cn

Java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration(proxyBeanMethods = false)
public class MyWebSocketConfiguration {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}
Kotlin
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.socket.server.standard.ServerEndpointExporter

@Configuration(proxyBeanMethods = false)
class MyWebSocketConfiguration {

    @Bean
    fun serverEndpointExporter(): ServerEndpointExporter {
        return ServerEndpointExporter()
    }

}

前面示例中显示的 Bean 注册了任何@ServerEndpoint带有底层 WebSocket 容器的带注释的 bean。 当部署到独立的 servlet 容器时,此角色由 servlet 容器初始值设定项执行,而ServerEndpointExporterbean 不是必需的。spring-doc.cadn.net.cn

4. Spring MVC

Spring Boot 有许多Starters,包括 Spring MVC。 请注意,一些 starters 包含对 Spring MVC 的依赖,而不是直接包含它。 本节回答有关 Spring MVC 和 Spring Boot 的常见问题。spring-doc.cadn.net.cn

4.1. 编写 JSON REST 服务

任何弹簧@RestController只要 Jackson2 在 Classpath 上,默认情况下,只要 Jackson2 在 Classpath 上,应用程序就应该呈现 JSON 响应,如以下示例所示:spring-doc.cadn.net.cn

Java
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @RequestMapping("/thing")
    public MyThing thing() {
        return new MyThing();
    }

}
Kotlin
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class MyController {

    @RequestMapping("/thing")
    fun thing(): MyThing {
        return MyThing()
    }

}

只要MyThing可以被 Jackson2 序列化(对于普通的 POJO 或 Groovy 对象为 true),那么localhost:8080/thing默认提供它的 JSON 表示形式。 请注意,在浏览器中,您有时可能会看到 XML 响应,因为浏览器倾向于发送首选 XML 的 accept 标头。spring-doc.cadn.net.cn

4.2. 编写 XML REST 服务

如果您有 Jackson XML 扩展 (jackson-dataformat-xml) 时,您可以使用它来呈现 XML 响应。 我们用于 JSON 的上一个示例将起作用。 要使用 Jackson XML 渲染器,请将以下依赖项添加到您的项目中:spring-doc.cadn.net.cn

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

如果 Jackson 的 XML 扩展不可用而 JAXB 可用,则可以呈现 XML,但需要满足以下附加要求MyThing注释为@XmlRootElement,如以下示例所示:spring-doc.cadn.net.cn

Java
import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class MyThing {

    private String name;

    // getters/setters ...

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

}
Kotlin
import jakarta.xml.bind.annotation.XmlRootElement

@XmlRootElement
class MyThing {

    var name: String? = null

}

您需要确保 JAXB 库是项目的一部分,例如通过添加:spring-doc.cadn.net.cn

<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
</dependency>
要让服务器呈现 XML 而不是 JSON,您可能必须发送Accept: text/xml标头(或使用浏览器)。

4.3. 自定义 Jackson ObjectMapper

Spring MVC(客户端和服务器端)使用HttpMessageConverters在 HTTP 交换中协商内容转换。 如果 Jackson 在 classpath 上,则您已经获得了由Jackson2ObjectMapperBuilder,其实例是自动配置的。spring-doc.cadn.net.cn

ObjectMapper(或XmlMapperfor Jackson XML 转换器)实例(默认创建)具有以下自定义属性:spring-doc.cadn.net.cn

Spring Boot 还具有一些功能,可以更轻松地自定义此行为。spring-doc.cadn.net.cn

您可以配置ObjectMapperXmlMapper实例。 Jackson 提供了一套广泛的开/关功能,可用于配置其处理的各个方面。 这些功能在 6 个枚举(在 Jackson 中)中进行了描述,这些枚举映射到环境中的属性:spring-doc.cadn.net.cn

枚举 财产

com.fasterxml.jackson.databind.DeserializationFeaturespring-doc.cadn.net.cn

spring.jackson.deserialization.<feature_name>spring-doc.cadn.net.cn

true,falsespring-doc.cadn.net.cn

com.fasterxml.jackson.core.JsonGenerator.Featurespring-doc.cadn.net.cn

spring.jackson.generator.<feature_name>spring-doc.cadn.net.cn

true,falsespring-doc.cadn.net.cn

com.fasterxml.jackson.databind.MapperFeaturespring-doc.cadn.net.cn

spring.jackson.mapper.<feature_name>spring-doc.cadn.net.cn

true,falsespring-doc.cadn.net.cn

com.fasterxml.jackson.core.JsonParser.Featurespring-doc.cadn.net.cn

spring.jackson.parser.<feature_name>spring-doc.cadn.net.cn

true,falsespring-doc.cadn.net.cn

com.fasterxml.jackson.databind.SerializationFeaturespring-doc.cadn.net.cn

spring.jackson.serialization.<feature_name>spring-doc.cadn.net.cn

true,falsespring-doc.cadn.net.cn

com.fasterxml.jackson.annotation.JsonInclude.Includespring-doc.cadn.net.cn

spring.jackson.default-property-inclusionspring-doc.cadn.net.cn

always,non_null,non_absent,non_default,non_emptyspring-doc.cadn.net.cn

例如,要启用美颜打印,请将spring.jackson.serialization.indent_output=true. 请注意,由于使用了松绑,因此indent_output不必匹配相应枚举常量的大小写,即INDENT_OUTPUT.spring-doc.cadn.net.cn

此基于环境的配置将应用于自动配置的Jackson2ObjectMapperBuilderbean 的 API 创建,并应用于使用构建器创建的任何映射器,包括自动配置的ObjectMapper豆。spring-doc.cadn.net.cn

上下文的Jackson2ObjectMapperBuilder可由一个或多个Jackson2ObjectMapperBuilderCustomizer豆。 可以对此类定制器 bean 进行排序(Boot 自己的定制器的 order 为 0),从而允许在 Boot 的定制之前和之后应用其他定制。spring-doc.cadn.net.cn

任何 bean 类型com.fasterxml.jackson.databind.Module会自动注册到自动配置的Jackson2ObjectMapperBuilder并应用于任何ObjectMapper实例。 这提供了一种全局机制,用于在向应用程序添加新功能时提供自定义模块。spring-doc.cadn.net.cn

如果要替换默认的ObjectMapper完全定义一个@Bean并将其标记为@Primary或者,如果您更喜欢基于构建器的方法,请定义一个Jackson2ObjectMapperBuilder @Bean. 请注意,无论哪种情况,这样做都会禁用ObjectMapper.spring-doc.cadn.net.cn

如果您提供任何@Beans的类型MappingJackson2HttpMessageConverter,它们将替换 MVC 配置中的默认值。 此外,还有一个HttpMessageConverters(如果使用默认 MVC 配置,则始终可用)。 它有一些有用的方法来访问默认和用户增强的消息转换器。spring-doc.cadn.net.cn

请参阅“自定义 @ResponseBody 渲染”部分和WebMvcAutoConfigurationsource code 了解更多详情。spring-doc.cadn.net.cn

4.4. 自定义 @ResponseBody 渲染

Spring 用途HttpMessageConverters渲染@ResponseBody(或来自@RestController). 您可以通过在 Spring Boot 上下文中添加适当类型的 bean 来贡献其他转换器。 如果您添加的 bean 的类型无论如何都会包含在内(例如MappingJackson2HttpMessageConverter对于 JSON 转换),它将替换默认值。 一种HttpMessageConverters提供,并且如果您使用默认 MVC 配置,则它始终可用。 它有一些有用的方法来访问默认和用户增强的消息转换器(例如,如果您想手动将它们注入到自定义RestTemplate).spring-doc.cadn.net.cn

与正常的 MVC 使用一样,任何WebMvcConfigurer您提供的 bean 还可以通过覆盖configureMessageConverters方法。 但是,与普通 MVC 不同的是,您只能提供所需的其他转换器(因为 Spring Boot 使用相同的机制来提供其默认值)。 最后,如果您通过提供自己的 MVC 配置来选择退出 Spring Boot 默认 MVC 配置@EnableWebMvc配置,您可以完全控制并使用getMessageConvertersWebMvcConfigurationSupport.spring-doc.cadn.net.cn

请参阅WebMvcAutoConfigurationsource code 了解更多详情。spring-doc.cadn.net.cn

4.5. 处理 Multipart 文件上传

Spring Boot 拥抱 servlet 5jakarta.servlet.http.PartAPI 支持上传文件。 默认情况下, Spring Boot 将 Spring MVC 配置为每个文件的最大大小为 1MB,在单个请求中的最大文件数据为 10MB。 您可以覆盖这些值、中间数据存储到的位置(例如,存储到/tmp目录),以及使用在MultipartProperties类。 例如,如果要指定文件不受限制,请将spring.servlet.multipart.max-file-sizeproperty 设置为-1.spring-doc.cadn.net.cn

当您希望将多部分编码文件数据作为@RequestParam-annotated 类型的参数MultipartFile在 Spring MVC 控制器处理程序方法中。spring-doc.cadn.net.cn

请参阅MultipartAutoConfigurationsource 了解更多详情。spring-doc.cadn.net.cn

建议使用容器的内置支持来进行分段上传,而不是引入额外的依赖项,例如 Apache Commons File Upload。

4.6. 关闭 Spring MVC DispatcherServlet

默认情况下,所有内容都从应用程序的根目录 () 提供。 如果您希望映射到其他路径,则可以按如下方式配置一个路径:/spring-doc.cadn.net.cn

性能
spring.mvc.servlet.path=/mypath
Yaml
spring:
  mvc:
    servlet:
      path: "/mypath"

如果您有其他 servlet,则可以声明@Bean的类型ServletServletRegistrationBean对于每个,Spring Boot 将对容器透明地注册它们。 由于 Servlet 是以这种方式注册的,因此它们可以映射到DispatcherServlet而无需调用它。spring-doc.cadn.net.cn

配置DispatcherServlet你自己很不寻常,但如果你真的需要这样做,一个@Bean的类型DispatcherServletPath还必须提供DispatcherServlet.spring-doc.cadn.net.cn

4.7. 关闭默认 MVC 配置

完全控制 MVC 配置的最简单方法是提供您自己的@Configuration使用@EnableWebMvc注解。 这样做会将所有 MVC 配置都掌握在您手中。spring-doc.cadn.net.cn

4.8. 自定义 ViewResolver

一个ViewResolver是 Spring MVC 的核心组件,将@Controller到实际View实现。 请注意,ViewResolvers主要用于 UI 应用程序,而不是 REST 样式的服务 (aView不用于渲染@ResponseBody). 有许多ViewResolver可供选择,Spring 本身并不拘泥于您应该使用哪些。 另一方面, Spring Boot 会为您安装一两个,具体取决于它在 Classpath 和应用程序上下文中找到的内容。 这DispatcherServlet使用它在 Application Context 中找到的所有解析程序,依次尝试每个解析程序,直到获得结果。 如果您添加自己的解析程序,则必须了解添加解析程序的顺序和位置。spring-doc.cadn.net.cn

WebMvcAutoConfiguration添加以下内容ViewResolvers到您的上下文中:spring-doc.cadn.net.cn

  • InternalResourceViewResolver命名为 'defaultViewResolver'。 此函数查找可以使用DefaultServlet(包括静态资源和 JSP 页面,如果您使用它们)。 它将前缀和后缀应用于视图名称,然后在 servlet 上下文中查找具有该路径的物理资源(默认值都为空,但可以通过spring.mvc.view.prefixspring.mvc.view.suffix). 您可以通过提供相同类型的 bean 来覆盖它。spring-doc.cadn.net.cn

  • 一个BeanNameViewResolver命名为 'beanNameViewResolver'。 这是视图解析器链中的一个有用成员,它拾取与View正在解决。 应该没有必要覆盖或替换它。spring-doc.cadn.net.cn

  • 一个ContentNegotiatingViewResolver仅当实际存在View目前。 这是一个复合解析器,委托给所有其他解析器,并尝试查找与客户端发送的 'Accept' HTTP 标头的匹配项。 有一个有用的博客关于ContentNegotiatingViewResolver您可能想学习以了解更多信息,您还可以查看源代码以获取详细信息。 您可以关闭自动配置的ContentNegotiatingViewResolver通过定义一个名为 'viewResolver' 的 bean。spring-doc.cadn.net.cn

  • 如果您使用 Thymeleaf,则还有一个ThymeleafViewResolver命名为 'thymeleafViewResolver'。 它通过用前缀和后缀将视图名称括起来来查找资源。 前缀为spring.thymeleaf.prefix,后缀为spring.thymeleaf.suffix. 前缀和后缀的值分别默认为 'classpath:/templates/' 和 '.html' 。 您可以覆盖ThymeleafViewResolver通过提供同名的 Bean。spring-doc.cadn.net.cn

  • 如果您使用 FreeMarker,则还有一个FreeMarkerViewResolver命名为 'freeMarkerViewResolver'。 它在加载器路径中查找资源(该路径被外部化为spring.freemarker.templateLoaderPath,并且具有默认值 'classpath:/templates/'),方法是用前缀和后缀将视图名称括起来。 前缀外部化为spring.freemarker.prefix,后缀外部化为spring.freemarker.suffix. 前缀和后缀的默认值分别为 empty 和 '.ftlh'。 您可以覆盖FreeMarkerViewResolver通过提供同名的 Bean。spring-doc.cadn.net.cn

  • 如果您使用 Groovy 模板(实际上,如果groovy-templates在你的 Classpath 上),你还有一个GroovyMarkupViewResolver命名为 'groovyMarkupViewResolver'。 它通过在视图名称周围加上前缀和后缀(外部化为spring.groovy.template.prefixspring.groovy.template.suffix). 前缀和后缀的默认值分别为 'classpath:/templates/' 和 '.tpl'。 您可以覆盖GroovyMarkupViewResolver通过提供同名的 Bean。spring-doc.cadn.net.cn

  • 如果您使用 Mustache,则还有一个MustacheViewResolver命名为 'mustacheViewResolver'。 它通过用前缀和后缀将视图名称括起来来查找资源。 前缀为spring.mustache.prefix,后缀为spring.mustache.suffix. 前缀和后缀的值分别默认为 'classpath:/templates/' 和 '.mustache'。 您可以覆盖MustacheViewResolver通过提供同名的 Bean。spring-doc.cadn.net.cn

有关更多详细信息,请参阅以下部分:spring-doc.cadn.net.cn

5. Jersey

5.1. 使用 Spring Security 保护 Jersey 端点

Spring Security 可用于保护基于 Jersey 的 Web 应用程序,其方式与用于保护基于 Spring MVC 的 Web 应用程序的方式大致相同。 但是,如果要将 Spring Security 的方法级安全性与 Jersey 一起使用,则必须将 Jersey 配置为使用setStatus(int)sendError(int). 这可以防止 Jersey 在 Spring Security 有机会向 Client 端报告身份验证或授权失败之前提交响应。spring-doc.cadn.net.cn

jersey.config.server.response.setStatusOverSendErrorproperty 必须设置为true在应用程序的ResourceConfigbean,如以下示例所示:spring-doc.cadn.net.cn

import java.util.Collections;

import org.glassfish.jersey.server.ResourceConfig;

import org.springframework.stereotype.Component;

@Component
public class JerseySetStatusOverSendErrorConfig extends ResourceConfig {

    public JerseySetStatusOverSendErrorConfig() {
        register(Endpoint.class);
        setProperties(Collections.singletonMap("jersey.config.server.response.setStatusOverSendError", true));
    }

}

5.2. 将 Jersey 与另一个 Web 框架一起使用

要将 Jersey 与其他 Web 框架(如 Spring MVC)一起使用,应对其进行配置,以便允许其他框架处理它无法处理的请求。 首先,通过将spring.jersey.typeapplication 属性,其值为filter. 其次,配置您的ResourceConfig转发将导致 404 的请求,如以下示例所示。spring-doc.cadn.net.cn

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletProperties;

import org.springframework.stereotype.Component;

@Component
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        register(Endpoint.class);
        property(ServletProperties.FILTER_FORWARD_ON_404, true);
    }

}

6. HTTP 客户端

Spring Boot 提供了许多与 HTTP 客户端一起使用的Starters。 本节回答了与使用它们相关的问题。spring-doc.cadn.net.cn

6.1. 配置 RestTemplate 以使用代理

io.html 中所述,您可以使用RestTemplateCustomizerRestTemplateBuilder构建自定义的RestTemplate. 这是创建RestTemplate配置为使用代理。spring-doc.cadn.net.cn

代理配置的确切细节取决于正在使用的底层客户端请求工厂。spring-doc.cadn.net.cn

6.2. 配置基于 Reactor Netty 的 WebClient 使用的 TcpClient

当 Reactor Netty 位于基于 Reactor Netty 的 Reactor Netty 的WebClient是自动配置的。 要自定义客户端对网络连接的处理,请提供ClientHttpConnector豆。 以下示例配置了 60 秒的连接超时,并添加了一个ReadTimeoutHandler:spring-doc.cadn.net.cn

Java
import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import reactor.netty.http.client.HttpClient;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.client.reactive.ReactorResourceFactory;

@Configuration(proxyBeanMethods = false)
public class MyReactorNettyClientConfiguration {

    @Bean
    ClientHttpConnector clientHttpConnector(ReactorResourceFactory resourceFactory) {
        HttpClient httpClient = HttpClient.create(resourceFactory.getConnectionProvider())
                .runOn(resourceFactory.getLoopResources())
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60000)
                .doOnConnected((connection) -> connection.addHandlerLast(new ReadTimeoutHandler(60)));
        return new ReactorClientHttpConnector(httpClient);
    }

}
Kotlin
import io.netty.channel.ChannelOption
import io.netty.handler.timeout.ReadTimeoutHandler
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.client.reactive.ClientHttpConnector
import org.springframework.http.client.reactive.ReactorClientHttpConnector
import org.springframework.http.client.reactive.ReactorResourceFactory
import reactor.netty.http.client.HttpClient

@Configuration(proxyBeanMethods = false)
class MyReactorNettyClientConfiguration {

    @Bean
    fun clientHttpConnector(resourceFactory: ReactorResourceFactory): ClientHttpConnector {
        val httpClient = HttpClient.create(resourceFactory.connectionProvider)
            .runOn(resourceFactory.loopResources)
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 60000)
            .doOnConnected { connection ->
                connection.addHandlerLast(ReadTimeoutHandler(60))
            }
        return ReactorClientHttpConnector(httpClient)
    }

}
请注意ReactorResourceFactory对于连接提供程序和事件循环资源。 这确保了接收请求的服务器和发出请求的客户端有效地共享资源。

7. 日志记录

Spring Boot 没有强制性的日志记录依赖项,除了 Commons Logging API,它通常由 Spring Framework 的spring-jcl模块。 要使用 Logback,您需要包含它并且spring-jcl在 Classpath 上。 推荐的方法是通过Starters,这都依赖于spring-boot-starter-logging. 对于 Web 应用程序,您只需要spring-boot-starter-web,因为它传递依赖于日志记录Starters。 如果您使用 Maven,则以下依赖项会为您添加日志记录:spring-doc.cadn.net.cn

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

Spring Boot 有一个LoggingSystemabstraction 尝试根据 Classpath 的内容配置 logging。 如果 Logback 可用,则它是首选。spring-doc.cadn.net.cn

如果你需要对 logging 进行的唯一更改是设置各种 logger 的级别,你可以在application.properties通过使用 “logging.level” 前缀,如以下示例所示:spring-doc.cadn.net.cn

性能
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
Yaml
logging:
  level:
    org.springframework.web: "debug"
    org.hibernate: "error"

您还可以使用logging.file.name.spring-doc.cadn.net.cn

要配置日志记录系统的更精细设置,您需要使用LoggingSystem有问题。 默认情况下, Spring Boot 从系统的默认位置(例如classpath:logback.xml),但您可以使用logging.config财产。spring-doc.cadn.net.cn

7.1. 配置 Logback 以进行日志记录

如果您需要将自定义应用于 logback ,而不是可以使用application.properties,您将需要添加标准的 logback 配置文件。 您可以添加logback.xmlfile 复制到 Classpath 的根目录,以便 logback 查找。 您还可以使用logback-spring.xml如果要使用 Spring Boot Logback 扩展spring-doc.cadn.net.cn

Spring Boot 提供了许多 logback 配置,这些配置可以是included在您自己的配置中。 这些 includes 旨在允许重新应用某些常见的 Spring Boot 约定。spring-doc.cadn.net.cn

以下文件在org/springframework/boot/logging/logback/:spring-doc.cadn.net.cn

  • defaults.xml- 提供转换规则、模式属性和通用记录器配置。spring-doc.cadn.net.cn

  • console-appender.xml- 添加ConsoleAppender使用CONSOLE_LOG_PATTERN.spring-doc.cadn.net.cn

  • file-appender.xml- 添加RollingFileAppender使用FILE_LOG_PATTERNROLLING_FILE_NAME_PATTERN具有适当的设置。spring-doc.cadn.net.cn

此外,遗产base.xml文件是为了与早期版本的 Spring Boot 兼容。spring-doc.cadn.net.cn

典型的定制logback.xml文件将如下所示:spring-doc.cadn.net.cn

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
    <logger name="org.springframework.web" level="DEBUG"/>
</configuration>

您的 logback 配置文件还可以使用 System 属性,其中LoggingSystem为您创建:spring-doc.cadn.net.cn

Spring Boot 还通过使用自定义 Logback 转换器在控制台上(但不在日志文件中)提供了一些不错的 ANSI 颜色终端输出。 请参阅CONSOLE_LOG_PATTERNdefaults.xmlconfiguration 示例。spring-doc.cadn.net.cn

如果 Groovy 在 classpath 上,您应该能够使用logback.groovy也。 如果存在,则优先使用此设置。spring-doc.cadn.net.cn

Groovy 配置不支持 Spring 扩展。 任何logback-spring.groovy不会检测到文件。

7.1.1. 为仅文件输出配置 Logback

如果要禁用控制台日志记录并仅将输出写入文件,则需要自定义logback-spring.xml那个导入file-appender.xml但不是console-appender.xml,如以下示例所示:spring-doc.cadn.net.cn

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
    <root level="INFO">
        <appender-ref ref="FILE" />
    </root>
</configuration>

您还需要添加logging.file.name发送到您的application.propertiesapplication.yaml,如以下示例所示:spring-doc.cadn.net.cn

性能
logging.file.name=myapplication.log
Yaml
logging:
  file:
    name: "myapplication.log"

7.2. 配置 Log4j 进行日志记录

如果 Log4j 2 在 Classpath 上,则 Spring Boot 支持 Log4j 2 进行日志记录配置。 如果使用 starters 来组装依赖项,则必须排除 Logback,然后包含 Log4j 2。 如果您不使用Starters,则需要提供(至少)spring-jcl除了 Log4j 2.spring-doc.cadn.net.cn

推荐的路径是通过Starters,即使它需要一些摇晃。 以下示例展示了如何在 Maven 中设置Starters:spring-doc.cadn.net.cn

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

Gradle 提供了几种不同的方法来设置 Starter。 一种方法是使用模块替换。 为此,请声明对 Log4j 2 Starters的依赖项,并告诉 Gradle 任何出现的默认日志记录Starters都应替换为 Log4j 2 Starters,如以下示例所示:spring-doc.cadn.net.cn

dependencies {
    implementation "org.springframework.boot:spring-boot-starter-log4j2"
    modules {
        module("org.springframework.boot:spring-boot-starter-logging") {
            replacedBy("org.springframework.boot:spring-boot-starter-log4j2", "Use Log4j2 instead of Logback")
        }
    }
}
Log4j Starters将常见日志记录要求(例如让 Tomcat 使用java.util.logging但使用 Log4j 2) 配置输出。
要确保使用java.util.logging路由到 Log4j 2 中,通过设置java.util.logging.managersystem 属性设置为org.apache.logging.log4j.jul.LogManager.

7.2.1. 使用 YAML 或 JSON 配置 Log4j 2

除了默认的 XML 配置格式外,Log4j 2 还支持 YAML 和 JSON 配置文件。 要将 Log4j 2 配置为使用备用配置文件格式,请将相应的依赖项添加到 Classpath 中,并命名配置文件以匹配您选择的文件格式,如以下示例所示:spring-doc.cadn.net.cn

格式 依赖 文件名

YAMLspring-doc.cadn.net.cn

com.fasterxml.jackson.core:jackson-databind + com.fasterxml.jackson.dataformat:jackson-dataformat-yamlspring-doc.cadn.net.cn

log4j2.yaml + log4j2.ymlspring-doc.cadn.net.cn

JSON 格式spring-doc.cadn.net.cn

com.fasterxml.jackson.core:jackson-databindspring-doc.cadn.net.cn

log4j2.json + log4j2.jsnspring-doc.cadn.net.cn

7.2.2. 使用复合配置配置 Log4j 2

Log4j 2 支持将多个配置文件组合成一个复合配置。 要在 Spring Boot 中使用此支持,请配置logging.log4j2.config.override替换为一个或多个辅助配置文件的位置。 辅助配置文件将与主配置合并,无论主配置文件的源是 Spring Boot 的默认值,标准位置(如log4j.xml或由logging.config财产。spring-doc.cadn.net.cn

8. 数据访问

Spring Boot 包含许多用于处理数据源的 Starter。 本节回答与执行此作相关的问题。spring-doc.cadn.net.cn

8.1. 配置自定义 DataSource

配置您自己的DataSource中,定义一个@Bean的配置中。 Spring Boot 重用了DataSource任何需要的地方,包括数据库初始化。 如果需要外部化一些设置,可以将DataSource到环境(参见“features.html”)。spring-doc.cadn.net.cn

以下示例显示了如何在 Bean 中定义数据源:spring-doc.cadn.net.cn

Java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "app.datasource")
    public SomeDataSource dataSource() {
        return new SomeDataSource();
    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyDataSourceConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "app.datasource")
    fun dataSource(): SomeDataSource {
        return SomeDataSource()
    }

}

以下示例演示如何通过设置属性来定义数据源:spring-doc.cadn.net.cn

性能
app.datasource.url=jdbc:h2:mem:mydb
app.datasource.username=sa
app.datasource.pool-size=30
Yaml
app:
  datasource:
    url: "jdbc:h2:mem:mydb"
    username: "sa"
    pool-size: 30

假设SomeDataSource具有 URL、用户名和池大小的常规 JavaBean 属性,则这些设置会在DataSource可供其他组件使用。spring-doc.cadn.net.cn

Spring Boot 还提供了一个名为DataSourceBuilder,该数据源可用于创建标准数据源之一(如果它在 Classpath 上)。 构建器可以根据 Classpath 上可用的内容来检测要使用的 one。 它还会根据 JDBC URL 自动检测驱动程序。spring-doc.cadn.net.cn

以下示例演示如何使用DataSourceBuilder:spring-doc.cadn.net.cn

Java
import javax.sql.DataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {

    @Bean
    @ConfigurationProperties("app.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

}
Kotlin
import javax.sql.DataSource

import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyDataSourceConfiguration {

    @Bean
    @ConfigurationProperties("app.datasource")
    fun dataSource(): DataSource {
        return DataSourceBuilder.create().build()
    }

}

要使用该DataSource,您只需要连接信息。 还可以提供特定于池的设置。 检查将在运行时使用的实现以获取更多详细信息。spring-doc.cadn.net.cn

以下示例演示如何通过设置属性来定义 JDBC 数据源:spring-doc.cadn.net.cn

性能
app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30
Yaml
app:
  datasource:
    url: "jdbc:mysql://localhost/test"
    username: "dbuser"
    password: "dbpass"
    pool-size: 30

但是,有一个问题。 由于未公开连接池的实际类型,因此不会在自定义的元数据中生成任何键DataSource并且您的 IDE 中没有可用的补全(因为DataSourceinterface 不公开任何属性)。 此外,如果您碰巧在 Classpath 上有 Hikari,则此基本设置不起作用,因为 Hikari 没有url属性(但确实具有jdbcUrl属性)。 在这种情况下,您必须按如下方式重写配置:spring-doc.cadn.net.cn

性能
app.datasource.jdbc-url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30
Yaml
app:
  datasource:
    jdbc-url: "jdbc:mysql://localhost/test"
    username: "dbuser"
    password: "dbpass"
    pool-size: 30

您可以通过强制连接池使用并返回专用实现而不是DataSource. 您无法在运行时更改实现,但选项列表将是显式的。spring-doc.cadn.net.cn

以下示例显示了如何创建HikariDataSourceDataSourceBuilder:spring-doc.cadn.net.cn

Java
import com.zaxxer.hikari.HikariDataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {

    @Bean
    @ConfigurationProperties("app.datasource")
    public HikariDataSource dataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

}
Kotlin
import com.zaxxer.hikari.HikariDataSource
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyDataSourceConfiguration {

    @Bean
    @ConfigurationProperties("app.datasource")
    fun dataSource(): HikariDataSource {
        return DataSourceBuilder.create().type(HikariDataSource::class.java).build()
    }

}

您甚至可以利用DataSourceProperties为您服务 — 也就是说,如果未提供 URL,则为默认嵌入式数据库提供合理的用户名和密码。 您可以轻松地初始化DataSourceBuilder从任何DataSourcePropertiesobject,因此你也可以注入 Spring Boot 自动创建的DataSource。 但是,这会将您的配置拆分为两个命名空间:url,username,password,typedriverspring.datasource其余的在您的自定义命名空间 (app.datasource). 为避免这种情况,您可以重新定义自定义DataSourceProperties在您的自定义命名空间上,如以下示例所示:spring-doc.cadn.net.cn

Java
import com.zaxxer.hikari.HikariDataSource;

import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource")
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("app.datasource.configuration")
    public HikariDataSource dataSource(DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
    }

}
Kotlin
import com.zaxxer.hikari.HikariDataSource
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary

@Configuration(proxyBeanMethods = false)
class MyDataSourceConfiguration {

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource")
    fun dataSourceProperties(): DataSourceProperties {
        return DataSourceProperties()
    }

    @Bean
    @ConfigurationProperties("app.datasource.configuration")
    fun dataSource(properties: DataSourceProperties): HikariDataSource {
        return properties.initializeDataSourceBuilder().type(HikariDataSource::class.java).build()
    }

}

此设置使您与 Spring Boot 默认为您执行的作同步,不同之处在于选择了专用连接池(在代码中),并且其设置在app.datasource.configurationsub 命名空间。 因为DataSourceProperties正在处理url/jdbcUrltranslation 的翻译,您可以按如下方式进行配置:spring-doc.cadn.net.cn

性能
app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.configuration.maximum-pool-size=30
Yaml
app:
  datasource:
    url: "jdbc:mysql://localhost/test"
    username: "dbuser"
    password: "dbpass"
    configuration:
      maximum-pool-size: 30
Spring Boot 会将 Hikari 特定的设置暴露给spring.datasource.hikari. 此示例使用更通用的configurationsub 命名空间为例,不支持多个 DataSource 实现。
因为您的自定义配置选择与 Hikari 一起使用,所以app.datasource.type没有效果。 在实践中,构建器会使用您可能在此处设置的任何值进行初始化,然后被对.type().

请参阅 “Spring Boot 功能” 部分中的 “data.html” 和DataSourceAutoConfiguration类了解更多详情。spring-doc.cadn.net.cn

8.2. 配置两个 DataSource

如果需要配置多个数据源,则可以应用上一节中描述的相同技巧。 但是,您必须标记DataSource实例设置为@Primary,因为未来的各种 auto-configuration 都希望能够按类型获得一个。spring-doc.cadn.net.cn

如果您创建自己的DataSource时,自动配置将回退。 在以下示例中,我们提供的功能集与自动配置在主数据源上提供的功能集完全相同spring-doc.cadn.net.cn

Java
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbcp2.BasicDataSource;

import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration(proxyBeanMethods = false)
public class MyDataSourcesConfiguration {

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.first")
    public DataSourceProperties firstDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.first.configuration")
    public HikariDataSource firstDataSource(DataSourceProperties firstDataSourceProperties) {
        return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
    }

    @Bean
    @ConfigurationProperties("app.datasource.second")
    public BasicDataSource secondDataSource() {
        return DataSourceBuilder.create().type(BasicDataSource.class).build();
    }

}
Kotlin
import com.zaxxer.hikari.HikariDataSource
import org.apache.commons.dbcp2.BasicDataSource
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary

@Configuration(proxyBeanMethods = false)
class MyDataSourcesConfiguration {

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.first")
    fun firstDataSourceProperties(): DataSourceProperties {
        return DataSourceProperties()
    }

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.first.configuration")
    fun firstDataSource(firstDataSourceProperties: DataSourceProperties): HikariDataSource {
        return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource::class.java).build()
    }

    @Bean
    @ConfigurationProperties("app.datasource.second")
    fun secondDataSource(): BasicDataSource {
        return DataSourceBuilder.create().type(BasicDataSource::class.java).build()
    }

}
firstDataSourceProperties必须标记为@Primary,以便 Database Initializer 功能使用您的副本(如果使用 Initializer)。

这两个数据源也都绑定用于高级自定义。 例如,您可以按如下方式配置它们:spring-doc.cadn.net.cn

性能
app.datasource.first.url=jdbc:mysql://localhost/first
app.datasource.first.username=dbuser
app.datasource.first.password=dbpass
app.datasource.first.configuration.maximum-pool-size=30

app.datasource.second.url=jdbc:mysql://localhost/second
app.datasource.second.username=dbuser
app.datasource.second.password=dbpass
app.datasource.second.max-total=30
Yaml
app:
  datasource:
    first:
      url: "jdbc:mysql://localhost/first"
      username: "dbuser"
      password: "dbpass"
      configuration:
        maximum-pool-size: 30

    second:
      url: "jdbc:mysql://localhost/second"
      username: "dbuser"
      password: "dbpass"
      max-total: 30

您可以将相同的概念应用于辅助DataSource以及,如以下示例所示:spring-doc.cadn.net.cn

Java
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbcp2.BasicDataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration(proxyBeanMethods = false)
public class MyCompleteDataSourcesConfiguration {

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.first")
    public DataSourceProperties firstDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.first.configuration")
    public HikariDataSource firstDataSource(DataSourceProperties firstDataSourceProperties) {
        return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
    }

    @Bean
    @ConfigurationProperties("app.datasource.second")
    public DataSourceProperties secondDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("app.datasource.second.configuration")
    public BasicDataSource secondDataSource(
            @Qualifier("secondDataSourceProperties") DataSourceProperties secondDataSourceProperties) {
        return secondDataSourceProperties.initializeDataSourceBuilder().type(BasicDataSource.class).build();
    }

}
Kotlin
import com.zaxxer.hikari.HikariDataSource
import org.apache.commons.dbcp2.BasicDataSource
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary

@Configuration(proxyBeanMethods = false)
class MyCompleteDataSourcesConfiguration {

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.first")
    fun firstDataSourceProperties(): DataSourceProperties {
        return DataSourceProperties()
    }

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.first.configuration")
    fun firstDataSource(firstDataSourceProperties: DataSourceProperties): HikariDataSource {
        return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource::class.java).build()
    }

    @Bean
    @ConfigurationProperties("app.datasource.second")
    fun secondDataSourceProperties(): DataSourceProperties {
        return DataSourceProperties()
    }

    @Bean
    @ConfigurationProperties("app.datasource.second.configuration")
    fun secondDataSource(secondDataSourceProperties: DataSourceProperties): BasicDataSource {
        return secondDataSourceProperties.initializeDataSourceBuilder().type(BasicDataSource::class.java).build()
    }

}

前面的示例在自定义命名空间上配置了两个数据源,其逻辑与 Spring Boot 在自动配置中使用的逻辑相同。 请注意,每个configurationSub 命名空间 根据所选实现提供高级设置。spring-doc.cadn.net.cn

8.3. 使用 Spring 数据存储库

Spring Data 可以创建@Repository各种风格的接口。 Spring Boot 会为您处理所有这些作,只要这些@Repositories包含在其中一个自动配置包中,通常是主应用程序类的包(或子包),该包带有@SpringBootApplication@EnableAutoConfiguration.spring-doc.cadn.net.cn

对于许多应用程序,您所需要做的就是将正确的 Spring Data 依赖项放在 Classpath 上。 有一个spring-boot-starter-data-jpa对于 JPA,spring-boot-starter-data-mongodb适用于 MongoDB,以及支持技术的各种其他Starters。 首先,创建一些存储库接口来处理@Entity对象。spring-doc.cadn.net.cn

Spring Boot 确定@Repositorydefinitions 来扫描 auto-configuration 软件包。 如需更多控制,请使用@Enable…Repositories来自 Spring Data 的注释。spring-doc.cadn.net.cn

有关 Spring Data 的更多信息,请参阅 Spring Data 项目页面spring-doc.cadn.net.cn

8.4. 将 @Entity 定义与 Spring 配置分开

Spring Boot 确定@Entitydefinitions 来扫描 auto-configuration 软件包。 如需更多控制,请使用@EntityScanannotation 中,如以下示例所示:spring-doc.cadn.net.cn

Java
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@EntityScan(basePackageClasses = City.class)
public class MyApplication {

    // ...

}
Kotlin
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@EntityScan(basePackageClasses = [City::class])
class MyApplication {

    // ...

}

8.5. 配置 JPA 属性

Spring Data JPA 已经提供了一些独立于供应商的配置选项(例如用于 SQL 日志记录的选项),并且 Spring Boot 将这些选项以及 Hibernate 的更多选项公开为外部配置属性。 其中一些是根据上下文自动检测的,因此您不必设置它们。spring-doc.cadn.net.cn

spring.jpa.hibernate.ddl-auto是一种特殊情况,因为根据运行时条件,它具有不同的默认值。 如果使用嵌入式数据库,并且没有架构管理器(例如 Liquibase 或 Flyway)正在处理DataSource,则默认为create-drop. 在所有其他情况下,它默认为none.spring-doc.cadn.net.cn

要使用的方言由 JPA 提供程序检测。 如果您更喜欢自己设置方言,请将spring.jpa.database-platform财产。spring-doc.cadn.net.cn

以下示例显示了要设置的最常见选项:spring-doc.cadn.net.cn

性能
spring.jpa.hibernate.naming.physical-strategy=com.example.MyPhysicalNamingStrategy
spring.jpa.show-sql=true
Yaml
spring:
  jpa:
    hibernate:
      naming:
        physical-strategy: "com.example.MyPhysicalNamingStrategy"
    show-sql: true

此外,所有spring.jpa.properties.*作为普通 JPA 属性传递(前缀被剥离),当本地EntityManagerFactory已创建。spring-doc.cadn.net.cn

您需要确保在spring.jpa.properties.*与您的 JPA 提供商所期望的完全匹配。 Spring Boot 不会尝试对这些条目进行任何类型的松散绑定。spring-doc.cadn.net.cn

例如,如果要配置 Hibernate 的批处理大小,则必须使用spring.jpa.properties.hibernate.jdbc.batch_size. 如果您使用其他表单,例如batchSizebatch-size,则 Hibernate 不会应用该设置。spring-doc.cadn.net.cn

如果需要对 Hibernate 属性应用高级自定义,请考虑注册一个HibernatePropertiesCustomizerbean 的 bean 中,将在创建EntityManagerFactory. 这优先于自动配置应用的任何内容。

8.6. 配置 Hibernate 命名策略

Hibernate 使用两种不同的命名策略将名称从对象模型映射到相应的数据库名称。 物理和隐式策略实现的完全限定类名可以通过设置spring.jpa.hibernate.naming.physical-strategyspring.jpa.hibernate.naming.implicit-strategy属性。 或者,如果ImplicitNamingStrategyPhysicalNamingStrategybean 在应用程序上下文中可用,Hibernate 将自动配置为使用它们。spring-doc.cadn.net.cn

默认情况下, Spring Boot 使用CamelCaseToUnderscoresNamingStrategy. 使用此策略,所有点都替换为下划线,驼峰大小写也替换为下划线。 此外,默认情况下,所有表名都以小写形式生成。 例如,TelephoneNumber实体映射到telephone_number桌子。 如果您的架构需要大小写混合的标识符,请定义自定义CamelCaseToUnderscoresNamingStrategybean,如以下示例所示:spring-doc.cadn.net.cn

Java
import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyHibernateConfiguration {

    @Bean
    public CamelCaseToUnderscoresNamingStrategy caseSensitivePhysicalNamingStrategy() {
        return new CamelCaseToUnderscoresNamingStrategy() {

            @Override
            protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) {
                return false;
            }

        };
    }

}
Kotlin
import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyHibernateConfiguration {

    @Bean
    fun caseSensitivePhysicalNamingStrategy(): CamelCaseToUnderscoresNamingStrategy {
        return object : CamelCaseToUnderscoresNamingStrategy() {
            override fun isCaseInsensitive(jdbcEnvironment: JdbcEnvironment): Boolean {
                return false
            }
        }
    }

}

如果您更喜欢使用 Hibernate 的默认值,请设置以下属性:spring-doc.cadn.net.cn

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

或者,您可以配置以下 Bean:spring-doc.cadn.net.cn

Java
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
class MyHibernateConfiguration {

    @Bean
    PhysicalNamingStrategyStandardImpl caseSensitivePhysicalNamingStrategy() {
        return new PhysicalNamingStrategyStandardImpl();
    }

}
Kotlin
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
internal class MyHibernateConfiguration {

    @Bean
    fun caseSensitivePhysicalNamingStrategy(): PhysicalNamingStrategyStandardImpl {
        return PhysicalNamingStrategyStandardImpl()
    }

}

8.7. 配置 Hibernate 二级缓存

可以为一系列缓存提供程序配置 Hibernate 二级缓存。 与其配置 Hibernate 再次查找缓存提供程序,不如尽可能提供上下文中可用的缓存提供程序。spring-doc.cadn.net.cn

要使用 JCache 执行此作,首先确保org.hibernate.orm:hibernate-jcache在 Classpath 上可用。 然后,添加一个HibernatePropertiesCustomizerbean,如以下示例所示:spring-doc.cadn.net.cn

Java
import org.hibernate.cache.jcache.ConfigSettings;

import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyHibernateSecondLevelCacheConfiguration {

    @Bean
    public HibernatePropertiesCustomizer hibernateSecondLevelCacheCustomizer(JCacheCacheManager cacheManager) {
        return (properties) -> properties.put(ConfigSettings.CACHE_MANAGER, cacheManager.getCacheManager());
    }

}
Kotlin
import org.hibernate.cache.jcache.ConfigSettings
import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer
import org.springframework.cache.jcache.JCacheCacheManager
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyHibernateSecondLevelCacheConfiguration {

    @Bean
    fun hibernateSecondLevelCacheCustomizer(cacheManager: JCacheCacheManager): HibernatePropertiesCustomizer {
        return HibernatePropertiesCustomizer { properties ->
            properties[ConfigSettings.CACHE_MANAGER] = cacheManager.cacheManager
        }
    }

}

此定制器会将 Hibernate 配置为使用相同的CacheManager作为应用程序使用的 VPN。 也可以使用单独的CacheManager实例。 有关详细信息,请参阅 Hibernate 用户指南spring-doc.cadn.net.cn

8.8. 在 Hibernate 组件中使用依赖注入

默认情况下, Spring Boot 会注册一个BeanContainer使用BeanFactory以便转换器和实体侦听器可以使用常规依赖项注入。spring-doc.cadn.net.cn

您可以通过注册HibernatePropertiesCustomizer,用于删除或更改hibernate.resource.beans.container财产。spring-doc.cadn.net.cn

8.9. 使用自定义 EntityManagerFactory

要完全控制EntityManagerFactory,您需要添加一个@Bean命名为 'entityManagerFactory'。 Spring Boot 自动配置在存在该类型的 bean 时关闭其实体 manager。spring-doc.cadn.net.cn

8.10. 使用多个 EntityManagerFactories

如果您需要对多个数据源使用 JPA,则可能需要一个数据源EntityManagerFactory每个数据源。 这LocalContainerEntityManagerFactoryBean来自 Spring ORM 允许您配置EntityManagerFactory满足您的需求。 您还可以重复使用JpaProperties以绑定每个EntityManagerFactory,如以下示例所示:spring-doc.cadn.net.cn

Java
import javax.sql.DataSource;

import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

@Configuration(proxyBeanMethods = false)
public class MyEntityManagerFactoryConfiguration {

    @Bean
    @ConfigurationProperties("app.jpa.first")
    public JpaProperties firstJpaProperties() {
        return new JpaProperties();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean firstEntityManagerFactory(DataSource firstDataSource,
            JpaProperties firstJpaProperties) {
        EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(firstJpaProperties);
        return builder.dataSource(firstDataSource).packages(Order.class).persistenceUnit("firstDs").build();
    }

    private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties jpaProperties) {
        JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(jpaProperties);
        return new EntityManagerFactoryBuilder(jpaVendorAdapter, jpaProperties.getProperties(), null);
    }

    private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
        // ... map JPA properties as needed
        return new HibernateJpaVendorAdapter();
    }

}
Kotlin
import javax.sql.DataSource

import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.orm.jpa.JpaVendorAdapter
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter

@Configuration(proxyBeanMethods = false)
class MyEntityManagerFactoryConfiguration {

    @Bean
    @ConfigurationProperties("app.jpa.first")
    fun firstJpaProperties(): JpaProperties {
        return JpaProperties()
    }

    @Bean
    fun firstEntityManagerFactory(
        firstDataSource: DataSource?,
        firstJpaProperties: JpaProperties
    ): LocalContainerEntityManagerFactoryBean {
        val builder = createEntityManagerFactoryBuilder(firstJpaProperties)
        return builder.dataSource(firstDataSource).packages(Order::class.java).persistenceUnit("firstDs").build()
    }

    private fun createEntityManagerFactoryBuilder(jpaProperties: JpaProperties): EntityManagerFactoryBuilder {
        val jpaVendorAdapter = createJpaVendorAdapter(jpaProperties)
        return EntityManagerFactoryBuilder(jpaVendorAdapter, jpaProperties.properties, null)
    }

    private fun createJpaVendorAdapter(jpaProperties: JpaProperties): JpaVendorAdapter {
        // ... map JPA properties as needed
        return HibernateJpaVendorAdapter()
    }

}

上面的示例创建了一个EntityManagerFactory使用DataSource名为firstDataSource. 它扫描位于同一包中的 entity asOrder. 可以使用app.first.jpaNamespace。spring-doc.cadn.net.cn

当你为LocalContainerEntityManagerFactoryBean您自己,以及在创建自动配置的LocalContainerEntityManagerFactoryBean丢失了。 例如,在 Hibernate 的情况下,spring.jpa.hibernate前缀不会自动应用于您的LocalContainerEntityManagerFactoryBean. 如果您依赖这些属性来配置命名策略或 DDL 模式等内容,则需要在创建LocalContainerEntityManagerFactoryBean豆。

您应该为需要 JPA 访问权限的任何其他数据源提供类似的配置。 要完成图片,您需要配置JpaTransactionManager对于每个EntityManagerFactory也。 或者,您可以使用跨越两者的 JTA 事务 Management 器。spring-doc.cadn.net.cn

如果使用 Spring Data,则需要配置@EnableJpaRepositories因此,如以下示例所示:spring-doc.cadn.net.cn

Java
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = Order.class, entityManagerFactoryRef = "firstEntityManagerFactory")
public class OrderConfiguration {

}
Kotlin
import org.springframework.context.annotation.Configuration
import org.springframework.data.jpa.repository.config.EnableJpaRepositories

@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = [Order::class], entityManagerFactoryRef = "firstEntityManagerFactory")
class OrderConfiguration
Java
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = Customer.class, entityManagerFactoryRef = "secondEntityManagerFactory")
public class CustomerConfiguration {

}
Kotlin
import org.springframework.context.annotation.Configuration
import org.springframework.data.jpa.repository.config.EnableJpaRepositories

@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = [Customer::class], entityManagerFactoryRef = "secondEntityManagerFactory")
class CustomerConfiguration

8.11. 使用传统的 persistence.xml 文件

Spring Boot 不会搜索或使用META-INF/persistence.xml默认情况下。 如果您更喜欢使用传统的persistence.xml,您需要定义自己的@Bean的类型LocalEntityManagerFactoryBean(ID 为 'entityManagerFactory')并在此处设置持久化单元名称。spring-doc.cadn.net.cn

8.12. 使用 Spring Data JPA 和 Mongo 存储库

Spring Data JPA 和 Spring Data Mongo 都可以自动创建Repository实现。 如果它们都存在于 Classpath 中,则可能必须进行一些额外的配置以告诉 Spring Boot 要创建哪些存储库。 最明确的方法是使用标准的 Spring Data@EnableJpaRepositories@EnableMongoRepositoriesannotations 并提供Repository接口。spring-doc.cadn.net.cn

还有一些标志 (spring.data.*.repositories.enabledspring.data.*.repositories.type),您可以使用该存储库在外部配置中打开和关闭自动配置的存储库。 这样做很有用,例如,如果您想关闭 Mongo 存储库并仍然使用自动配置的MongoTemplate.spring-doc.cadn.net.cn

其他自动配置的 Spring Data 存储库类型(Elasticsearch、Redis 等)存在相同的障碍和相同的功能。 要使用它们,请相应地更改注释和标志的名称。spring-doc.cadn.net.cn

8.13. 自定义 Spring Data 的 Web 支持

Spring Data 提供 Web 支持,可简化 Spring Data 存储库在 Web 应用程序中的使用。 Spring Boot 在spring.data.webnamespace 来自定义其配置。 请注意,如果您使用的是 Spring Data REST,则必须使用spring.data.rest命名空间。spring-doc.cadn.net.cn

8.14. 将 Spring Data Repositories 公开为 REST 端点

Spring Data REST 可以公开Repository实现作为 REST 端点, 前提是已为应用程序启用了 Spring MVC。spring-doc.cadn.net.cn

Spring Boot 公开了一组有用的属性(从spring.data.rest命名空间),自定义RepositoryRestConfiguration. 如果您需要提供额外的自定义,则应使用RepositoryRestConfigurer豆。spring-doc.cadn.net.cn

如果您未在您的自定义上指定任何订单RepositoryRestConfigurer,它在 Spring Boot 内部使用的一个之后运行。 如果需要指定顺序,请确保顺序大于 0。

8.15. 配置 JPA 使用的组件

如果要配置 JPA 使用的组件,则需要确保在 JPA 之前初始化该组件。 当组件被自动配置时, Spring Boot 会为你处理这个问题。 例如,当 Flyway 被自动配置时,Hibernate 被配置为依赖于 Flyway,以便 Flyway 有机会在 Hibernate 尝试使用数据库之前初始化数据库。spring-doc.cadn.net.cn

如果您自己配置组件,则可以使用EntityManagerFactoryDependsOnPostProcessorsubclass 作为设置必要依赖项的便捷方式。 例如,如果您使用 Hibernate Search 并将 Elasticsearch 作为其索引管理器,则任何EntityManagerFactorybean 必须配置为依赖于elasticsearchClientbean,如以下示例所示:spring-doc.cadn.net.cn

Java
import jakarta.persistence.EntityManagerFactory;

import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryDependsOnPostProcessor;
import org.springframework.stereotype.Component;

/**
 * {@link EntityManagerFactoryDependsOnPostProcessor} that ensures that
 * {@link EntityManagerFactory} beans depend on the {@code elasticsearchClient} bean.
 */
@Component
public class ElasticsearchEntityManagerFactoryDependsOnPostProcessor
        extends EntityManagerFactoryDependsOnPostProcessor {

    public ElasticsearchEntityManagerFactoryDependsOnPostProcessor() {
        super("elasticsearchClient");
    }

}
Kotlin
import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryDependsOnPostProcessor
import org.springframework.stereotype.Component

@Component
class ElasticsearchEntityManagerFactoryDependsOnPostProcessor :
    EntityManagerFactoryDependsOnPostProcessor("elasticsearchClient")

8.16. 使用两个数据源配置 jOOQ

如果您需要将 jOOQ 与多个数据源一起使用,则应创建自己的数据源DSLContext对于每个 1 个。 有关更多详细信息,请参阅 JooqAutoConfigurationspring-doc.cadn.net.cn

特别JooqExceptionTranslatorSpringTransactionProvider可以重复使用以提供与自动配置对单个DataSource.

9. 数据库初始化

SQL 数据库可以以不同的方式初始化,具体取决于您的堆栈是什么。 当然,您也可以手动执行此作,前提是数据库是一个单独的过程。 建议使用单个机制来生成架构。spring-doc.cadn.net.cn

9.1. 使用 Hibernate 初始化数据库

您可以设置spring.jpa.hibernate.ddl-auto来控制 Hibernate 的数据库初始化。 支持的值包括none,validate,update,createcreate-drop. Spring Boot 根据您是否使用嵌入式数据库为您选择默认值。 嵌入式数据库是通过查看Connectiontype 和 JDBC url 的 URL 进行验证。hsqldb,h2derby是嵌入式数据库,而其他数据库则不是。 如果识别出嵌入式数据库,但未检测到架构管理器(Flyway 或 Liquibase),则ddl-auto默认为create-drop. 在所有其他情况下,它默认为none.spring-doc.cadn.net.cn

从内存中切换到“真实”数据库时要小心,不要对新平台中存在表和数据做出假设。 您必须将ddl-auto显式或使用其他机制之一来初始化数据库。spring-doc.cadn.net.cn

您可以通过启用org.hibernate.SQL记录。 如果您启用 debug 模式,则会自动为您完成此作。

此外,名为import.sql如果 Hibernate 从头开始创建模式(即,如果ddl-auto属性设置为createcreate-drop). 如果您小心,这对于演示和测试很有用,但可能不是您希望在 production 中的 Classpath 上的内容。 它是一个 Hibernate 功能(与 Spring 无关)。spring-doc.cadn.net.cn

9.2. 使用基本 SQL 脚本初始化数据库

Spring Boot 可以自动创建 JDBC 的模式(DDL 脚本)DataSource或 R2DBCConnectionFactory并初始化其数据(DML 脚本)。spring-doc.cadn.net.cn

默认情况下,它从optional:classpath*:schema.sql和数据脚本optional:classpath*:data.sql. 这些架构和数据脚本的位置可以使用spring.sql.init.schema-locationsspring.sql.init.data-locations分别。 这optional:前缀表示应用程序将在文件不存在时启动。 要使应用程序在文件不存在时无法启动,请删除optional:前缀。spring-doc.cadn.net.cn

此外,Spring Boot 会处理optional:classpath*:schema-${platform}.sqloptional:classpath*:data-${platform}.sql文件(如果存在),其中${platform}的值是spring.sql.init.platform. 这允许您在必要时切换到特定于数据库的脚本。 例如,您可以选择将其设置为数据库的供应商名称 (hsqldb,h2,oracle,mysql,postgresql等)。spring-doc.cadn.net.cn

默认情况下,仅在使用嵌入式内存数据库时执行 SQL 数据库初始化。 要始终初始化 SQL 数据库,而不管其类型如何,请将spring.sql.init.modealways. 同样,要禁用初始化,请将spring.sql.init.modenever. 默认情况下, Spring Boot 启用其基于脚本的数据库初始化器的快速失败功能。 这意味着,如果脚本导致异常,应用程序将无法启动。 您可以通过设置spring.sql.init.continue-on-error.spring-doc.cadn.net.cn

基于脚本DataSource默认情况下,在任何 JPA 之前执行初始化EntityManagerFactorybean 被创建。schema.sql可用于为 JPA 托管的实体创建架构,并且data.sql可用于填充它。 虽然我们不建议使用多个数据源初始化技术,但如果您希望使用基于脚本的DataSource初始化,以便能够在 Hibernate 执行的架构创建的基础上进行构建,请将spring.jpa.defer-datasource-initializationtrue. 这会将数据源初始化推迟到任何EntityManagerFactorybean 已创建并初始化。schema.sql然后,可以用于对 Hibernate 执行的任何模式创建进行添加,并且data.sql可用于填充它。spring-doc.cadn.net.cn

初始化脚本支持单行注释和块注释。 不支持其他注释格式。--/* */

如果您使用的是更高级别的数据库迁移工具,如 Flyway 或 Liquibase,则应单独使用它们来创建和初始化架构。 使用基本schema.sqldata.sql不建议将脚本与 Flyway 或 Liquibase 一起使用,并且在未来版本中将删除支持。spring-doc.cadn.net.cn

如果您需要使用更高级别的数据库迁移工具初始化测试数据,请参阅有关 FlywayLiquibase 的部分。spring-doc.cadn.net.cn

9.3. 初始化 Spring Batch 数据库

如果您使用 Spring Batch,则它预打包了适用于大多数流行数据库平台的 SQL 初始化脚本。 Spring Boot 可以检测您的数据库类型并在启动时执行这些脚本。 如果您使用嵌入式数据库,则默认情况下会发生这种情况。 您还可以为任何数据库类型启用它,如以下示例所示:spring-doc.cadn.net.cn

性能
spring.batch.jdbc.initialize-schema=always
Yaml
spring:
  batch:
    jdbc:
      initialize-schema: "always"

您还可以通过设置spring.batch.jdbc.initialize-schemanever.spring-doc.cadn.net.cn

9.4. 使用更高级别的数据库迁移工具

Spring Boot 支持两个更高级别的迁移工具:FlywayLiquibasespring-doc.cadn.net.cn

9.4.1. 在启动时执行 Flyway 数据库迁移

要在启动时自动运行 Flyway 数据库迁移,请添加org.flywaydb:flyway-core添加到您的 Classpath 中。spring-doc.cadn.net.cn

通常,迁移是格式为V<VERSION>__<NAME>.sql(使用<VERSION>下划线分隔的版本,例如 '1' 或 '2_1')。 默认情况下,它们位于名为classpath:db/migration,但您可以通过设置spring.flyway.locations. 这是一个或多个classpath:filesystem:地点。 例如,以下配置将在默认 classpath 位置和/opt/migration目录:spring-doc.cadn.net.cn

性能
spring.flyway.locations=classpath:db/migration,filesystem:/opt/migration
Yaml
spring:
  flyway:
    locations: "classpath:db/migration,filesystem:/opt/migration"

您还可以添加特殊的{vendor}placeholder 以使用特定于供应商的脚本。 假设以下内容:spring-doc.cadn.net.cn

性能
spring.flyway.locations=classpath:db/migration/{vendor}
Yaml
spring:
  flyway:
    locations: "classpath:db/migration/{vendor}"

而不是使用db/migration中,前面的配置会根据数据库的类型(例如db/migration/mysql用于 MySQL)。 支持的数据库列表位于DatabaseDriver.spring-doc.cadn.net.cn

迁移也可以用 Java 编写。 Flyway 将自动配置任何实现JavaMigration.spring-doc.cadn.net.cn

FlywayProperties提供了 Flyway 的大部分设置和一小部分附加属性,这些属性可用于禁用迁移或关闭位置检查。 如果您需要对配置进行更多控制,请考虑注册FlywayConfigurationCustomizer豆。spring-doc.cadn.net.cn

Spring Boot 调用Flyway.migrate()以执行数据库迁移。 如果您想要更多控制权,请提供@Bean实现FlywayMigrationStrategy.spring-doc.cadn.net.cn

Flyway 支持 SQL 和 Java 回调。 要使用基于 SQL 的回调,请将回调脚本放在classpath:db/migration目录。 要使用基于 Java 的回调,请创建一个或多个实现Callback. 任何此类 bean 都会自动注册到Flyway. 可以使用@Order或通过实施Ordered. 实现已弃用的FlywayCallback接口也可以被检测到,但它们不能与Callback豆。spring-doc.cadn.net.cn

默认情况下,Flyway 会自动将 (@Primary) DataSource并将其用于迁移。 如果您想使用不同的DataSource,您可以创建一个 ID 并标记其@Bean@FlywayDataSource. 如果您这样做并且需要两个数据源,请记住创建另一个数据源并将其标记为@Primary. 或者,您可以使用 Flyway 的原生DataSource通过设置spring.flyway.[url,user,password]在外部属性中。 设置spring.flyway.urlspring.flyway.user足以导致 Flyway 使用自己的DataSource. 如果尚未设置这三个属性中的任何一个,则其等效项的值spring.datasource属性。spring-doc.cadn.net.cn

您还可以使用 Flyway 为特定场景提供数据。 例如,您可以将特定于测试的迁移置于src/test/resources并且它们仅在应用程序启动进行测试时运行。 此外,您还可以使用特定于配置文件的配置来自定义spring.flyway.locations,以便某些迁移仅在特定配置文件处于活动状态时运行。 例如,在application-dev.properties,您可以指定以下设置:spring-doc.cadn.net.cn

性能
spring.flyway.locations=classpath:/db/migration,classpath:/dev/db/migration
Yaml
spring:
  flyway:
    locations: "classpath:/db/migration,classpath:/dev/db/migration"

通过该设置,迁移dev/db/migration仅在dev配置文件处于活动状态。spring-doc.cadn.net.cn

9.4.2. 启动时执行 Liquibase 数据库迁移

要在启动时自动运行 Liquibase 数据库迁移,请添加org.liquibase:liquibase-core添加到您的 Classpath 中。spring-doc.cadn.net.cn

当您添加org.liquibase:liquibase-core添加到您的 Classpath 中,默认情况下,数据库迁移会在应用程序启动期间和测试运行之前运行。 可以使用spring.liquibase.enabled属性,在maintest配置。 不能使用两种不同的方法来初始化数据库(例如,Liquibase 用于应用程序启动,JPA 用于测试运行)。spring-doc.cadn.net.cn

默认情况下,主更改日志是从db/changelog/db.changelog-master.yaml,但您可以通过设置spring.liquibase.change-log. 除了 YAML,Liquibase 还支持 JSON、XML 和 SQL 更改日志格式。spring-doc.cadn.net.cn

默认情况下,Liquibase 会自动将 (@Primary) DataSource并将其用于迁移。 如果您需要使用不同的DataSource,您可以创建一个 ID 并标记其@Bean@LiquibaseDataSource. 如果您这样做并且需要两个数据源,请记住创建另一个数据源并将其标记为@Primary. 或者,您可以使用 Liquibase 的原生DataSource通过设置spring.liquibase.[driver-class-name,url,user,password]在外部属性中。 设置spring.liquibase.urlspring.liquibase.user足以使 Liquibase 使用自己的DataSource. 如果尚未设置这三个属性中的任何一个,则其等效项的值spring.datasource属性。spring-doc.cadn.net.cn

LiquibaseProperties了解有关可用设置(如上下文、默认架构等)的详细信息。spring-doc.cadn.net.cn

9.4.3. 使用 Flyway 进行仅测试迁移

如果要创建填充测试数据库的 Flyway 迁移,请将它们放在src/test/resources/db/migration. 例如,名为src/test/resources/db/migration/V9999__test-data.sql将在您的生产迁移之后执行,并且仅在您运行测试时执行。 您可以使用此文件创建所需的测试数据。 此文件不会打包到您的 uber jar 或容器中。spring-doc.cadn.net.cn

9.4.4. 使用 Liquibase 进行仅测试迁移

如果要创建填充测试数据库的 Liquibase 迁移,则必须创建一个测试更改日志,其中还包括生产更改日志。spring-doc.cadn.net.cn

首先,您需要将 Liquibase 配置为在运行测试时使用不同的更改日志。 一种方法是创建 Spring Boottestprofile 并将 Liquibase 属性放入其中。 为此,请创建一个名为src/test/resources/application-test.properties并将以下属性放入其中:spring-doc.cadn.net.cn

性能
spring.liquibase.change-log=classpath:/db/changelog/db.changelog-test.yaml
Yaml
spring:
  liquibase:
    change-log: "classpath:/db/changelog/db.changelog-test.yaml"

这会将 Liquibase 配置为在test轮廓。spring-doc.cadn.net.cn

现在在src/test/resources/db/changelog/db.changelog-test.yaml:spring-doc.cadn.net.cn

databaseChangeLog:
  - include:
      file: classpath:/db/changelog/db.changelog-master.yaml
  - changeSet:
      runOrder: "last"
      id: "test"
      changes:
        # Insert your changes here

此更改日志将在运行测试时使用,并且不会打包在您的 uber jar 或容器中。 它包括生产变更日志,然后声明一个新的变更集,其runOrder: lastsetting 指定它在运行所有 production 变更集之后运行。 例如,您现在可以使用 insert 变更集来插入数据,或者使用 sql 变更集直接执行 SQL。spring-doc.cadn.net.cn

最后要做的是配置 Spring Boot 以激活test配置文件。 为此,您可以添加@ActiveProfiles("test")注解添加到您的@SpringBootTest带注释的测试类。spring-doc.cadn.net.cn

9.5. 依赖于初始化的数据库

数据库初始化是在应用程序启动时作为应用程序上下文刷新的一部分执行的。 为了允许在启动期间访问已初始化的数据库,将自动检测充当数据库初始值设定项的 bean 和需要初始化该数据库的 bean。 其初始化依赖于已初始化数据库的 Bean 被配置为依赖于初始化它的 Bean。 如果在启动期间,应用程序尝试访问数据库,但尚未初始化数据库,则可以配置对 bean 的其他检测,这些 bean 初始化数据库并要求已初始化数据库。spring-doc.cadn.net.cn

9.5.1. 检测数据库初始化器

Spring Boot 将自动检测初始化 SQL 数据库的以下类型的 bean:spring-doc.cadn.net.cn

如果你将第三方Starters用于数据库初始化库,它可能会提供一个检测器,以便也自动检测其他类型的 bean。 要检测其他 bean,请注册DatabaseInitializerDetectorMETA-INF/spring.factories.spring-doc.cadn.net.cn

9.5.2. 检测依赖于数据库初始化的 bean

Spring Boot 将自动检测依赖于数据库初始化的以下类型的 bean:spring-doc.cadn.net.cn

如果您使用的是第三方入门数据访问库,则它可能会提供一个检测器,以便也会自动检测其他类型的 bean。 要检测其他 bean,请注册DependsOnDatabaseInitializationDetectorMETA-INF/spring.factories. 或者,对 Bean 的类或其@Beanmethod 替换为@DependsOnDatabaseInitialization.spring-doc.cadn.net.cn

10. 无SQL

Spring Boot 提供了许多支持 NoSQL 技术的Starters。 本节回答了将 NoSQL 与 Spring Boot 结合使用时出现的问题。spring-doc.cadn.net.cn

10.1. 用 Jedis 代替 Lettuce

默认情况下,Spring Boot Starters(spring-boot-starter-data-redis) 使用 Lettuce。 您需要排除该依赖项并包含 Jedis 依赖项。 Spring Boot 管理这两个依赖项,因此您可以在不指定版本的情况下切换到 Jedis。spring-doc.cadn.net.cn

以下示例展示了如何在 Maven 中执行此作:spring-doc.cadn.net.cn

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

以下示例显示了如何在 Gradle 中执行此作:spring-doc.cadn.net.cn

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-data-redis') {
        exclude group: 'io.lettuce', module: 'lettuce-core'
    }
    implementation 'redis.clients:jedis'
    // ...
}

11. 消息

Spring Boot 提供了许多 starter 来支持消息传递。 本节回答了在 Spring Boot 中使用消息传递时出现的问题。spring-doc.cadn.net.cn

11.1. 禁用事务处理的 JMS 会话

如果您的 JMS 代理不支持事务处理会话,则必须完全禁用对事务的支持。 如果您创建自己的JmsListenerContainerFactory,无需执行任何作,因为默认情况下它无法进行交易。 如果要使用DefaultJmsListenerContainerFactoryConfigurer要重用 Spring Boot 的默认值,您可以禁用事务处理会话,如下所示:spring-doc.cadn.net.cn

Java
import jakarta.jms.ConnectionFactory;

import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;

@Configuration(proxyBeanMethods = false)
public class MyJmsConfiguration {

    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory,
            DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory listenerFactory = new DefaultJmsListenerContainerFactory();
        configurer.configure(listenerFactory, connectionFactory);
        listenerFactory.setTransactionManager(null);
        listenerFactory.setSessionTransacted(false);
        return listenerFactory;
    }

}
Kotlin
import jakarta.jms.ConnectionFactory
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.jms.config.DefaultJmsListenerContainerFactory

@Configuration(proxyBeanMethods = false)
class MyJmsConfiguration {

    @Bean
    fun jmsListenerContainerFactory(connectionFactory: ConnectionFactory?,
            configurer: DefaultJmsListenerContainerFactoryConfigurer): DefaultJmsListenerContainerFactory {
        val listenerFactory = DefaultJmsListenerContainerFactory()
        configurer.configure(listenerFactory, connectionFactory)
        listenerFactory.setTransactionManager(null)
        listenerFactory.setSessionTransacted(false)
        return listenerFactory
    }

}

前面的示例覆盖了默认工厂,并且它应该应用于您的应用程序定义的任何其他工厂(如果有)。spring-doc.cadn.net.cn

12. 批量申请

当人们从 Spring Boot 应用程序中使用 Spring Batch 时,经常会出现许多问题。 本节将解决这些问题。spring-doc.cadn.net.cn

12.1. 指定批处理数据源

默认情况下,批处理应用程序需要一个DataSource以存储作业详细信息。 Spring Batch 需要一个DataSource默认情况下。 要让它使用DataSource除了应用程序的 mainDataSource,声明一个DataSourcebean,为其@Beanmethod 替换为@BatchDataSource. 如果您这样做并且需要两个数据源,请记住标记另一个数据源@Primary. 要获得更大的控制权,请添加@EnableBatchProcessing到你的@Configuration类或 extendDefaultBatchConfiguration. 请参阅 Javadoc@EnableBatchProcessingDefaultBatchConfiguration了解更多详情。spring-doc.cadn.net.cn

有关 Spring Batch 的更多信息,请参阅 Spring Batch 项目页面spring-doc.cadn.net.cn

12.2. 在启动时运行 Spring Batch 作业

Spring Batch 自动配置是通过添加spring-boot-starter-batch添加到应用程序的 Classpath 中。spring-doc.cadn.net.cn

如果单个Job在应用程序上下文中找到,则会在启动时执行(请参阅JobLauncherApplicationRunner了解详情)。 如果多个Jobbean 中,必须使用spring.batch.job.name.spring-doc.cadn.net.cn

要禁用运行Job在应用程序上下文中,将spring.batch.job.enabledfalse.spring-doc.cadn.net.cn

有关更多详细信息,请参阅 BatchAutoConfigurationspring-doc.cadn.net.cn

12.3. 从命令行运行

Spring Boot 将任何以 开头的命令行参数转换为要添加到--Environment,请参阅访问命令行属性。 这不应用于将参数传递给批处理作业。 要在命令行上指定批处理参数,请使用常规格式(即 without ),如以下示例所示:--spring-doc.cadn.net.cn

$ java -jar myapp.jar someParameter=someValue anotherParameter=anotherValue

如果指定Environment在命令行中,作业将忽略它。 请考虑以下命令:spring-doc.cadn.net.cn

$ java -jar myapp.jar --server.port=7070 someParameter=someValue

这仅向批处理作业提供一个参数:someParameter=someValue.spring-doc.cadn.net.cn

12.4. 重启已停止或失败的作业

重新启动失败的Job,则必须在命令行上重新指定所有参数(标识和非标识)。 非标识参数不会从上一次执行中复制。 这允许修改或删除它们。spring-doc.cadn.net.cn

当您使用自定义JobParametersIncrementer,您必须收集 Incrementer 管理的所有参数才能重新启动失败的执行。

12.5. 存储 Job 仓库

Spring Batch 需要一个数据存储Job存储 库。 如果使用 Spring Boot,则必须使用实际的数据库。 请注意,它可以是内存数据库,请参阅配置 Job Repositoryspring-doc.cadn.net.cn

13. 执行器

Spring Boot 包括 Spring Boot Actuator。 本节回答了使用它时经常出现的问题。spring-doc.cadn.net.cn

13.1. 更改 Actuator 端点的 HTTP 端口或地址

在独立应用程序中,Actuator HTTP 端口默认与主 HTTP 端口相同。 要使应用程序侦听其他端口,请设置 external 属性:management.server.port. 要侦听完全不同的网络地址(例如,当您有一个用于管理的内部网络和一个用于用户应用程序的外部网络时),您还可以设置management.server.address设置为服务器能够绑定到的有效 IP 地址。spring-doc.cadn.net.cn

有关更多详细信息,请参阅ManagementServerProperties源代码和“生产就绪功能”部分中的“actuator.html”。spring-doc.cadn.net.cn

13.2. 自定义 'whitelabel' 错误页面

Spring Boot 会安装一个“whitelabel”错误页面,如果您遇到服务器错误,您会在浏览器客户端中看到该页面(使用 JSON 和其他媒体类型的机器客户端应该看到带有正确错误代码的合理响应)。spring-doc.cadn.net.cn

设置server.error.whitelabel.enabled=false以关闭默认错误页面。 这样做将恢复您正在使用的 Servlet 容器的默认值。 请注意, Spring Boot 仍然尝试解决错误视图,因此您可能应该添加自己的错误页面,而不是完全禁用它。

用您自己的页面覆盖错误页面取决于您使用的模板技术。 例如,如果使用 Thymeleaf,则可以添加error.html模板。 如果您使用 FreeMarker,则可以添加error.ftlh模板。 通常,您需要一个View解析为名称error@Controller处理/error路径。 除非您替换了一些默认配置,否则您应该会找到一个BeanNameViewResolverApplicationContext,因此@Beanerror将是做到这一点的一种方式。 看ErrorMvcAutoConfiguration以获取更多选项。spring-doc.cadn.net.cn

有关如何在 Servlet 容器中注册处理程序的详细信息,另请参阅“错误处理”部分。spring-doc.cadn.net.cn

13.3. 自定义 Sanitization

要控制清理,请定义一个SanitizingFunction豆。 这SanitizableData调用函数时,提供对 key 和 value 的访问,以及PropertySource他们从那里来。 例如,这允许您清理来自特定属性源的每个值。 每SanitizingFunction按顺序调用,直到函数更改可清理数据的值。spring-doc.cadn.net.cn

13.4. 将健康指标映射到 Micrometer 指标

Spring Boot 运行状况指示器返回一个Status键入以指示整体系统运行状况。 如果要监控特定应用程序的运行状况级别或发出警报,可以使用 Micrometer 将这些状态导出为指标。 默认情况下,Spring Boot 使用状态代码 “UP”、“DOWN”、“OUT_OF_SERVICE” 和 “UNKNOWN”。 要导出这些,您需要将这些状态转换为一组数字,以便它们可以与 Micrometer 一起使用Gauge.spring-doc.cadn.net.cn

以下示例显示了编写此类 exporter 的一种方法:spring-doc.cadn.net.cn

Java
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;

import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.health.Status;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyHealthMetricsExportConfiguration {

    public MyHealthMetricsExportConfiguration(MeterRegistry registry, HealthEndpoint healthEndpoint) {
        // This example presumes common tags (such as the app) are applied elsewhere
        Gauge.builder("health", healthEndpoint, this::getStatusCode).strongReference(true).register(registry);
    }

    private int getStatusCode(HealthEndpoint health) {
        Status status = health.health().getStatus();
        if (Status.UP.equals(status)) {
            return 3;
        }
        if (Status.OUT_OF_SERVICE.equals(status)) {
            return 2;
        }
        if (Status.DOWN.equals(status)) {
            return 1;
        }
        return 0;
    }

}
Kotlin
import io.micrometer.core.instrument.Gauge
import io.micrometer.core.instrument.MeterRegistry
import org.springframework.boot.actuate.health.HealthEndpoint
import org.springframework.boot.actuate.health.Status
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyHealthMetricsExportConfiguration(registry: MeterRegistry, healthEndpoint: HealthEndpoint) {

    init {
        // This example presumes common tags (such as the app) are applied elsewhere
        Gauge.builder("health", healthEndpoint) { health ->
            getStatusCode(health).toDouble()
        }.strongReference(true).register(registry)
    }

    private fun getStatusCode(health: HealthEndpoint): Int {
        return when (health.health().status) {
            Status.UP -> 3
            Status.OUT_OF_SERVICE -> 2
            Status.DOWN -> 1
            else -> 0
        }
    }

}

14. 安全

本节解决使用 Spring Boot 时的安全性问题,包括将 Spring Security 与 Spring Boot 一起使用时出现的问题。spring-doc.cadn.net.cn

有关 Spring Security 的更多信息,请参阅 Spring Security 项目页面spring-doc.cadn.net.cn

14.1. 关闭 Spring Boot 安全配置

如果您定义了@Configuration替换为SecurityFilterChainbean 时,它会关闭 Spring Boot 中的默认 webapp 安全设置。spring-doc.cadn.net.cn

14.2. 更改 UserDetailsService 并添加用户帐户

如果您提供@Bean的类型AuthenticationManager,AuthenticationProviderUserDetailsService,则默认的@BeanInMemoryUserDetailsManager未创建。 这意味着您拥有可用的 Spring Security 的完整功能集(例如各种身份验证选项)。spring-doc.cadn.net.cn

添加用户帐户的最简单方法是提供您自己的帐户UserDetailsService豆。spring-doc.cadn.net.cn

14.3. 在 Proxy Server 后面运行时启用 HTTPS

确保所有主要终端节点仅通过 HTTPS 可用,对于任何应用程序来说都是一项重要的苦差事。 如果你使用 Tomcat 作为 servlet 容器,那么 Spring Boot 会添加 Tomcat 自己的RemoteIpValve如果检测到某些环境设置,则自动执行此作,并且您应该能够依赖HttpServletRequest报告它是否安全(甚至在处理实际 SSL 终止的代理服务器的下游)。 标准行为由某些请求标头 (x-forwarded-forx-forwarded-proto),其名称是约定俗成的,因此它应该适用于大多数前端代理。 您可以通过在application.properties,如以下示例所示:spring-doc.cadn.net.cn

性能
server.tomcat.remoteip.remote-ip-header=x-forwarded-for
server.tomcat.remoteip.protocol-header=x-forwarded-proto
Yaml
server:
  tomcat:
    remoteip:
      remote-ip-header: "x-forwarded-for"
      protocol-header: "x-forwarded-proto"

(这些属性中的任何一个的存在都会打开阀门。 或者,您也可以添加RemoteIpValve通过自定义TomcatServletWebServerFactory使用WebServerFactoryCustomizerbean。spring-doc.cadn.net.cn

要将 Spring Security 配置为要求所有(或部分)请求都使用安全通道,请考虑添加您自己的SecurityFilterChainbean 添加以下内容HttpSecurity配置:spring-doc.cadn.net.cn

Java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class MySecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // Customize the application security ...
        http.requiresChannel((channel) -> channel.anyRequest().requiresSecure());
        return http.build();
    }

}
Kotlin
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.SecurityFilterChain

@Configuration
class MySecurityConfig {

    @Bean
    fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
        // Customize the application security ...
        http.requiresChannel { requests -> requests.anyRequest().requiresSecure() }
        return http.build()
    }

}

15. 热插拔

Spring Boot 支持热插拔。 本节回答了有关其工作原理的问题。spring-doc.cadn.net.cn

15.1. 重新加载静态内容

热重载有多种选择。 推荐的方法是使用spring-boot-devtools,因为它提供了额外的开发时功能,例如支持快速应用程序重启和 LiveReload,以及合理的开发时配置(例如模板缓存)。 Devtools 通过监视 Classpath 的更改来工作。 这意味着必须 “构建” 静态资源更改才能使更改生效。 默认情况下,在 Eclipse 中,当您保存更改时,这会自动发生。 在 IntelliJ IDEA 中,Make Project 命令会触发必要的构建。 由于默认的重启排除项,对静态资源的更改不会触发应用程序的重启。 但是,它们确实会触发实时重新加载。spring-doc.cadn.net.cn

或者,在 IDE 中运行(尤其是在调试时)是进行开发的好方法(所有现代 IDE 都允许重新加载静态资源,通常还允许热交换 Java 类更改)。spring-doc.cadn.net.cn

最后,可以配置 Maven 和 Gradle 插件(请参阅addResources属性),以支持从命令行运行并直接从源重新加载静态文件。 如果您正在使用更高级别的工具编写该代码,则可以将其与外部 css/js 编译器进程一起使用。spring-doc.cadn.net.cn

15.2. 在不重启容器的情况下重新加载模板

Spring Boot 支持的大多数模板技术都包含一个用于禁用缓存的配置选项(本文档稍后将介绍)。 如果您使用spring-boot-devtools模块中,这些属性将在开发时自动为您配置spring-doc.cadn.net.cn

15.2.1. Thymeleaf 模板

如果使用 Thymeleaf,请将spring.thymeleaf.cachefalse. 看ThymeleafAutoConfiguration对于其他 Thymeleaf 自定义选项。spring-doc.cadn.net.cn

15.2.2. FreeMarker 模板

如果您使用 FreeMarker,请将spring.freemarker.cachefalse. 看FreeMarkerAutoConfiguration了解其他 FreeMarker 自定义选项。spring-doc.cadn.net.cn

15.2.3. Groovy 模板

如果您使用 Groovy 模板,请将spring.groovy.template.cachefalse. 看GroovyTemplateAutoConfiguration了解其他 Groovy 自定义选项。spring-doc.cadn.net.cn

15.3. 应用程序快速重启

spring-boot-devtools模块包括对应用程序自动重启的支持。 虽然不如 JRebel 等技术快,但它通常比“冷启动”快得多。 在研究本文档后面讨论的一些更复杂的重新加载选项之前,您可能应该先尝试一下。spring-doc.cadn.net.cn

有关更多详细信息,请参阅 using.html 部分。spring-doc.cadn.net.cn

15.4. 在不重新启动容器的情况下重新加载 Java 类

许多现代 IDE(Eclipse、IDEA 等)都支持字节码的热交换。 因此,如果您所做的更改不会影响类或方法签名,它应该会干净地重新加载,而不会产生任何副作用。spring-doc.cadn.net.cn

16. 测试

Spring Boot 包括许多测试实用程序和支持类,以及一个提供常见测试依赖项的专用Starters。 本节回答有关测试的常见问题。spring-doc.cadn.net.cn

16.1. 使用 Spring Security 进行测试

Spring Security 支持以特定用户身份运行测试。 例如,下面代码段中的测试将使用具有ADMIN角色。spring-doc.cadn.net.cn

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

@WebMvcTest(UserController.class)
class MySecurityTests {

    @Autowired
    private MockMvc mvc;

    @Test
    @WithMockUser(roles = "ADMIN")
    void requestProtectedUrlWithUser() throws Exception {
        this.mvc.perform(get("/"));
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.security.test.context.support.WithMockUser
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders

@WebMvcTest(UserController::class)
class MySecurityTests(@Autowired val mvc: MockMvc) {

    @Test
    @WithMockUser(roles = ["ADMIN"])
    fun requestProtectedUrlWithUser() {
        mvc.perform(MockMvcRequestBuilders.get("/"))
    }

}

Spring Security 提供了与 Spring MVC Test 的全面集成,这也可以在使用@WebMvcTestslice 和MockMvc.spring-doc.cadn.net.cn

有关 Spring Security 的测试支持的更多详细信息,请参阅 Spring Security 的参考文档spring-doc.cadn.net.cn

16.2. 结构@Configuration包含在切片测试中的类

切片测试的工作原理是将 Spring Framework 的组件扫描限制为基于其类型的一组有限的组件。 对于不是通过组件扫描创建的任何 bean,例如,使用@Bean注解,切片测试将无法在应用程序上下文中包含/排除它们。 请考虑以下示例:spring-doc.cadn.net.cn

import org.apache.commons.dbcp2.BasicDataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration(proxyBeanMethods = false)
public class MyConfiguration {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated());
        return http.build();
    }

    @Bean
    @ConfigurationProperties("app.datasource.second")
    public BasicDataSource secondDataSource() {
        return DataSourceBuilder.create().type(BasicDataSource.class).build();
    }

}

对于@WebMvcTest对于具有上述@Configuration类中,您可能希望具有SecurityFilterChainbean 中,以便您可以测试控制器端点是否得到正确保护。 然而MyConfiguration不会被 @WebMvcTest 的组件扫描筛选条件选取,因为它与筛选条件指定的任何类型都不匹配。 您可以通过使用@Import(MyConfiguration.class). 这将加载MyConfiguration包括BasicDataSourcebean 中,这在测试 Web 层时不是必需的。 将 configuration 类拆分为两个将允许仅导入 security configuration。spring-doc.cadn.net.cn

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated());
        return http.build();
    }

}
import org.apache.commons.dbcp2.BasicDataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyDatasourceConfiguration {

    @Bean
    @ConfigurationProperties("app.datasource.second")
    public BasicDataSource secondDataSource() {
        return DataSourceBuilder.create().type(BasicDataSource.class).build();
    }

}

当需要将某个域的 bean 包含在 slice 测试中时,拥有单个配置类可能效率低下。 相反,将应用程序的配置构建为具有特定域的 bean 的多个细粒度类可以允许仅针对特定切片测试导入它们。spring-doc.cadn.net.cn

17. 构建

Spring Boot 包括适用于 Maven 和 Gradle 的构建插件。 本节回答了有关这些插件的常见问题。spring-doc.cadn.net.cn

17.1. 生成构建信息

Maven 插件和 Gradle 插件都允许生成包含项目坐标、名称和版本的构建信息。 还可以将插件配置为通过配置添加其他属性。 当存在这样的文件时, Spring Boot 会自动配置BuildProperties豆。spring-doc.cadn.net.cn

要使用 Maven 生成构建信息,请为build-info目标,如以下示例所示:spring-doc.cadn.net.cn

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>3.1.12</version>
            <executions>
                <execution>
                    <goals>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
有关更多详细信息,请参阅 Spring Boot Maven Plugin 文档

以下示例对 Gradle 执行相同的作:spring-doc.cadn.net.cn

springBoot {
    buildInfo()
}
有关更多详细信息,请参阅 Spring Boot Gradle Plugin 文档

17.2. 生成 Git 信息

Maven 和 Gradle 都允许生成git.properties文件,其中包含有关git源代码存储库。spring-doc.cadn.net.cn

对于 Maven 用户,spring-boot-starter-parentPOM 包括一个预配置的插件,用于生成git.properties文件。 要使用它,请为Git Commit Id Plugin添加到您的 POM 中:spring-doc.cadn.net.cn

<build>
    <plugins>
        <plugin>
            <groupId>io.github.git-commit-id</groupId>
            <artifactId>git-commit-id-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Gradle 用户可以通过使用gradle-git-propertiesplugin,如以下示例所示:spring-doc.cadn.net.cn

plugins {
    id "com.gorylenko.gradle-git-properties" version "2.4.1"
}

Maven 和 Gradle 插件都允许git.properties进行配置。spring-doc.cadn.net.cn

提交时间git.properties应匹配以下格式:yyyy-MM-dd’T’HH:mm:ssZ. 这是上面列出的两个插件的默认格式。 使用这种格式可以将时间解析为Date及其格式(序列化为 JSON 时)由 Jackson 的日期序列化配置设置控制。

17.3. 自定义依赖项版本

spring-boot-dependenciesPOM 管理常见依赖项的版本。 适用于 Maven 和 Gradle 的 Spring Boot 插件允许使用 build 属性自定义这些托管依赖项版本。spring-doc.cadn.net.cn

每个 Spring Boot 版本都是针对这组特定的第三方依赖项进行设计和测试的。 覆盖版本可能会导致兼容性问题。

要使用 Maven 覆盖依赖项版本,请参阅 Maven 插件文档的此部分spring-doc.cadn.net.cn

如需覆盖 Gradle 中的依赖项版本,请参阅 Gradle 插件文档的此部分spring-doc.cadn.net.cn

17.4. 使用 Maven 创建可执行 JAR

spring-boot-maven-plugin可用于创建可执行的 “fat” JAR。 如果您使用spring-boot-starter-parentPOM 中,你可以声明插件,你的 jar 会被重新打包,如下所示:spring-doc.cadn.net.cn

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

如果您不使用父 POM,您仍然可以使用该插件。 但是,您还必须添加<executions>部分,如下所示:spring-doc.cadn.net.cn

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>3.1.12</version>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

有关完整的使用详情,请参阅插件文档spring-doc.cadn.net.cn

17.5. 使用 Spring Boot 应用程序作为依赖项

与 war 文件一样, Spring Boot 应用程序不打算用作依赖项。 如果您的应用程序包含要与其他项目共享的类,则建议的方法是将该代码移动到单独的模块中。 然后,您的应用程序和其他项目可以依赖单独的模块。spring-doc.cadn.net.cn

如果您无法按照上述建议重新排列代码,则必须将 Spring Boot 的 Maven 和 Gradle 插件配置为生成适合用作依赖项的单独工件。 可执行存档不能用作依赖项,因为可执行 jar 格式将应用程序类打包在BOOT-INF/classes. 这意味着当可执行 jar 用作依赖项时,无法找到它们。spring-doc.cadn.net.cn

要生成两个工件,一个可用作依赖项,另一个可用作可执行文件,必须指定分类器。 此分类器应用于可执行存档的名称,将默认存档用作依赖项。spring-doc.cadn.net.cn

配置exec在 Maven 中,您可以使用以下配置:spring-doc.cadn.net.cn

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

17.6. 在可执行 jar 运行时提取特定库

可执行 jar 中的大多数嵌套库不需要解压缩即可运行。 但是,某些库可能会出现问题。 例如,JRuby 包含自己的嵌套 jar 支持,它假定jruby-complete.jar始终以文件形式直接提供。spring-doc.cadn.net.cn

要处理任何有问题的库,您可以标记特定的嵌套 jar 应在可执行 jar 首次运行时自动解压缩。 此类嵌套 jar 写入由java.io.tmpdirsystem 属性。spring-doc.cadn.net.cn

应注意确保您的作系统已配置,以便在应用程序仍在运行时不会删除已解压缩到临时目录的 jar。

例如,要指示应使用 Maven 插件将 JRuby 标记为解包,您可以添加以下配置:spring-doc.cadn.net.cn

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <requiresUnpack>
                    <dependency>
                        <groupId>org.jruby</groupId>
                        <artifactId>jruby-complete</artifactId>
                    </dependency>
                </requiresUnpack>
            </configuration>
        </plugin>
    </plugins>
</build>

17.7. 创建带有 Exclusions 的不可执行 JAR

通常,如果您将可执行文件和不可执行 jar 作为两个单独的构建产品,则可执行版本具有库 jar 中不需要的其他配置文件。 例如,application.yaml配置文件可能已从不可执行的 JAR 中排除。spring-doc.cadn.net.cn

在 Maven 中,可执行 jar 必须是主对象,您可以为库添加分类 jar,如下所示:spring-doc.cadn.net.cn

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <executions>
                <execution>
                    <id>lib</id>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <configuration>
                        <classifier>lib</classifier>
                        <excludes>
                            <exclude>application.yaml</exclude>
                        </excludes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

17.8. 远程调试使用 Maven 启动的 Spring Boot 应用程序

要将远程调试器附加到使用 Maven 启动的 Spring Boot 应用程序,可以使用jvmArgumentsMaven 插件的属性。spring-doc.cadn.net.cn

有关更多详细信息,请参阅此示例spring-doc.cadn.net.cn

17.9. 从 Ant 构建可执行档案,而不使用 spring-boot-antlib

要使用 Ant 进行构建,您需要获取依赖项、编译,然后创建 jar 或 war 存档。 要使其可执行,您可以使用spring-boot-antlib模块,或者您可以按照以下说明作:spring-doc.cadn.net.cn

  1. 如果要构建 jar,请将应用程序的类和资源打包到嵌套的BOOT-INF/classes目录。 如果要构建 war,请将应用程序的类打包到嵌套的WEB-INF/classes目录中。spring-doc.cadn.net.cn

  2. 在嵌套的BOOT-INF/libdirectory 或WEB-INF/lib为了一场战争。 切记不要压缩存档中的条目。spring-doc.cadn.net.cn

  3. 添加provided(embedded container) 依赖项BOOT-INF/libdirectory 或WEB-INF/lib-provided为了一场战争。 切记不要压缩存档中的条目。spring-doc.cadn.net.cn

  4. 添加spring-boot-loader类(以便Main-Class可用)。spring-doc.cadn.net.cn

  5. 使用适当的Starters(例如JarLauncher)作为Main-Class属性,并指定它需要作为清单条目的其他属性 — 主要是通过设置Start-Class财产。spring-doc.cadn.net.cn

以下示例演示如何使用 Ant 构建可执行存档:spring-doc.cadn.net.cn

<target name="build" depends="compile">
    <jar destfile="target/${ant.project.name}-${spring-boot.version}.jar" compress="false">
        <mappedresources>
            <fileset dir="target/classes" />
            <globmapper from="*" to="BOOT-INF/classes/*"/>
        </mappedresources>
        <mappedresources>
            <fileset dir="src/main/resources" erroronmissingdir="false"/>
            <globmapper from="*" to="BOOT-INF/classes/*"/>
        </mappedresources>
        <mappedresources>
            <fileset dir="${lib.dir}/runtime" />
            <globmapper from="*" to="BOOT-INF/lib/*"/>
        </mappedresources>
        <zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
        <manifest>
            <attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
            <attribute name="Start-Class" value="${start-class}" />
        </manifest>
    </jar>
</target>

18. 提前处理

当人们使用 Spring Boot 应用程序的预先处理时,经常会出现许多问题。 本节将解决这些问题。spring-doc.cadn.net.cn

18.1. 条件

预先处理可优化应用程序,并在构建时根据环境评估条件配置文件是通过条件实现的,因此也会受到影响。spring-doc.cadn.net.cn

如果希望 bean 是基于预先优化的应用程序中的条件创建的,则必须在构建应用程序时设置环境。 在构建时提前处理时创建的 bean 始终在运行应用程序时创建,并且无法关闭。 为此,您可以设置构建应用程序时应使用的配置文件。spring-doc.cadn.net.cn

对于 Maven,这是通过设置profiles的配置spring-boot-maven-plugin:process-aot执行:spring-doc.cadn.net.cn

<profile>
    <id>native</id>
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>process-aot</id>
                            <configuration>
                                <profiles>profile-a,profile-b</profiles>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</profile>

对于 Gradle,您需要配置ProcessAot任务:spring-doc.cadn.net.cn

tasks.withType(org.springframework.boot.gradle.tasks.aot.ProcessAot).configureEach {
    args('--spring.profiles.active=profile-a,profile-b')
}

在运行预先优化的应用程序时,仅支持更改不影响条件的配置属性的配置文件,而不受限制。spring-doc.cadn.net.cn

19. 传统部署

Spring Boot 支持传统部署以及更现代的部署形式。 本节解答了有关传统部署的常见问题。spring-doc.cadn.net.cn

19.1. 创建一个可部署的 war 文件

因为 Spring WebFlux 并不严格依赖于 servlet API,而且应用程序默认部署在嵌入式 Reactor Netty 服务器上,所以 WebFlux 应用程序不支持 War 部署。

生成可部署的 war 文件的第一步是提供SpringBootServletInitializer子类并覆盖其configure方法。 这样做利用了 Spring Framework 的 servlet 3.0 支持,并允许您在 servlet 容器启动应用程序时对其进行配置。 通常,您应该更新应用程序的 main 类以扩展SpringBootServletInitializer,如以下示例所示:spring-doc.cadn.net.cn

Java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(MyApplication.class);
    }

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

}
Kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.runApplication
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer

@SpringBootApplication
class MyApplication : SpringBootServletInitializer() {

    override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder {
        return application.sources(MyApplication::class.java)
    }

}

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

下一步是更新您的构建配置,以便您的项目生成 war 文件而不是 jar 文件。 如果您使用 Maven 和spring-boot-starter-parent(为你配置 Maven 的 war 插件),你需要做的就是修改pom.xml将打包更改为 war,如下所示:spring-doc.cadn.net.cn

<packaging>war</packaging>

如果使用 Gradle,则需要修改build.gradle将 War 插件应用于项目,如下所示:spring-doc.cadn.net.cn

apply plugin: 'war'

该过程的最后一步是确保嵌入式 servlet 容器不会干扰 war 文件部署到的 servlet 容器。 为此,您需要将嵌入式 servlet 容器依赖项标记为已提供。spring-doc.cadn.net.cn

如果使用 Maven,以下示例将 Servlet 容器(在本例中为 Tomcat)标记为已提供:spring-doc.cadn.net.cn

<dependencies>
    <!-- ... -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <!-- ... -->
</dependencies>

如果使用 Gradle,以下示例将 servlet 容器(在本例中为 Tomcat)标记为已提供:spring-doc.cadn.net.cn

dependencies {
    // ...
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    // ...
}
providedRuntime比 Gradle 的compileOnly配置。 除其他限制外,compileOnly依赖项不在测试 Classpath 上,因此任何基于 Web 的集成测试都会失败。

如果使用 Spring Boot 构建工具,则将嵌入式 servlet 容器依赖项标记为 provided 会生成一个可执行的 war 文件,其中提供的依赖项打包在lib-provided目录。 这意味着,除了可部署到 servlet 容器之外,您还可以使用java -jar在命令行上。spring-doc.cadn.net.cn

19.2. 将现有应用程序转换为 Spring Boot

要将现有的非 Web Spring 应用程序转换为 Spring Boot 应用程序,请将创建ApplicationContext并将其替换为对SpringApplicationSpringApplicationBuilder. Spring MVC Web 应用程序通常适合先创建一个可部署的 war 应用程序,然后再将其迁移到可执行的 war 或 jar 中。 请参阅有关将 jar 转换为 war 的入门指南spring-doc.cadn.net.cn

通过扩展来创建可部署的 warSpringBootServletInitializer(例如,在名为Application) 并添加 Spring Boot@SpringBootApplicationannotation 中,请使用类似于以下示例中所示的代码:spring-doc.cadn.net.cn

Java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        // Customize the application or call application.sources(...) to add sources
        // Since our example is itself a @Configuration class (through
        // @SpringBootApplication)
        // we actually do not need to override this method.
        return application;
    }


}
Kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.runApplication
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer

@SpringBootApplication
class MyApplication : SpringBootServletInitializer() {

    override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder {
        // Customize the application or call application.sources(...) to add sources
        // Since our example is itself a @Configuration class (through @SpringBootApplication)
        // we actually do not need to override this method.
        return application
    }

}

请记住,无论您将sources只是一个弹簧ApplicationContext. 通常,任何已经有效的内容都应该在这里工作。 可能有一些 bean 你可以稍后删除,并让 Spring Boot 为它们提供自己的默认值,但是在你需要这样做之前,应该可以让一些东西工作。spring-doc.cadn.net.cn

静态资源可以移动到/public(或/static/resources/META-INF/resources) 的 API 中。 这同样适用于messages.properties(Spring Boot 在 Classpath 的根目录中自动检测到)。spring-doc.cadn.net.cn

Spring 的原版用法DispatcherServlet和 Spring Security 应该不需要进一步的更改。 如果您的应用程序中还有其他功能(例如,使用其他 servlet 或过滤器),则可能需要向Applicationcontext 中,通过将web.xml如下:spring-doc.cadn.net.cn

  • 一个@Bean的类型ServletServletRegistrationBean将该 bean 安装在容器中,就像它是一个<servlet/><servlet-mapping/>web.xml.spring-doc.cadn.net.cn

  • 一个@Bean的类型FilterFilterRegistrationBean的行为类似(如<filter/><filter-mapping/>).spring-doc.cadn.net.cn

  • ApplicationContext可以通过@ImportResourceApplication. 或者,已经大量使用 Comments 配置的情况可以用几行代码重新创建,如@Bean定义。spring-doc.cadn.net.cn

一旦 war 文件开始工作,你可以通过添加一个main方法添加到Application,如以下示例所示:spring-doc.cadn.net.cn

Java
public static void main(String[] args) {
    SpringApplication.run(MyApplication.class, args);
}
Kotlin
fun main(args: Array<String>) {
    runApplication<MyApplication>(*args)
}

如果您打算将应用程序作为 war 或可执行应用程序启动,则需要在可用于SpringBootServletInitializercallback 和mainmethod 的类中,如下所示:spring-doc.cadn.net.cn

Java
import org.springframework.boot.Banner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return customizerBuilder(builder);
    }

    public static void main(String[] args) {
        customizerBuilder(new SpringApplicationBuilder()).run(args);
    }

    private static SpringApplicationBuilder customizerBuilder(SpringApplicationBuilder builder) {
        return builder.sources(MyApplication.class).bannerMode(Banner.Mode.OFF);
    }

}
Kotlin
import org.springframework.boot.Banner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.builder.SpringApplicationBuilder
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer

@SpringBootApplication
class MyApplication : SpringBootServletInitializer() {

    override fun configure(builder: SpringApplicationBuilder): SpringApplicationBuilder {
        return customizerBuilder(builder)
    }

    companion object {

        @JvmStatic
        fun main(args: Array<String>) {
            customizerBuilder(SpringApplicationBuilder()).run(*args)
        }

        private fun customizerBuilder(builder: SpringApplicationBuilder): SpringApplicationBuilder {
            return builder.sources(MyApplication::class.java).bannerMode(Banner.Mode.OFF)
        }

    }

}

应用程序可以分为多个类别:spring-doc.cadn.net.cn

所有这些都应该适合翻译,但每个可能需要略有不同的技术。spring-doc.cadn.net.cn

如果 Servlet 3.0+ 应用程序已经使用 Spring Servlet 3.0+ 初始化器支持类,那么它们可能很容易进行翻译。 通常,来自现有WebApplicationInitializer可以移动到SpringBootServletInitializer. 如果现有应用程序具有多个ApplicationContext(例如,如果它使用AbstractDispatcherServletInitializer),那么您也许能够将所有上下文源合并到一个SpringApplication. 您可能会遇到的主要复杂情况是,如果合并不起作用,并且您需要维护上下文层次结构。 有关示例,请参阅 building a hierarchy 上的条目。 通常需要分解包含 Web 特定功能的现有父上下文,以便所有ServletContextAware组件位于子上下文中。spring-doc.cadn.net.cn

尚不是 Spring 应用程序的应用程序可能可转换为 Spring Boot 应用程序,前面提到的指南可能会有所帮助。 但是,您可能还会遇到问题。 在这种情况下,我们建议在 Stack Overflow 上提出问题,并带有spring-boot.spring-doc.cadn.net.cn

19.3. 将 WAR 部署到 WebLogic

要将 Spring Boot 应用程序部署到 WebLogic,必须确保 servlet 初始化器直接实现WebApplicationInitializer(即使您从已经实现它的基类扩展)。spring-doc.cadn.net.cn

WebLogic 的典型初始值设定项应类似于以下示例:spring-doc.cadn.net.cn

Java
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.WebApplicationInitializer;

@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer implements WebApplicationInitializer {

}
Kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
import org.springframework.web.WebApplicationInitializer

@SpringBootApplication
class MyApplication : SpringBootServletInitializer(), WebApplicationInitializer

如果使用 Logback,则还需要告诉 WebLogic 首选打包版本,而不是服务器预安装的版本。 为此,您可以通过添加WEB-INF/weblogic.xml文件,其中包含以下内容:spring-doc.cadn.net.cn

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app
    xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        https://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd
        http://xmlns.oracle.com/weblogic/weblogic-web-app
        https://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
    <wls:container-descriptor>
        <wls:prefer-application-packages>
            <wls:package-name>org.slf4j</wls:package-name>
        </wls:prefer-application-packages>
    </wls:container-descriptor>
</wls:weblogic-web-app>

20. Docker 撰写

本节包括与 Spring Boot 中的 Docker Compose 支持相关的主题。spring-doc.cadn.net.cn

20.1. 自定义 JDBC URL

使用JdbcConnectionDetails使用 Docker Compose 时,JDBC URL 的参数 可以通过应用org.springframework.boot.jdbc.parameterslabel 添加到 服务。例如:spring-doc.cadn.net.cn

services:
  postgres:
    image: 'postgres:15.3'
    environment:
      - 'POSTGRES_USER=myuser'
      - 'POSTGRES_PASSWORD=secret'
      - 'POSTGRES_DB=mydb'
    ports:
      - '5432:5432'
    labels:
      org.springframework.boot.jdbc.parameters: 'ssl=true&sslmode=require'

有了这个 Docker Compose 文件,使用的 JDBC URL 是jdbc:postgresql://127.0.0.1:5432/mydb?ssl=true&sslmode=require.spring-doc.cadn.net.cn

20.2. 在多个应用程序之间共享服务

如果要在多个应用程序之间共享服务,请创建compose.yaml文件,然后使用 configuration 属性spring.docker.compose.file在其他应用程序中引用compose.yaml文件。 您还应该设置spring.docker.compose.lifecycle-managementstart-only,因为它默认为start-and-stop停止一个应用程序也会关闭其他仍在运行的应用程序的共享服务。 将其设置为start-only不会在应用程序停止时停止共享服务,但需要注意的是,如果您关闭所有应用程序,服务将保持运行。 您可以通过运行docker compose stop在命令行中包含compose.yaml文件。spring-doc.cadn.net.cn