1. 概述

本文将指导你如何将 Spring Boot 应用迁移到 3.0 版本。成功迁移需满足两个前提条件:

  • 当前 Spring Boot 版本必须为 2.7
  • Java 版本必须为 17

2. 核心变更

Spring Boot 3.0 是框架的重大里程碑,核心组件有多项重要修改。

2.1 配置属性

部分属性键名已调整:

  • spring.redisspring.data.redis
  • spring.data.cassandraspring.cassandra
  • spring.jpa.hibernate.use-new-id-generator 已移除
  • server.max.http.header.sizeserver.max-http-request-header-size
  • spring.security.saml2.relyingparty.registration.{id}.identity-provider 支持已移除

识别废弃属性:在 pom.xml 添加迁移工具:

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

该依赖会在启动时生成废弃属性报告,并在运行时临时迁移属性。

2.2 Jakarta EE 10

Jakarta EE 10 带来依赖更新:

  • 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>

Servlet 依赖更新

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

⚠️ 包名变更:Jakarta EE 现在使用 jakarta.* 包替代 javax.*,需更新所有相关 import 语句。

2.3 Hibernate

若手动管理 Hibernate 依赖,需更新版本:

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

2.4 其他变更

  • 图片横幅支持移除:自定义横幅仅支持 banner.txt 文件
  • 日志日期格式变更:Logback/Log4J2 默认格式改为 yyyy-MM-dd'T'HH:mm:ss.SSSXXX
    恢复旧格式需设置:
    logging:
      pattern:
        dateformat: "旧格式值"
    
  • @ConstructorBinding 调整
    • 类级别的 @ConstructorBinding 注解需移除
    • 多构造函数时,需在目标构造函数上添加 @ConstructorBinding 指定绑定

3. Web 应用变更

3.1 尾部斜杠匹配配置

**尾部斜杠匹配配置已废弃,默认值设为 false**。例如:

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

现在 GET /api/v1/todos/name/ 默认返回 404。

重新启用尾部斜杠匹配

@Configuration
public class WebConfiguration implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.setUseTrailingSlashMatch(true);
    }
}

3.2 响应头大小控制

原属性 server.max.http.header.size 仅控制请求头,响应头需通过自定义 Bean 控制:

@Configuration
public class ServerConfiguration implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        factory.addConnectorCustomizers(connector -> 
            connector.setProperty("maxHttpResponseHeaderSize", "100000")
        );
    }
}

Jetty 需替换为 JettyServletWebServerFactory,其他容器不支持此功能。

3.3 其他变更

  • 优雅停机阶段调整
    • 优雅停机启动阶段:SmartLifecycle.DEFAULT_PHASE - 2048
    • Web 服务器停止阶段:SmartLifecycle.DEFAULT_PHASE - 1024

4. Actuator 变更

4.1 接口信息脱敏

默认对所有键值脱敏(原仅对敏感键)。可通过以下属性调整:

  • management.endpoint.env.show-values(/env 接口)
  • management.endpoint.configprops.show-values(/configprops 接口)

可选值:

  • NEVER:不显示任何值
  • ALWAYS:显示所有值
  • WHEN_AUTHORIZED:授权后显示(HTTP 需特定角色,JMX 全部授权)

4.2 其他变更

  • JMX 端点暴露:默认仅暴露 health 端点,可通过 management.endpoints.jmx.exposure.include 调整
  • 端点重命名/httptrace/httpexchanges
  • ObjectMapper 隔离:Actuator 使用独立的 ObjectMapper,可通过 management.endpoints.jackson.isolated-object-mapper=false 关闭

5. Spring Security

Spring Boot 3 仅兼容 Spring Security 6。迁移步骤:

  1. 先升级到 Spring Boot 2.7 + Spring Security 5.8
  2. 再升级到 Spring Boot 3 + Spring Security 6

关键变更:

  • 存在 AuthenticationManagerResolver 时不再自动配置 ReactiveUserDetailsService
  • SAML2 配置路径变更:spring.security.saml2.relyingparty.registration.{id}.identity-providerspring.security.saml2.relyingparty.registration.{id}.asserting-party

6. Spring Batch

6.1 @EnableBatchProcessing 不推荐

**使用自动配置时不再推荐 @EnableBatchProcessing**。该注解会导致自动配置回退。

6.2 多任务运行

自动配置仅支持单任务自动执行。多任务场景需:

  • 通过 spring.batch.job.name 指定启动任务
  • 或使用 Quartz/Spring Scheduler 调度任务

7. HttpClient 变更

Spring Boot 3 升级至 Apache HttpClient 5.x,需重构相关配置。

7.1 HttpClient 4.x 旧配置(不兼容)

@Configuration
public class RestTemplateConfiguration {
    @Bean
    public RestTemplate getRestTemplate() {
        CloseableHttpClient httpClient = HttpClients.custom().build();
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);
        requestFactory.setConnectTimeout(30000); // 5.x 中已废弃
        return new RestTemplate(requestFactory);
    }
}

7.2 不兼容原因

  • HttpComponentsClientHttpRequestFactory 要求 5.x 的 CloseableHttpClient
  • 超时方法(如 setConnectTimeout())已废弃或忽略
  • 包名变更:org.apache.http.*org.apache.hc.*

7.3 迁移到 HttpClient 5.x(5.4 版本前)

@Configuration
public class RestTemplateConfiguration {
    @Bean
    public RestTemplate restTemplate() {
        RequestConfig config = RequestConfig.custom()
          .setConnectTimeout(Timeout.ofSeconds(30))
          .setResponseTimeout(Timeout.ofSeconds(30))
          .build();
        CloseableHttpClient client = HttpClients.custom()
          .setDefaultRequestConfig(config)
          .build();
        return new RestTemplate(new HttpComponentsClientHttpRequestFactory(client));
    }
}

7.4 迁移到 HttpClient 5.4+

@Configuration
public class RestTemplateConfiguration {
    @Bean
    public RestTemplate restTemplate() {
        SocketConfig socketConfig = SocketConfig.custom()
          .setSoTimeout(Timeout.ofSeconds(30))
          .build();

        ConnectionConfig connectionConfig = ConnectionConfig.custom()
          .setConnectTimeout(Timeout.ofSeconds(30))
          .build();

        PoolingHttpClientConnectionManager connectionManager =
          PoolingHttpClientConnectionManagerBuilder.create()
            .setMaxConnPerRoute(20)
            .setMaxConnTotal(100)
            .setDefaultSocketConfig(socketConfig)
            .setDefaultConnectionConfig(connectionConfig)
            .build();

        CloseableHttpClient httpClient = HttpClients.custom()
          .setConnectionManager(connectionManager)
          .build();

        return new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
    }
}

8. 总结

本文详细介绍了从 Spring Boot 2.7 迁移到 3.0 的核心步骤,涵盖配置属性、Jakarta EE、Web 应用、Actuator、Security、Batch 及 HttpClient 等关键模块。其他模块(如 Spring Session、Micrometer)的变更可参考官方迁移指南

迁移前务必备份代码,建议在测试环境充分验证后再部署生产。


原始标题:Migrate Application From Spring Boot 2 to Spring Boot 3 | Baeldung