微服务升级Springboot3.1过程全记录(详细版)
微服务升级Springboot3.1过程全记录
前言
最近在做微服务升级springboot3.1相关工作,整个过程踩了不少坑,也填了许多坑,有感而发便写下这篇博客,希望能对看到文章的您有所帮助。我们废话不多说,先看我们本次升级的目标版本。
升级前版本号
<java.version>1.8</java.version>
<spring-boot.version>2.6.2</spring-boot.version>
<spring-cloud.version>2020.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
目标版本号
<java.version>17</java.version>
<spring-boot.version>3.1.0</spring-boot.version>
<spring-cloud.version>2022.0.2</spring-cloud.version>
<spring-cloud-alibaba.version>2022.0.0.0-RC2</spring-cloud-alibaba.version>
其他如果mybatis及动态数据源相关包也要跟着升级
包名 | 升级版本 |
---|---|
mybatis-spring-boot-starter | 3.0.2 |
mybatis-plus-boot-starter | 3.5.3.1 |
dynamic-datasource-spring-boot-starter | 3.6.1 |
一、升级须知
升级前先看下如何升级到springboot3.0,需要提前去官网看下springboot3.0迁移指南,因为从3.0开始就已经较之前的版本有了很多的变化。
1.JDK版本
从Spring Boot 3.0开始,最低支持的Java版本变为Java 17、最高支持Java 19,推荐使用LTS版本的Java 17,Oracle官方的JDK可以在这里下载。另外linux版本部署可以使用Docker镜像openjdk:17.0.2
2.Jakarta EE
由于Java EE已经变更为Jakarta EE,包名以 javax开头的需要相应地变更为jakarta。使用Intellij IDEA 可以通过点击重构-迁移软件包和类-Java EE to Jakarta EE来自动完成扫描和迁移。
3.Spring Security
由于从springboot3.0开始Spring Security版本也随之升级至6.0版本,先前5.x版本部分类和写法将不再兼容,由于涉及地方较多,
具体升级指南可参考官方文档 5.8 to 6.0 migration guide
如:org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter 该类已被删除
原本配置WebSecurity和HttpSecurity的configure方法变为普通的@Bean方法,分别返回WebSecurityCustomizer和SecurityFilterChain。
原先的方法authorizeRequests变为authorizeHttpRequests、方法antMatchers变为requestMatchers。
过去写法
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/ignore1", "/ignore2");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic(withDefaults());
}
}
现在写法
@Configuration
public class SecurityConfiguration {
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
// WebSecurityCustomizer是一个类似于Consumer<WebSecurity>的接口,函数接受一个WebSecurity类型的变量,无返回值
// 此处使用lambda实现WebSecurityCustomizer接口,web变量的类型WebSecurity,箭头后面可以对其进行操作
// 使用requestMatchers()代替antMatchers()
return (web) -> web.ignoring().requestMatchers("/ignore1", "/ignore2");
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
//使用authorizeHttpRequests()代替authorizeRequests()
.authorizeHttpRequests((authz) -> authz
//这种写法被称为Lambda DSL,代替原来的and()链式操作
.anyRequest().authenticated()
)
.httpBasic(withDefaults());
// 需要进行build(),返回SecurityFilterChain
return http.build();
}
}
4.图片Banner不再支持
Spring Boot 3.0自定义Banner只支持文本类型(banner.txt),不再支持图片类型。
5.日志日期格式变更
Logback和Log4j2的日志消息的日期和时间部分的默认格式已经改变,以符合ISO-8601标准。新的默认格式yyyy-MM-dd’T’HH:mm:ss.SSSXXX使用T来分隔日期和时间,而不是空格字符,并在最后添加时区偏移。LOG_DATEFORMAT_PATTERN环境变量或logging.pattern.dateformat属性可以用来恢复以前的默认值yyyy-MM-dd HH:mm:ss.SSS。
6.YamlJsonParser被移除
因为SnakeYAML的JSON解析与其他解析器的实现不一致。如果你直接使用YamlJsonParser,请迁移到其他JsonParser实现中。
7.自动配置文件变更
Spring Boot 2.7引入了一个新的文件:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
用于注册自动配置,同时保持与 spring.factories 中注册的向后兼容。Spring Boot 3.0发布后,spring.factories已经被移除,只能通过imports文件来注册自动配置。
8.路径匹配
现在Spring MVC和Spring Webflux 的路径匹配规则已经做了调整,默认情况下尾部斜杠/的匹配机制将和以前不同:
3.0以前/foo/bar等同于/foo/bar/
3.0以后/foo/bar不同于/foo/bar/
弃用配置 server.max-http-header-size
9.server.max-http-header-size已经被弃用
现在用server.max-http-request-header-size替代 ,并且现在该属性只能来配置请求头的大小,不再限制某些Web容器的响应头大小,如果需要限制响应头大小请通过自定义WebServerFactoryCustomizer来实现。
10.Elasticsearch
Elasticsearch的Rest客户端采用了新的API实现,旧的自动配置和Spring Data Elasticsearch中旧的客户端API已经被移除。凡是通过Spring Data Elasticsearch进行自动配置的项目需提前考虑转变成自行引入 elasticsearch-rest-high-level-client方式。
11.Swagger升级
官方网站:(https://springdoc.org/v2/#Introduction)
由于Spring Boot 3使用的是Jakarta EE 9,对应的springdoc版本需要升级到v2,目前里程碑M2版本。支持以下内容:
- OpenAPI 3
- Spring-boot v3 (Java 17 & Jakarta EE 9)
- JSR-303 特别注解 @NotNull, @Min, @Max, 和 @Size.
- Swagger-ui
- OAuth 2
- GraalVM native images
@Api → @Tag
@ApiIgnore → @Parameter(hidden = true) or @Operation(hidden = true) or @Hidden
@ApiImplicitParam → @Parameter
@ApiImplicitParams → @Parameters
@ApiModel → @Schema
@ApiModelProperty(hidden = true) → @Schema(accessMode = READ_ONLY)
@ApiModelProperty → @Schema
@ApiOperation(value = "foo", notes = "bar") → @Operation(summary = "foo", description = "bar")
@ApiParam → @Parameter
@ApiResponse(code = 404, message = "foo") → @ApiResponse(responseCode = "404", description = "foo")
下面以具体controller进行举例
@Tag 描述整个Controller
@Tag(name = "ZooController", description = "动物园API")
@RestController
@RequestMapping("/zoos")
public class ZooController {}
@Operation描述具体接口信息,@Parameter描述参数信息 @ApiResponse 接口响应描述信息
//描述具体接口信息,参数信息
@Operation(summary = "获取动物园详情", description = "返回单个对象",
parameters = {@Parameter(name = "id", description = "动物园id")})
@ApiResponse(responseCode = "2xx",description = "动物园实体对象")
@SneakyThrows
@GetMapping(value = "/{id}")
public ResponseEntity<ZooResponse> detail(@PathVariable("id") Integer id) {
return ResponseEntity.ok(zooService.detail(id));
}
@Schema 描述对象信息
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "ZooResponse", title = "动物园对象")
public class ZooResponse implements Serializable {
@Schema(title = "动物园id")
private Integer id;
@Schema(title = "动物园名称")
private String name;
@Schema(title = "动物园地址")
private String address;
@Schema(title = "动物园电话")
private String telephone;
}
二、升级过程
1.准备
1)下载JDK17,Oracle官方的JDK可以在这里下载。
2)maven 建议3.8+
2.配置IDEA
导入工程后设置工程jdk版本,添加JDK17后并设置工程jdk版本
Enable annotation processing
打开settings(快捷键是Ctrl + Alt + s),搜索栏搜索Annotation Processors ,启用注解处理,勾选Enable annotation processing,如下图
开启自动导入Editor->General->Auto Import
修改Java Complier 版本为17
3.修改pom.xm文件
如果引入了swagger需要改成这个
如果使用了 javax.validation-api 和hibernate-validator相关包
需替换成因为JSR303相关注解需升级至jakarta版本不然不生效
4.替换swagger注解
Idea 快捷命令ctr + shfit +r 全局替换, ctr+r当前文件内替换
Swagger对应注解替换如下:
@Api → @Tag
@ApiIgnore → @Parameter(hidden = true) or @Operation(hidden = true) or @Hidden
@ApiImplicitParam → @Parameter
@ApiImplicitParams → @Parameters
@ApiModel → @Schema
@ApiModelProperty(hidden = true) → @Schema(accessMode = READ_ONLY)
@ApiModelProperty → @Schema
@ApiOperation(value = “foo”, notes = “bar”) → @Operation(summary = “foo”, description = “bar”)
@ApiParam → @Parameter
@ApiResponse(code = 404, message = “foo”) → @ApiResponse(responseCode = “404”, description = “foo”)
5.替换Jakarta EE
由于Java EE已经变更为Jakarta EE,包名以 javax开头的需要相应地变更为jakarta。使用Intellij IDEA 可以通过点击
重构-迁移软件包和类-Java EE to Jakarta EE来自动完成扫描和迁移。
6.启动
7.问题记录
一些小问题我就不记录了
问题一
问题描述:Unable to make field private java.lang.Throwable java.lang.Throwable.cause accessible: module java.base does not “opens java.lang” to unnamed module @4fb3ee4e
原因:JDK8升级高版本问题,
**解决方式:**vm增加:
–add-opens
java.base/java.lang=ALL-UNNAMED
这个我还专门查了下具体原因,可参考:
--add-opens java.base/java.lang=ALL-UNNAMED 是一个用于 Java 命令行启动参数的配置。它用于解决 Java 模块化系统(Java Platform Module System,JPMS)中的访问限制问题。
在 Java 9 中引入了 JPMS,它将 Java SE 平台划分为一系列的模块。每个模块都有自己的 API 和内部实现,可以对其他模块隐藏其内部实现的细节。这样做的目的是为了增强代码的模块化性、安全性和可靠性。
在 JPMS 中,模块之间的访问权限默认是受限的。如果一个模块想要访问另一个模块中的非公开类型(non-exported type),则需要明确声明访问权限。但有时候,由于历史原因或其他因素,某些代码可能依赖于访问其他模块中的非公开类型。这时就可以使用 --add-opens 参数来打开对指定模块的访问权限。
具体到 --add-opens java.base/java.lang=ALL-UNNAMED 这个配置,它的作用是打开对 java.base 模块中的 java.lang 包的访问权限,使得所有未命名的模块都能访问 java.lang 包中的非公开类型。
这个配置一般在以下情况下使用:
第三方库或旧代码依赖于访问 java.lang 包的非公开类型:某些第三方库或旧代码可能直接或间接地依赖于访问 java.lang 包中的非公开类型。为了使这些代码能够在模块化环境下正常工作,可以使用 --add-opens 参数来解决访问限制问题。
迁移传统的非模块化应用程序到模块化环境:如果你正在将一个传统的非模块化的应用程序迁移到模块化环境中,可能会遇到一些访问限制的问题。在这种情况下,可以使用 --add-opens 参数来解决这些问题,以便应用程序能够在模块化环境中正常运行。
需要注意的是,使用 --add-opens 参数打开访问权限可能会破坏 JPMS 的安全性和模块化性,因此应该尽量避免使用它,只在必要时才使用。在使用时,要仔细评估风险,并确保了解应用程序的具体需求和依赖关系,以避免潜在的问题。
问题二
问题描述:spring.redis配置失效
原因:经排查发现spring.redis相关配置被取消,
解决方式 需要替换为spring.data.redis
问题三
问题描述:easyexcel下载文件出现问题
原因:经排查发现有些类已经不在使用
解决方式需要将com.alibaba.easyexcel 版本升级至3.3.1
另外这里如果是旧版本的需要做一些大的调整和改动,具体方式也比较简单可easyexcel的官网。
问题四
问题描述:Error creating bean with name ‘springUtil’: Unsatisfied dependency expressed through field ‘scheduler’: Error creating bean with name ‘slScheduler’ defined in class path resource xxx.class : DataSource name not set.
原因:从spring5.3.6使用org.quartz.impl.jdbcjobstore.JobStoreTX定义quartz的默认数据源支持,如下
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
spring5.3.18等高版本不在支持以上方式进行配置默认数据源
解决方式: 需修改成 org.quartz.jobStore.class=org.springframework.scheduling.quartz.LocalDataSourceJobStore
另外这里如果是旧版本的需要做一些大的调整和改动,具体方式也比较简单可easyexcel的官网。
参考链接
https://blog.csdn.net/renpeng301/article/details/124660893
三、总结
本篇文章的目的是能够提供给各位一些参考,有什么问题评论区沟通,如果都看到这里点个赞不过分吧。