将应用程序从Spring Boot 2迁移到Spring Boot 3

2023/05/11

1. 概述

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

2. 核心变化

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

2.1 配置属性

修改了一些属性键:

  • 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获得。

此依赖项会生成一份报告,在启动时打印已弃用的属性名称,并在运行时临时迁移这些属性。

2.2 JakartaEE 10

新版本的JakartaEE 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获得。

除了依赖坐标的变化,JakartaEE现在使用“jakarta”包而不是“javax”。因此,在我们更新依赖项之后,我们可能需要更新导入语句。

2.3 Hibernate

如果我们通过将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获得。

2.4 其他变化

此外,此版本还包括核心级别的其他重大更改:

  • 图像banner支持已删除:现在定义自定义banner时,只有banner.txt文件被认为是有效文件
  • 日志记录日期格式化程序:Logback和Log4J2的新默认日期格式是yyyy-MM-dd’T’HH:mm:ss.SSSXXX。如果我们想恢复旧的默认格式,我们需要在application.yaml中将属性logging.pattern.dateformat的值设置为旧值
  • @ConstructorBinding仅在构造函数级别:对于@ConfigurationProperties类,不再需要在类级别使用@ConstructorBinding,它应该被删除。但是,如果一个类或记录有多个构造函数,则必须在所需的构造函数上使用@ConstructorBinding来指定哪一个将用于属性绑定。

3. Web应用程序更改

最初,假设我们的应用程序是Web应用程序,我们应该考虑进行某些更改。

3.1 尾部斜杠匹配配置

新的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/”不再匹配,将导致HTTP404错误。

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

public class WebConfiguration implements WebMvcConfigurer {

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

3.2 响应头大小

正如我们已经提到的,属性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容器不支持此功能。

3.3 其他变化

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

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

4. Actuator变化

Actuator模块中引入了一些重大更改。

4.1 Actuator端点清理

在以前的版本中,Spring框架会自动屏蔽端点/env和/configprops上敏感键的值,这些值显示敏感信息,例如配置属性和环境变量。

在此版本中,Spring更改了默认情况下更安全的方法。

现在,它不再只屏蔽某些键,而是默认屏蔽所有键的值。我们可以通过使用以下值之一设置属性management.endpoint.env.show-values(对于/env端点)或management.endpoint.configprops.show-values(对于/configprops端点)来更改此配置:

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

4.2 其他变化

Spring Actuator模块上发生的其他相关更新:

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

5. Spring Security

Spring Boot 3仅与Spring Security 6兼容

在升级到Spring Boot 3.0之前,我们应该首先将Spring Boot 2.7应用升级到Spring Security 5.8

之后,我们可以将Spring Security升级到版本6和Spring Boot 3。

此版本中引入了一些重要更改:

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

6. Spring Batch

让我们看看Spring Batch模块中引入的一些重大变化。

6.1 不鼓励@EnableBatchProcessing

以前,我们可以启用Spring Batch的自动配置,使用@EnableBatchProcessing标注配置类。如果我们想使用自动配置,新版本的Spring Boot不鼓励使用这个注解

事实上,使用这个注解(或定义一个实现DefaultBatchConfiguration的bean)会告诉自动配置退出。

6.2 运行多个作业

以前,可以使用Spring Batch同时运行多个批处理作业。但是,情况已不再如此。如果自动配置检测到单个作业,它将在应用程序启动时自动执行

因此,如果上下文中存在多个作业,我们需要通过使用spring.batch.job.name属性提供作业名称来指定应在启动时执行的作业。因此,这意味着如果我们要运行多个作业,我们必须为每个作业创建一个单独的应用程序。

或者,我们可以使用Quartz、Spring Scheduler等调度程序或其他替代方案来调度作业。

7. 总结

在本文中,我们学习了如何将Spring Boot 2.7应用程序迁移到版本3,重点介绍了Spring环境的核心组件。其他模块也发生了一些变化,如Spring Session、Micrometer、依赖管理等。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章