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

目录

背景:

一、maven升级

二、代码改造

[2.1 javax替换为jakarta](#2.1 javax替换为jakarta)

[2.2 swagger2升级swagger3相关更新](#2.2 swagger2升级swagger3相关更新)

[2.2.1 新增SpringDocConfig配置类](#2.2.1 新增SpringDocConfig配置类)

[2.2.2 全局代码更新](#2.2.2 全局代码更新)

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

[2.3 Mybatis Plus升级](#2.3 Mybatis Plus升级)

[2.4 logback.xml更新](#2.4 logback.xml更新)

[2.5 application.yml更新](#2.5 application.yml更新)

三、其他注意事项

[3.1 Jdk相关](#3.1 Jdk相关)

[3.1.1 启动参数](#3.1.1 启动参数)

[3.2 Spring相关](#3.2 Spring相关)

[3.2.1 尾部斜杠匹配取消](#3.2.1 尾部斜杠匹配取消)

[3.2.2 RequestParam等传参报错](#3.2.2 RequestParam等传参报错)

[3.3.3 循环依赖启动报错](#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

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

XML 复制代码
<!-- 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版本)

XML 复制代码
<!-- 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配置类

java 复制代码
/**
 * 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;

    @Bean
    public 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中注解的对照关系,方便升级时对照。

swagger2 swagger3 说明
@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 全局代码替换(普通+正则替换)

java 复制代码
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 = $1


import 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 等)。

例如:

XML 复制代码
<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.

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

java 复制代码
public String getVersion(@RequestParam String authCode) {}

错误原因:

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

解决方式:

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

java 复制代码
public String getVersion(@RequestParam(value = "authCode", defaultValue = "") String authCode) {}

或者

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

XML 复制代码
<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中增加允许循环依赖配置解决

bash 复制代码
spring:
  main:
    allow-circular-references: true
相关推荐
笑小枫4 分钟前
SpringBoot 使用 Cache 集成 Redis做缓存保姆教程
spring boot·redis·缓存
Stimd10 分钟前
【重写SpringFramework】第三章小结(chapter 3-16)
java·后端·spring
潜洋19 分钟前
Spring Boot教程之五十二:CrudRepository 和 JpaRepository 之间的区别
java·大数据·数据库·spring boot
潘多编程32 分钟前
Spring Boot微服务中进行数据库连接池的优化?
数据库·spring boot·微服务
TENET信条35 分钟前
代码随想录 day55 第十一章 图论part05
java·开发语言·图论
xiangzhihong842 分钟前
Spring Boot整合Minio实现文件上传
java·spring boot·后端
涔溪1 小时前
如何在 IDEA 中配置 npm ?
java·npm·intellij-idea
V+zmm101341 小时前
基于微信小程序疫苗预约系统ssm+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
MasterNeverDown1 小时前
maven发包踩坑
java·maven
m0_749317521 小时前
蓝桥杯训练
java·学习·职场和发展·蓝桥杯