一、升级目标
springboot 3.1.x
java 17
maven-3.9.x
idea 2023.x
原系统环境:
springboot 2.1.x
java 8
maven-3.3.x
idea 2022.x
二、环境准备
1. JDK17下载oracle
image-20231220211150422
安装步骤不清楚的可以自行查一下bd/gg。
安装完成后配置环境变量:如果需要保留jdk8版本(由于本人参与多个项目的研发,大部分都是java8所以需要保留jdk8,这样在使用不同版本研发时直接切换JDK),可以在环境变更中配置两个JAVA8_HOME、JAVA17_HOME,通过JAVA_HOME进行切换。如果不需要保留多版本,默认直接配置到JAVA_HOME中即可。
image-20231220211233583
配置完成后可以在终端使用java -version命令查一下环境是否成功切换到17版本。
2. maven版本升级(springboot3.0兼容maven3.5+以上版本,不需要升级的可以忽略)
下载最新的maven包解压即可maven安装,本次升级安装使用的版本是apache-maven-3.9.5
安装完成后修改一下配置settings.xml(本次升级直接把以前3.3版本中的settings.xml内容复制过来)
3. idea配置
如果需要升级安装的自行下载安装IntelliJ IDEA
打开相关项目修改idea配置:
文件-->项目结构-->项目设置-->SDK修改为:jdk17(如果没有jdk17的话,可以在下方平台设置SDK中添加一个)
文件-->设置-->构建、执行、部署-->java编译器:字节码版本改为17
文件-->设置-->构建、执行、部署-->构建工具-->Maven:相关路径配置修改为新的maven目录
三、版本升级
1. 更新pom.xml版本号
修改spring-boot-starter-parent版本,本次升级使用的版本3.1.2
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.2</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
</properties>
版本修改后,点击重新加载Maven项目,项目在编译期会出现大批量的红色错误告警,不要紧张,此时的错误大部分上都是依赖包找不到,主要分两种:
a. 必现错误:import javax.*
原因是:从Spring Boot 3.0开始,原有的Java EE被彻底弃用(说是规避Oracle的版权问题,可以看这个Spring Boot 3.0为什么废弃了JavaEE,改用了Jakarta EE),换用Jakarta EE,所有javaEE中包名为javax.
的引用都需要更换为jakarta.,其他第三方厂商的工具包也有命名javax.*,所以。
b. 部分依赖包缺失
原因是:在springboot3中很多中间件做了很大的升级,导致有些项目中继承的依赖包找不到了,下面几个是在本次项目升级过程中遇到缺少的包(每个项目中依赖的工具包不一致,不要盲目引用,这里只做参考)。
如果在项目启动时报错:org.springframework.boot:xxx:null:jar
, 先检查一下pom中有没有引用xxx这个包,大概率是没有,直接手动引入一下相关包即可。
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.20.1</version>
<scope>runtime</scope>
</dependency>
c. 启动时第三方库类依赖注册报错
大部分原因:SpringBoot3 中自动配置注册的 spring.factories 写法已废弃,改为了META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
,项目中有使用spring.factories的可以在resource目录下创建META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
,将相关类迁移过来,注意语法不一样了,imports中直接平铺类全路径即可。
如果第三方厂商未做升级的话,会导致启动时第三方库类依赖报错找不到,springboot3.0发布已经将近1年时间大部分的第三方包都已经做了相应升级,如果项目上有引用公司内部或自己团队自研的工具包暂未升级也可以使用本地的imports注册。
以Dailymart中基于RocketMQ的自定义starter为例,第三方未做升级,我们需要将其配置类迁移到此文件下。
image-20231220211733974
2. 适配mysql--jpa(多数据源)
将pom依赖中: mysql-connector-java修改为com.mysql:mysql-connector-j(改不改都行)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
注意:
javax.persistence.EntityManagerFactory
切换为jakarta.persistence.EntityManagerFactory
,两个包中都有EntityManagerFactory。
如果启动报错,并提示找不到相关依赖类则需要修改相关配置
Could not load requested class : org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
Could not load requested class : org.hibernate.dialect.MySQL5InnoDBDialect
原有配置:
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean eduEntityManager(EntityManagerFactoryBuilder builder) {
Map<String, String> properties = new HashMap<>();
properties.put("hibernate.implicit\_naming\_strategy",
"org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
properties.put("hibernate.physical\_naming\_strategy",
"org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
properties.put("hibernate.hbm2ddl.auto",
env.getProperty("spring.jpa.hibernate.ddl-auto"));
properties.put("hibernate.dialect",
env.getProperty("spring.jpa.database-platform"));
return builder
.dataSource(primaryDataSource())
.packages("com.iflytek.rdg.ainote.eduentity")
.persistenceUnit("edu")
.properties(properties)
.build();
}
修改为:
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean eduEntityManager(EntityManagerFactoryBuilder builder) {
Map<String, String> properties = new HashMap<>();
properties.put("hibernate.implicit\_naming\_strategy",
"org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
properties.put("hibernate.physical\_naming\_strategy",
"org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy");
properties.put("hibernate.hbm2ddl.auto",
env.getProperty("spring.jpa.hibernate.ddl-auto"));
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
return builder
.dataSource(primaryDataSource())
.packages("com.iflytek.rdg.ainote.eduentity")
.persistenceUnit("edu")
.properties(properties)
.build();
}
其他的数据源修改方式一样,properties配置可以改为通过配置文件注入。
3. 适配mongo(多数据源)
主要修改MongoDbFactory
的生成方式从SimpleMongoDbFactory
更换为SimpleMongoClientDatabaseFactory
(spring-data-mongodb3.0之前版本使用SimpleMongoDbFactory,3.0之后的版本切换到SimpleMongoClientDatabaseFactory,本次版本从spring-data-mongodb-2.1.17升级到4.1.2)
旧mongo配置:
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoClientURI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
public abstract class AbstractMongoConfig {
private String url;
public MongoDbFactory getMongoDbFactory() {
return new SimpleMongoDbFactory(new MongoClientURI(url, new MongoClientOptions.Builder()));
}
/**
* get mongo template
*
* @return
*/
public abstract MongoTemplate getMongoTemplate();
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
新mongo配置
import com.mongodb.ConnectionString;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
public abstract class AbstractMongoConfig {
private String url;
public SimpleMongoClientDatabaseFactory getMongoDbFactory() {
ConnectionString connectionString = new ConnectionString(url);
MongoClient mongoClient = MongoClients.create(connectionString);
return new SimpleMongoClientDatabaseFactory(mongoClient, connectionString.getDatabase());
}
/**
* get mongo template
*
* @return
*/
public abstract MongoTemplate getMongoTemplate();
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
/**
* 多数据源配置
*/
@Configuration
@ConfigurationProperties(prefix = "spring.data.mongodb.result")
public class ResultMongoConfig extends AbstractMongoConfig {
@Override
@Bean(name = "resultMongoTemplate")
public MongoTemplate getMongoTemplate() {
return new MongoTemplate(getMongoDbFactory());
}
}
4. 适配Redis
本项目配置参考:
(本项目使用场景简单,只需要基本配置,如需要高级定制可以自定义Bean,LettuceConnectionFactory):
@Configuration
public class RedisConfig {
@Bean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
// 配置redisTemplate
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
// key序列化
redisTemplate.setKeySerializer(RedisSerializer.string());
// value序列化
redisTemplate.setValueSerializer(RedisSerializer.json());
// Hash key序列化
redisTemplate.setHashKeySerializer(RedisSerializer.string());
// Hash value序列化
redisTemplate.setHashValueSerializer(RedisSerializer.json());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
5. swagger2升级swagger3
去除swagger2相关依赖,引入swagger3依赖。
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>
增加配置application.yml
springdoc:
api-docs:
path: /api-docs
swagger-ui:
path: /swagger-ui.html
show-actuator: true
swagger注解变化:
swagger2注解 | swagger3注解 | 作用 |
@Api | @Tag | 描述Controller |
@ApiIgnore | @Parameter(hidden = true) @Operation(hidden = true) @Hidden | 描述忽略操作 |
@ApiImplicitParam | @Parameter | 描述参数 |
@ApiImplicitParams | @Parameters | 描述参数 |
@ApiModel | @Schema | 描述对象 |
@ApiModelProperty(hidden = true) | @Schema(accessMode = READ_ONLY) | 描述对象属性 |
@ApiOperation(value = "foo", notes = "bar") | @Operation(summary = "foo", description = "bar") | 描述方法 |
@ApiParam | @Parameter | 描述参数 |
OpenAPI配置:
@Bean
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.info(new Info().title("SpringShop API")
.description("Spring shop sample application")
.version("v0.0.1")
.license(new License().name("Apache 2.0").url("http://springdoc.org")))
.externalDocs(new ExternalDocumentation()
.description("SpringShop Wiki Documentation")
.url("https://springshop.wiki.github.org/docs"));
}
访问地址
http://localhost:8081/swagger-ui/index.html
四. 总结
升级springboot3.0的相关技术博客在网上有几篇,上面的问题都千奇百怪的,除了两个通用问题外其他的和我遇到的问题大部分都不太一样,有小部分问题当前网上还搜索不到解决方案,需要自己去分析,研究对比一下新旧版本的源码说明。
这次升级直接到了最新的springboot版本,所以随便把依赖的第三方包大部分都升级到了最新版本,暂时没有遇到其他的问题。
最后欢迎 加入苏三的星球,你将获得:商城微服务系统、商城系统、秒杀系统、代码生成工具、苏三demo系统等项目实战。系统设计、性能优化、技术选型、高频面试题、底层原理、Spring源码解读、工作经验分享、痛点问题等多个优质专栏。
还有1V1答疑、修改简历、职业规划、送书活动、技术交流。 目前星球已经更新了 4500+ 篇优质内容,还在持续爆肝中.....