如何从 Spring Boot 2 迁移到 Spring Boot 3?


在本教程中,我们将学习如何将 Spring Boot 应用程序迁移到3.0 版本。要成功将应用程序迁移到 Spring Boot 3,我们必须确保我们要迁移的应用程序的当前 Spring Boot 版本是 2.7,Java 版本是 17。

Spring Boot 3.0 标志着该框架的一个重要里程碑,对其核心组件进行了多项重要修改。

修改了一些属性键:

  • spring.redis已经迁移到spring.data.redis
  • spring.data.cassandra已经移动到spring.cassandra
  • spring.jpa.hibernate.use-new-id-generator已删除
  • server.max.http.header.size已移至server.max-http-request-header-size
  • spring.security.saml2.relyingparty.registration.{id}.identity-provider支持被移除
为了识别这些属性,我们可以在我们的pom.xml中添加spring-boot-properties-migrator:

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

最新版本的spring-boot-properties-migrator可从 Maven Central 获得。
此依赖项会生成一份报告,在启动时打印已弃用的属性名称,并在运行时临时迁移这些属性。

新版 Jakarta EE 10 带来了 Spring Boot 3 相关依赖的更新:

  • Servlet 规范更新至 6.0 版
  • JPA 规范更新到 3.1 版
因此,如果我们通过从spring-boot-starter依赖项中排除它们来管理这些依赖项,我们应该确保更新它们。
让我们从更新 JPA 依赖项开始:

<dependency>
    <groupId>jakarta.persistence</groupId>
    <artifactId>jakarta.persistence-api</artifactId>
    <version>3.1.0</version>
</dependency>

最新版本的jakarta.persistence-api可从 Maven Central 获得。

接下来,让我们更新 Servlet 依赖项:

<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.0.0</version>
</dependency>

最新版本的jakarta.servlet-api可从 Maven Central 获得。
除了依赖坐标的变化,Jakarta EE 现在使用“ jakarta ”包而不是“ javax ”。因此,在我们更新依赖项之后,我们可能需要更新导入语句。

如果我们通过将 Hibernate 依赖项从spring-boot-starter依赖项中排除来管理它,确保更新它很重要:

<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>6.1.4.Final</version>
</dependency>

最新版本的hibernate-core可从 Maven Central 获得。

尾部斜杠匹配配置
新的 Spring Boot 版本弃用了配置尾部斜杠匹配的选项,并将其默认值设置为false。

例如,让我们用一个简单的 GET 端点定义一个控制器:

@RestController
@RequestMapping("/api/v1/todos")
@RequiredArgsConstructor
public class TodosController {
    @GetMapping("/name")
    public List<String> findAllName(){
        return List.of("Hello","World");
    }
}

现在“ GET /api/v1/todos/name/ ”默认不再匹配,将导致 HTTP 404 错误。

我们可以通过定义一个实现WebMvcConfigurer或WebFluxConfigurer的新配置类(如果它是反应式服务)来为所有端点启用尾部斜线匹配:

public class WebConfiguration implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.setUseTrailingSlashMatch(true);
    }

}


响应头大小
正如我们已经提到的,属性server.max.http.header.size已被弃用,取而代之的是server.max-http-request-header-size,它只检查请求标头的大小。要为响应标头也定义一个限制,让我们定义一个新的 bean:

@Configuration
public class ServerConfiguration implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
            @Override
            public void customize(Connector connector) {
                connector.setProperty("maxHttpResponseHeaderSize", "100000");
            }
        });
    }
}

如果我们使用 Jetty 而不是 Tomcat,我们应该将TomcatServletWebServerFactory 更改为JettyServletWebServerFactory。此外,其他嵌入式 Web 容器不支持此功能。

此外,此版本在 Web 应用程序级别还有其他重大变化:

  • 优雅关机的阶段:优雅关机的 SmartLifecycle 实现更新了阶段。Spring 现在在SmartLifecycle.DEFAULT_PHASE – 2048阶段启动正常关闭,并在SmartLifecycle.DEFAULT_PHASE – 1024阶段停止 Web 服务器。
  • RestTemplate上的HttpClient升级:Rest Template 更新其 Apache HttpClient5版本

Spring Actuator
在以前的版本中,Spring Framework 会自动屏蔽端点/env和/configprops上敏感键的值,这些值显示敏感信息,例如配置属性和环境变量。在此版本中,Spring 更改了默认情况下更安全的方法。
现在,它不再只屏蔽某些键,而是默认屏蔽所有键的值。我们可以通过使用以下值之一设置属性management.endpoint.env.show-values(对于/env端点)或management.endpoint.configprops.show-values(对于 / configprops端点)来更改此配置:

  • NEVER : 没有显示值
  • ALWAYS:显示的所有值
  • WHEN_AUTHORIZED:如果用户被授权,则显示所有值。对于JMX,所有用户都被授权。对于 HTTP,只有特定角色才能访问数据。

其他:

  • Jmx 端点公开:JMX 仅处理健康端点。通过配置属性management.endpoints.jmx.exposure.include和management.endpoints.jmx.exposure.exclude,我们可以自定义它。
  • httptrace端点重命名:此版本将“ /httptrace ”端点重命名为“ /httpexchanges ”
  • 隔离的ObjectMapper:此版本现在隔离了负责序列化执行器端点响应的ObjectMapper实例。我们可以通过将management.endpoints.jackson.isolated-object-mapper属性设置为false来更改此功能。

Spring Boot 3 仅与 Spring Security 6 兼容。
在升级到 Spring Boot 3.0 之前,我们应该先将我们的 Spring Boot 2.7 应用升级到 Spring Security 5.8。之后,我们可以将 Spring Security 升级到版本 6 和 Spring Boot 3。
此版本中引入了一些重要更改:

  • ReactiveUserDetailsS​​ervice 未自动配置:在存在AuthenticationManagerResolver的情况下,不再自动配置ReactiveUserDetailsS​​ervice。
  • SAML2 Relying Party Configuration:我们之前提到新版本的 Spring boot 不再支持位于spring.security.saml2.relyingparty.registration.{id}.identity-provider下的属性。相反,我们应该使用spring.security.saml2.relyingparty.registration.{id}.asserting-party下的新属性。

Spring Batch模块
1、以前,我们可以启用Spring Batch的自动配置,使用@EnableBatchProcessing注释配置类。如果我们想使用自动配置,新版本的 Spring Boot 不鼓励使用这个注解。
事实上,使用这个注释(或定义一个实现DefaultBatchConfiguration 的bean )告诉自动配置退出。

2、以前,可以使用 Spring Batch 同时运行多个批处理作业。但是,情况已不再如此。如果自动配置检测到单个作业,它将在应用程序启动时自动执行。
因此,如果上下文中存在多个作业,我们需要通过使用 spring.batch.job.name属性提供作业名称来指定应在启动时执行的作业。因此,这意味着如果我们要运行多个作业,我们必须为每个作业创建一个单独的应用程序。
或者,我们可以使用 Quartz、Spring Scheduler 等调度程序或其他替代方案来调度作业。


可以在 GitHub 上找到示例的完整源代码。