轩辕李的博客 轩辕李的博客
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

轩辕李

勇猛精进,星辰大海
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java

    • 核心

    • 并发

    • 经验

      • Java8升级到Java11的实践
      • Java 11升级到Java17,以及升级到Spring Boot 3的过程
        • 为何升级Java 17
        • Java 11升级到Java 17
        • Spring Boot 2.x升级到Spring Boot 3
          • 三方库升级
          • 属性变化
          • 自动配置文件
          • 尾部斜杠匹配
          • 删除了Elasticsearch’s high-level REST client
          • dubbo框架的升级
          • jasypt-spring-boot的升级
          • sentinel的升级
          • Springfox迁移到Spring Doc 2
          • Thymeleaf模板引擎的升级
        • 总结
    • JVM

    • 企业应用

  • Spring

  • 其他语言

  • 工具

  • 后端
  • Java
  • 经验
轩辕李
2023-07-11
目录

Java 11升级到Java17,以及升级到Spring Boot 3的过程

随着Spring Boot 3 (opens new window)在2022年11月发布,最低支持Java 17。

作为Java企业开发领域最具影响力的框架,Spring Boot 3的发布,也意味着Java 17必将慢慢普及开来。

Java 11升级到Java 17,以及升级到Spring Boot 3的过程,是Java开发者必须面对的问题。本文将对此进行简单的介绍。

# 为何升级Java 17

  • 更高的性能,参考 How much faster is Java 17? (opens new window)
  • 更好的安全性,参考 Java 17的增强伪随机数生成器
  • 更好的开发体验和开发效率,参见 Java历代版本新特性 12-17部分
  • 更好的生态支持,比如Spring Boot 3 (opens new window) 和 GraalVM Native Image (opens new window)

# Java 11升级到Java 17

首先,我们需要注意到已经删除的功能,包括:

  • Nashorn JavaScript引擎。Java 15删除了Nashorn JavaScript引擎。如果您仍想使用引擎,则可以使用 nashorn-core 依赖项。
  • 实验编译器。Java 17 删除了对 GraalVM 的实验性提前 (AOT) 和实时 (JIT) 编译器的支持,如 JEP 410 (opens new window) 文档中所述。

其次,我们需要对Java 12到Java 17的新特性有所了解,请参考上面的文章。

其中,值得关注的新特性有:

  • Switch 表达式 (opens new window)
  • ZGC (opens new window)
  • 文本块 (opens new window)
  • instanceOf 模式匹配 (opens new window)
  • 记录类 (opens new window)
  • 密封类 (opens new window)
  • 隐藏类 (opens new window)

# Spring Boot 2.x升级到Spring Boot 3

首先,请查看 Spring Boot 3 迁移指南 (opens new window)。

其中的重点有以下几方面:

# 三方库升级

其中最主要的是Spring Framework 6 (opens new window)和 Spring Security 6 (opens new window)。

还有就是相关Jakarta EE的升级。

从Jakarta EE 9开始,javax包名已经改为jakarta。Spring Boot 3.0已经升级到Jakarta EE 10,因此,需要注意包名的变化。

主要是以下包名的变化:

  • 迁移javax.activation包到jakarta.activation
  • 迁移javax.annotation包到jakarta.annotation
  • 迁移javax.security.auth.message包到jakarta.security.auth.message
  • 迁移javax.security.jacc包到jakarta.security.jacc
  • 迁移javax.batch包到jakarta.batch
  • 迁移javax.decorator包到jakarta.decorator
  • 迁移javax.ejb包到jakarta.ejb
  • 迁移javax.el包到jakarta.el
  • 迁移javax.enterprise包到jakarta.enterprise
  • 迁移javax.faces包到jakarta.faces
  • 迁移javax.inject包到jakarta.inject
  • 迁移javax.interceptor包到jakarta.interceptor
  • 迁移javax.jms包到jakarta.jms
  • 迁移javax.json包到jakarta.json
  • 迁移javax.jws包到jakarta.jws
  • 迁移javax.mail包到jakarta.mail
  • 迁移javax.persistence包到jakarta.persistence
  • 迁移javax.resource包到jakarta.resource
  • 迁移javax.security.enterprise包到jakarta.security.enterprise
  • 迁移javax.servlet包到jakarta.servlet
  • 迁移javax.transaction包到jakarta.transaction
  • 迁移javax.validation包到jakarta.validation
  • 迁移javax.websocket包到jakarta.websocket
  • 迁移javax.ws包到jakarta.ws
  • 迁移javax.xml.bind包到jakarta.xml.bind
  • 迁移javax.soap包到jakarta.soap
  • 迁移javax.xml.ws包到jakarta.xml.ws

相关的Maven依赖也会发生变化,查看 Maven Repository: jakarta (opens new window)

# 属性变化

在 Spring Boot 3.0 中,一些配置属性被重命名/删除,开发人员需要相应地更新它们的 application.properties/application.yml。

为了帮助你解决这个问题,Spring Boot 提供了一个 spring-boot-properties-migrator 模块。作为依赖项添加到项目后,这不仅会在启动时分析应用程序的环境和打印诊断,还会在运行时临时迁移属性。

您可以通过将以下内容添加到 Maven 来添加迁移器pom.xml:

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

完成迁移后,请确保从项目的依赖项中删除此模块。

你也可以在此页面 (opens new window)找到具体属性变化,进行手动替换。

# 自动配置文件

Spring Boot 2.7 引入了一个新 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,用于注册自动配置,同时保持与 spring.factories 注册的向后兼容性。

在Spring Boot 3中,删除了对在 中 spring.factories 注册自动配置的支持,取而代之的是导入文件。

也就是说从 Spring Boot 3 开始,必须使用 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 进行导入,以前的 spring.factories 导入方式将失效

# 尾部斜杠匹配

从 Spring Framework 6.0 开始,尾部斜杠匹配配置选项已被弃用,其默认值设置为 false .这意味着以前,以下控制器将同时匹配“GET /some/greeting”和“GET /some/greeting/”:

@RestController
public class MyController {

  @GetMapping("/some/greeting")
  public String greeting() {
    return "Hello";
  }
}

可以通过以下方式更改默认值:

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

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

# 删除了Elasticsearch’s high-level REST client

Elasticsearch 8.x开始,不支持Elasticsearch’s high-level REST client,因此Spring Boot 3.0删除了对其的支持。

请查看high-level REST client迁移指南 (opens new window) 了解如何迁移到新的Java REST客户端。

如果项目中去除RestHighLevelClient太麻烦,则可以通过添加如下配置来保留RestHighLevelClient:

    @Configuration
    @ConditionalOnProperty(prefix = "spring.elasticsearch", name = "uris")
    public static class RestHighLevelClientConfig {

        /**
         * ElasticSearch客户端
         *
         * @param properties 属性
         * @return {@link RestHighLevelClient}
         */
        @Bean
        @ConditionalOnMissingBean(RestHighLevelClient.class)
        public RestHighLevelClient restHighLevelClient(ElasticsearchProperties properties) {
            RestClientBuilder builder = RestClient.builder(properties.getUris().stream().map(HttpHost::create).toArray(HttpHost[]::new));
            PropertyMapper map = PropertyMapper.get();
            map.from(properties.getUsername()).whenHasText().to((username) -> {
                CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
                Credentials credentials = new UsernamePasswordCredentials(properties.getUsername(), properties.getPassword());
                credentialsProvider.setCredentials(AuthScope.ANY, credentials);
                builder.setHttpClientConfigCallback((httpClientBuilder) -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
            });
            return new RestHighLevelClient(builder);
        }
    }

# dubbo框架的升级

dubbo 3.2 (opens new window) 开始对Spring Boot 3进行支持,所以需要升级dubbo版本。

参考 2.x 升级至 3.x (opens new window)。

# jasypt-spring-boot的升级

需要注意的是,jasypt-spring-boot 3.x 基于密码的默认配置 (opens new window)发生了变化。

为了与2.x版本的兼容性,你可以手动注入jasyptStringEncryptor,且属性与原先一致,并把org.jasypt.salt.NoOpIVGenerator改为org.jasypt.iv.NoIvGenerator。

    @Bean("jasyptStringEncryptor")
    public StringEncryptor stringEncryptor(@Value("${jasypt.encryptor.password}") String password) {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword(password);
        config.setAlgorithm("PBEWithMD5AndDES");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);
        return encryptor;
    }

# sentinel的升级

主要是适配duboo 3:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-apache-dubbo3-adapter</artifactId>
    <version>x.y.z</version>
</dependency>

对于Spring Boot 3,sentinel官网还没有发布对应的版本,你可以fork官方项目 (opens new window),把servlet迁移到Jakarta EE包名,然后发布到自己的私服。

其实对于一些三方包,可能官方还没有发布对应的Spring Boot 3版本支持,都可以暂时采用上面的方式。 比如 mqtt-spring-boot-starter (opens new window)。

# Springfox迁移到Spring Doc 2

Springfox已经不再维护,可以使用Spring Doc 2 (opens new window)代替它。

迁移文档:Migrating from SpringFox (opens new window)

# Thymeleaf模板引擎的升级

Spring Boot 3将Thymeleaf的依赖升级到3.1,参考 Thymeleaf 3.1迁移指南 (opens new window)。

其中最重要的变化是:

不再支持通过web-API提供的表达式实用对象。
在此版本中,不再提供用于表达式的#request、#response、#session和#servletContext对象。先前版本中,这些对象可以用于在Thymeleaf模板中进行表达式计算和操作,但在3.1版本中被移除了。

所以如果你的thymeleaf模板中使用了这些对象,需要进行修改。

比如原先在页面中可以直接访问servletContext中的属性:${#servletContext.getAttribute('ctx')}。现在则需要从Controller中传递这些属性到模板中:

    @GetMapping("/index")
    public String index(HttpServletRequest request, Model model) {
        model.addAttribute("ctx", request.getServletContext().getAttribute("ctx"));
        return "index";
    }

页面中使用ctx属性:

<link th:href="${ctx}+'/css/base.css'" rel="stylesheet" type="text/css">

# 总结

更高的性能,更好的安全性,更好的开发体验和开发效率,更好的生态支持。Java 17与Spring Boot 3你值得拥有!

祝你变得更强!

编辑 (opens new window)
上次更新: 2023/07/17
Java8升级到Java11的实践
JVM体系

← Java8升级到Java11的实践 JVM体系→

最近更新
01
Spring Boot版本新特性
09-15
02
Spring框架版本新特性
09-01
03
Spring Boot开发初体验
08-15
更多文章>
Theme by Vdoing | Copyright © 2018-2025 京ICP备2021021832号-2 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式