jdk8升级JDK21(Springboot2.7.18升级Springboot3.4.0)

目录

背景:

一、maven升级

二、代码改造

2.1 javax替换为jakarta

2.2 swagger2升级swagger3相关更新

2.2.1 新增SpringDocConfig配置类

2.2.2 全局代码更新

2.2.3 全局代码替换(普通+正则替换)

2.3 Mybatis Plus升级

2.4 logback.xml更新

2.5 application.yml更新

三、其他注意事项

3.1 Jdk相关

3.1.1 启动参数

3.2 Spring相关

3.2.1 尾部斜杠匹配取消

3.2.2 RequestParam等传参报错

3.3.3 循环依赖启动报错


背景:

由于各种漏洞原因需要升级Spring6,同时项目上还在使用Jdk8,索性将JDK升级为21,同时springboot也升级为最新发布的Springboot3.4.0,在此记录。

一、maven升级

其中关键依赖升级:

  • Springboot 3.4.0(2024/11/22发布的稳定版,内部依赖spring 6.2.0、tomcat 10.1.33、logback 1.5.12...)
  • Mybatis-plus 3.5.9(Mybatis3.5.16)
  • Shiro 2.0.2
  • Lombok 1.18.36(注意最低兼容版本 jdk17 >= 1.18.22,jdk21 >= 1.18.30)
  • swagger3(springdoc 2.6.0,注意swagger2升级swagger3不再使用io.springfox,需要使用org.springdoc包)
  • mysql-connector-j 8.4.0

部分升级注意事项也写在了注释里

<!-- 2024/11/22发布的稳定版,内部依赖spring 6.2.0、tomcat 10.1.33、logback 1.5.12... -->
<dependency><!-- Import dependency management from Spring Boot --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>3.4.0</version>
</dependency><dependency><groupId>jakarta.servlet</groupId><artifactId>jakarta.servlet-api</artifactId><scope>compile</scope>
</dependency><!-- Mybatis Plus全家桶升级,参考https://baomidou.com/getting-started/install/ -->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-bom</artifactId><version>3.5.9</version>
</dependency>
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-bom</artifactId><version>${mybatis-plus-bom.version}</version>
</dependency>
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.9</version><exclusions><exclusion><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-jsqlparser</artifactId>
</dependency>
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId>
</dependency><!-- 8.0.30之后的版本,mysql依赖的坐标变更 
可参考https://blogs.oracle.com/mysql/post/mysql-connectorj-has-new-maven-coordinates-->
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.31</version>
</dependency><!-- lombok最低兼容版本 jdk17 >= 1.18.22,jdk21 >= 1.18.30 -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.36</version>
</dependency><!-- swagger2升级swagger3不再使用io.springfox,需要使用springdoc-->
<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.6.0</version>
</dependency>
<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-api</artifactId><version>2.6.0</version>
</dependency>

其他中间件升级(适配SpringBoot3.4.0版本)


<!-- RocketMQ springboot版,文档地址:https://github.com/apache/rocketmq-spring-->
<dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.3.1</version>
</dependency><!-- Redisson 文档地址:https://redisson.org/docs/integration-with-spring/#spring-boot-starter-->
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.38.1</version>
</dependency><!-- Kafka 此版本springboot默认依赖3.3.0版本spring-kafka-->
<dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId>
</dependency><!-- ElasticSearch 此版本springboot支持目前最新版es(8.11.1)-->
<dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId><version>8.11.1</version>
</dependency><!-- Mapstruct 此版本springboot支持目前最新版es(8.11.1)使用时需注意:升级到最新版本后,若想转换List<Entity>,则@Mapper修饰的convert转换类中必须带有Entity单独转换方法,
否则无法直接转换List<Entity>会报错(list转换时会使用单独转换的方法遍历转换)。-->
<dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>1.6.3</version>
</dependency><!-- Freemarker-->
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.33</version>
</dependency>

二、代码改造

2.1 javax替换为jakarta

在springboot3中,最低支持的Jdk版本提升到Java 17,移除对Java EE APIs的支持并转向Jakarta EE,因此引入包中import需全局替换。

详细的Springboot3更新可参考官方release note。

Spring-Boot-3.0-Release-Notes

具体需要替换的包:

javax.persistence.* -> jakarta.persistence.*

javax.validation.* -> jakarta.validation.*

javax.servlet.* -> jakarta.servlet.*

javax.annotation.* -> jakarta.annotation.*

javax.transaction.* -> jakarta.transaction.*

2.2 swagger2升级swagger3相关更新

2.2.1 新增SpringDocConfig配置类

/*** spring doc配置*/
@Configuration
public class SpringDocConfig {@Value("${framework.swagger.title}")private String swaggerTitle;@Value("${framework.swagger.description}")private String swaggerDescription;@Value("${framework.swagger.contact.name}")private String swaggerContactName;@Value("${framework.swagger.contact.url}")private String swaggerContactUrl;@Value("${framework.swagger.contact.email}")private String swaggerContactEmail;@Value("${framework.swagger.version}")private String swaggerVersion;@Beanpublic OpenAPI apiInfo() {return new OpenAPI().info(new Info().title(swaggerTitle).description(swaggerDescription).version(swaggerVersion).contact(new Contact().name(swaggerContactName).email(swaggerContactEmail).url(swaggerContactUrl)));}}

2.2.2 全局代码更新

下面是swagger2和swagger3中注解的对照关系,方便升级时对照。

swagger2swagger3说明
@Api@Tag用在请求的类上,表示对类的说明
@ApiIgnore@Hidden隐藏显示
@ApiImplicitParam@Parameter用在请求方法上,指定具体某一个请求参数的详细信息
@ApiImplicitParams@Parameters用在请求方法上,表示一组参数的说明
@ApiModel@Schema用于请求或者响应类上,说明请求或者响应数据
@ApiModelProperty@Schema

用在属性上,描述响应类的属性用,swagger2中的hidden = true属性

相当于swagger3中 的accessMode = READ_ONLY属性

@ApiOperation@Operation

用在请求的方法上,说明方法的用途、作用,对应注解中swagger2中

的value和notes属性对应swagger3中的summary和description属性

@ApiParam@Parameter描述参数信息

2.2.3 全局代码替换(普通+正则替换)

import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.tags.Tag;@Api\(value = (.*), tags = (.*)\)
@Tag\( name= $2, description = $1\)@Api\(tags = \{(.*)\}\)
@Tag\(name = $1\)import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;@ApiOperation\(value = (.*), notes = (.*)\)
@Operation\(summary = $1, description = $2\)@ApiOperation\(value=(.*)\)
@Operation\(summary = $1\)import io.swagger.annotations.ApiResponses;
import io.swagger.v3.oas.annotations.responses.ApiResponses;import io.swagger.annotations.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponse;@ApiResponse\(code = HttpStatus.SC_OK, message = (.*)\)
@ApiResponse(responseCode = "200", description = $1)import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Parameter;#unicode中文范围 \u4e00-\u9eff
@ApiParam\(value = ("[\w|\u4e00-\u9eff]+")
@Parameter\(description = $1import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;@ApiModelProperty\((.*)\)
@Schema\(description = $1\)import io.swagger.annotations.ApiModel;
import io.swagger.v3.oas.annotations.media.Schema;

2.3 Mybatis Plus升级

BaseMapper.selectCount()和.count()等方法返回值类型由原来的Integer变为Long,代码需做兼容,例如使用Math.toIntExact()方法将long转为int

例如:

2.4 logback.xml更新

使用 SizeAndTimeBasedRollingPolicy替换TimeBasedRollingPolicy:   

        该策略同时支持按时间和文件大小滚动日志。与旧的 TimeBasedRollingPolicy 类相比,它是更推荐的滚动策略。

文件命名模式调整:

        在 fileNamePattern 中,使用 %d{yyyy-MM-dd}-%i.log 作为文件名格式,这允许日志按照日期命名,并在同一天滚动日志时通过 %i 生成分片文件(如 2024-10-01-1.log, 2024-10-01-2.log 等)。

例如:

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/${APPDIR}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>20MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy><!--更改为↓↓↓--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!-- 归档的日志文件的路径,例如今天是2018-06-13日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。而2018-06-13的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/${APPDIR}/error/log-error-%d{yyyy-MM-dd}-%i.log</fileNamePattern><!-- 除按日志记录之外,还配置了日志文件不能超过20M,若超过20M,日志文件会以索引0开始,命名日志文件,例如log-error-2018-06-13.0.log --><!-- 日志文件的最大大小 --><maxFileSize>10MB</maxFileSize><!-- 最大保留30天的日志 --><maxHistory>30</maxHistory><!-- 总日志文件大小不超过3GB 达到该限制时,将删除最早的日志文件--><totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>

2.5 application.yml更新

① spring.http.encoding.XXX 更新为 server.servlet.encoding.XXX

② spring.redis.XXX 更新为 spring.data.redis.XXX

注意引用的地方也同样替换

三、其他注意事项

3.1 Jdk相关

3.1.1 启动参数

Java9之后模块化特性要求类库声明可被调用的范围若启动报错可在启动项添加对应参数,下面是一些例子。

--add-opens java.base/java.util=ALL-UNNAMED

--add-opens java.base/java.time=ALL-UNNAMED

--add-opens java.base/java.lang=ALL-UNNAMED

--add-opens java.base/java.lang.reflect=ALL-UNNAMED

--add-opens java.base/java.io=ALL-UNNAMED

--add-opens java.base/java.nio=ALL-UNNAMED

--add-opens java.base/sun.nio.ch=ALL-UNNAMED

比如下面这个报错,则启动参数增加 --add-opens java.base/java.nio=ALL-UNNAMED

添加方式:

Idea中:

Linux启动脚本中:

3.2 Spring相关

具体升级变化可参考官方Release-Notes

SpringBoot 2.x->3的变化:

Spring Boot 3.0 Release Notes · spring-projects/spring-boot Wiki · GitHub

Spring升级到6.0的变化:
Spring-Framework-6.0-Release-Notes

3.2.1 尾部斜杠匹配取消

从 Spring Framework 6.0 开始,尾部斜杠匹配配置选项已为 deprecated,其默认值设置为 false。

简单来说,就是比如以前@GetMapping("/list")这样的控制器,可以通过 /list 和 /list/ 两个路径都能访问到,现在只能通过 /list 访问。

3.2.2 RequestParam等传参报错

错误信息:

Name for argument of type [java.lang.String] not specified, and parameter name information not available via reflection. Ensure that the compiler uses the '-parameters' flag.

代码中的使用方式可能为这样:

public String getVersion(@RequestParam String authCode) {}

错误原因:

这个异常java.lang.IllegalArgumentException指出的问题是,在Spring框架中,某个方法参数的名称没有被明确指定,并且无法通过反射获取到。这通常发生在使用注解(如@RequestParam、@PathVariable等)来注入方法参数时,而该参数的名称在编译后的字节码中丢失了。

解决方式:

①规范使用注解,加入value属性,明确指定参数名称

public String getVersion(@RequestParam(value = "authCode", defaultValue = "") String authCode) {}

或者

②若改动太多,可增加maven打包参数:在pom.xml中的maven-compiler-plugin配置里添加<compilerArgument>-parameters</compilerArgument>

<plugins><!-- compiler插件, 设定JDK版本 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.0</version><configuration><compilerArgs><arg>-parameters</arg></compilerArgs><source>21</source><target>21</target><showWarnings>true</showWarnings></configuration></plugin>
</plugins>

3.3.3 循环依赖启动报错

升级后启动可能报循环依赖问题。

Description:

The dependencies of some of the beans in the application context form a cycle:

   operatePermissionAop defined in file [C:\work\project\XXXX.class]
┌─────┐
|  sysUserOrgServiceImpl
↑     ↓
|  sysAreaInfoServiceImpl
└─────┘
Action:

Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.

可在yml中增加允许循环依赖配置解决

spring:main:allow-circular-references: true

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/66530.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI赋能跨境电商:魔珐科技3D数字人破解出海痛点

跨境出海进入狂飙时代&#xff0c;AI应用正在深度渗透并重塑着跨境电商产业链的每一个环节&#xff0c;迎来了发展的高光时刻。生成式AI时代的大幕拉开&#xff0c;AI工具快速迭代&#xff0c;为跨境电商行业的突破与飞跃带来了无限可能性。 由于跨境电商业务自身特性鲜明&…

【HarmonyOS NEXT】鸿蒙应用实现屏幕录制详解和源码

【HarmonyOS NEXT】鸿蒙应用实现屏幕录制详解和源码 一、前言 官方文档关于屏幕录制的API和示例介绍获取简单和突兀。使用起来会让上手程度变高。所以特意开篇文章&#xff0c;讲解屏幕录制的使用。官方文档参见&#xff1a;使用AVScreenCaptureRecorder录屏写文件(ArkTS) 二…

Ubuntu挂载云盘操作步骤

1. 查看磁盘分区情况 使用 fdisk -l 命令查看当前系统中所有磁盘的分区情况&#xff0c;找到需要挂载的云盘设备&#xff0c;例如/dev/vdc。 2. 创建新分区 使用 fdisk /dev/vdc 命令对云盘进行分区操作&#xff1a; 输入n创建新分区。 输入p选择创建主分区。 输入1指定分区…

stm32u5串口点灯

通过对单个字符输入的拼接暂存&#xff0c;实现对字符串的比较控制灯的亮灭 char buf[32];char temp[32];while (1){printf("start\n\r");memset(temp,0, sizeof(temp));memset(buf,0, sizeof(buf));while(temp[0] !\r){memset(temp,0, sizeof(temp));HAL_UART_Rece…

PHP 5 6 7 8 9 各重要版本开发特性和选择简要说明

PHP开发&#xff0c;所用版本的选型 PHP5.4是最后一个支持纯正32位操作系统的版本&#xff0c;在Winxp下仍可使用。 PHP5.6是php5.x的最后一个稳定版本&#xff0c;时至今天&#xff0c;仍有很多用户网站系统在使用&#xff0c;网上仍有很多学习资料是基于这个版本&#xff0c;…

Xen 虚拟化技术在云计算平台中的应用详解

Xen 虚拟化技术在云计算平台中的应用详解 随着云计算的飞速发展&#xff0c;虚拟化技术成为构建云平台的核心支柱&#xff0c;而 Xen 作为一种高性能、开源的虚拟化技术&#xff0c;被广泛应用于云计算平台中。Xen 凭借其灵活的架构和出色的性能&#xff0c;为众多云服务商提供…

Elixir语言的正则表达式

Elixir语言中的正则表达式 引言 正则表达式是用于匹配文本模式的一种强大工具。在很多编程语言中&#xff0c;正则表达式被广泛应用于字符串的查找、替换和验证。Elixir作为一门现代化的函数式编程语言&#xff0c;也提供了对正则表达式的支持&#xff0c;方便开发者进行复杂…

MATLAB语言的正则表达式

MATLAB 中的正则表达式使用指南 引言 在数据处理和文本分析中&#xff0c;正则表达式是一种强大而灵活的工具。MATLAB 作为一种广泛应用于科学计算和数据分析的编程语言&#xff0c;提供了对正则表达式的支持&#xff0c;使得用户可以方便地进行字符串匹配与处理。本文将深入…

《Java 中 Thread 类的基本用法总结》

在 Java 编程中&#xff0c;Thread类是实现多线程的核心类之一。下面将对Thread类在创建线程、线程中断、线程等待、线程休眠和获取线程实例等方面的基本用法进行总结。 一、线程创建 继承 Thread 类 定义一个类继承自Thread类。重写run方法&#xff0c;run方法中包含了该线程…

Flannel:Kubernetes 网络方案的“轻骑兵”

Flannel&#xff1a;Kubernetes 网络方案的“轻骑兵” 在 Kubernetes 中&#xff0c;网络是连接所有组件的核心。每个 Pod 都需要一个独立的 IP&#xff0c;方便 Pod 间的通信&#xff0c;而 Flannel 正是解决这个问题的经典容器网络插件&#xff08;CNI&#xff09;。它简单、…

Android - NDK:编译可执行程序在android设备上运行

在android开发中&#xff0c;调试时会把C代码直接编译成可执行程序&#xff0c;运行在android设备上以确认其功能是否正常。 1、基于NDK编译可执行文件 2、push到 /data/local/tmp目录下 3、设置权限&#xff0c;执行。 ndk工程中build.gradle设置 groovy plugins {id com.a…

用matlab调用realterm一次性发送16进制数

realterm采用PutString接口进行发送&#xff0c;需要注意的是发送的16进制数前面要加入0x标志。只有这样&#xff0c;realterm才能将输入的字符串识别为16进制数的形式。 另外,PutString函数支持两个参数输入&#xff0c;第一个参数为字符串&#xff0c;第二个参数为发送形式&…

Python3刷算法来呀,贪心系列题单

1.7号题单 1、​​​​​​k次取反后最大值 2、柠檬水找零 3、分发糖果 示例 1&#xff1a; 输入&#xff1a;ratings [1,0,2] 输出&#xff1a;5 解释&#xff1a;你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。示例 2&#xff1a; 输入&#xff1a;ratings…

Couchbase 和数据湖技术的区别、联系和相关性分析

Couchbase 和数据湖技术&#xff08;如 Delta Lake、Apache Hudi、Apache Iceberg&#xff09;分别是两类不同的数据存储与管理系统&#xff0c;但它们也可以在特定场景中结合使用&#xff0c;以下是它们的区别、联系和相关性分析&#xff1a; 区别&#xff1a; 1. 核心用途&a…

el-table拖拽表格

1、拖拽插件安装 npm i -S vuedraggable // vuedraggable依赖Sortable.js&#xff0c;我们可以直接引入Sortable使用Sortable的特性。 // vuedraggable是Sortable的一种加强&#xff0c;实现组件化的思想&#xff0c;可以结合Vue&#xff0c;使用起来更方便。 2、引入拖拽函数…

深入理解 Android 中的 KeyguardManager

深入理解 Android 中的 KeyguardManager 引言 在 Android 系统中&#xff0c;KeyguardManager 是一个重要的系统服务&#xff0c;负责管理设备的锁屏界面&#xff08;Keyguard&#xff09;。锁屏界面是设备安全性的第一道防线&#xff0c;用于防止未经授权的用户访问设备。Ke…

Transformer 和 Attention机制入门

1. 什么是 Transformer 背景&#xff1a; 在自然语言处理领域&#xff0c;早期常使用循环神经网络&#xff08;RNN&#xff09;及其变体&#xff08;如 LSTM、GRU&#xff09;来处理序列数据&#xff0c;如机器翻译、文本生成等任务。然而&#xff0c;RNN 结构存在以下问题&…

Unity学习笔记(七)使用状态机重构角色攻击

前言 本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记 攻击状态重构 首先我们重构攻击状态的动画 之前的动画&#xff0c;我们是使用状态(isAttacking)攻击次数(comboCounter)完成动画的过渡&#xff0c;这样虽然能完成功能&#xff0c;但是如…

Windows10环境下安装RabbitMq折腾记

最近有个老项目需要迁移到windows10环境&#xff0c;用的是比较老的rabbitmq安装包&#xff0c;如下所示。经过一番折腾&#xff0c;死活服务起不来&#xff0c;最终果断放弃老版本启用新版本。现在把折腾过程记录下&#xff1a; 一、安装erlang 安装完成后的目录结构&#xff…

Three.js 基础概念:构建3D世界的核心要素

文章目录 前言一、场景&#xff08;Scene&#xff09;二、相机&#xff08;Camera&#xff09;三、渲染器&#xff08;Renderer&#xff09;四、物体&#xff08;Object&#xff09;五、材质&#xff08;Material&#xff09;六、几何体&#xff08;Geometry&#xff09;七、光…