代码架构升级方案
目录
- 前言
- 一、OpenRewrite
- 1.OpenRewrite
- 2.应用场景:
- 3.OpenRewrite项目升级、构建方案
- 二、构建方案一:配置文件方式
- 1.pom.xml文件配置相关依赖
- 2. terminal终端执行mvn命令
- 3. 对比项目文件
- 三、构建方案二:recipe.yml脚本方式
- 四、排版
- 五、常见问题
- 1. pom redis配置变更(多一级data:)
- 2. Mybatisplus 自动填充功能
- 七、附录
前言
随着 Spring Boot 2.x 等旧版本即将到期且不再获得支持,迁移到较新版本对于安全性、兼容性和性能改进至关重要。但是,迁移过程面临着一些挑战:
- 重大变更:主要版本升级通常会引入重大变更。Spring Boot 3.x 需要Java 17并从 迁移javax.到jakarta. packages; httpclient由3、4升级5;
- 弃用的 API:许多常用的 API 和模式已被弃用并需要替换。
- 手动更新:**传统迁移需要手动更新依赖项、重构代码和修复兼容性问题。
- 耗时:**大型代码库可能需要数周或数月才能迁移,从而增加项目成本和风险。
- 测试负担:**必须彻底测试每个更改以确保功能保持完好。
一、OpenRewrite
1.OpenRewrite
OpenRewrite是一款开源的自动化代码重构工具,可帮助开发人员减少技术负担。它为框架迁移、安全修复和代码样式提供了预构建的重构方案,将工作量从几小时缩短到几分钟。
OpenRewrite 社区最初专注于 Java,目前正在积极扩展对更多语言和框架的支持。主要特点:
- 自动重构:自动更新代码语法、依赖关系和模式
- 基于配方:使用声明性配方来定义转换规则
- 风格保存:保留原始代码格式和注释
- 大规模变更:可以一致地处理整个代码库
- 可扩展:支持针对特定迁移需求的自定义配方
2.应用场景:
Java 版本升级 :从 Java 8 到 Java 21,从 Java EE 到 Jakarta EE 。
Spring 框架迁移:从 Spring 5 到 Spring 6,从 Spring Boot 2 到 Spring Boot 3。
测试框架迁移: 从 Junit 4 到 Junit 5。
依赖管理:自动更新 Java 项目的 Maven 或 Gradle 依赖,确保使用最新和最安全的库版本。
代码清理和格式化:自动清理和格式化 Java 代码,确保符合项目或组织的编码标准和风格指南。
修复安全漏洞:自动识别和修复 Java 代码中的已知安全漏洞,如使用了有安全问题的库或方法。
3.OpenRewrite项目升级、构建方案
- 配置文件方式:pom.xml文件增加rewrite-maven-plugin插件方式
- 基于recipe.yml脚本方式:recipe.yml脚本定义升级依赖清单
二、构建方案一:配置文件方式
1.pom.xml文件配置相关依赖
原项目pom.xml文件上追加相关依赖、配置:
- 1.rewrite-maven-plugin
- 2.java 21
- 3.lombok 。
配置片断如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><properties><!-- 2.update java 21 --><java.version>21</java.version></properties><dependencies><!-- 3.must Add lombok version to 1.18.34 for compatibility with java 21 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version><scope>provided</scope></dependency></dependencies><build><plugins><!-- 1. Add rewrite-maven-plugin and upgrade SpringBoot_3_2、spring6.12.0--><plugin><groupId>org.openrewrite.maven</groupId><artifactId>rewrite-maven-plugin</artifactId><version>6.16.0</version><configuration><exportDatatables>true</exportDatatables><activeRecipes><recipe>org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_2</recipe></activeRecipes></configuration><dependencies><dependency><groupId>org.openrewrite.recipe</groupId><artifactId>rewrite-spring</artifactId><version>6.12.0</version></dependency></dependencies></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
2. terminal终端执行mvn命令
提示:此过程需下载全量的依赖包、时间较长,必须保证网络通畅
terminal终端执行rewrite插件,开始项目升级、下载依赖:
mvn -X rewrite:run
执行成功后如图:
清理package和删除pom.xml中rewrite-maven-plugin
mvn clean package
3. 对比项目文件
开始处理对比文件。
三、构建方案二:recipe.yml脚本方式
操作步骤:
- 已基准分支checkout一个新分支用于本次代码迁移
- 在项目根目录中放置文件 recipe.yml(文件见 附件)
- 在项目根目录中打开CMD,并运行mvn命令。
mvn命令如下:
mvn -X org.openrewrite.maven:rewrite-maven-plugin:6.16.0:run -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_2 -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.12.0
提示:如果Mvn配置文件不为settings.xml默认文件,则在命令行后追加: -s "D:\setup\apache-maven-3.9.9\conf\settings-ali.xml"
-
对比项目文件
执行成功后,开始处理对比文件。 -
附件recipe.yml
---
type: specs.openrewrite.org/v1beta/recipe
name: org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_2
displayName: Migrate to Spring Boot 3.2
description: |Migrate applications to the latest Spring Boot 3.2 release. This recipe will modify an application's build files, make changes to deprecated/preferred APIs, and migrate configuration settings that have changes between versions. This recipe will also chain additional framework migrations (Spring Framework, Spring Data, etc) that are required as part of the migration to Spring Boot 3.1.
tags:- spring- boot
recipeList:- org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1- org.openrewrite.java.dependencies.UpgradeDependencyVersion:groupId: org.springframework.bootartifactId: "*"newVersion: 3.2.xoverrideManagedVersion: false- org.openrewrite.maven.UpgradePluginVersion:groupId: org.springframework.bootartifactId: spring-boot-maven-pluginnewVersion: 3.2.x- org.openrewrite.java.dependencies.UpgradeDependencyVersion:groupId: org.springframeworkartifactId: "*"newVersion: 6.1.x- org.openrewrite.maven.UpgradeParentVersion:groupId: org.springframework.bootartifactId: spring-boot-starter-parentnewVersion: 3.2.x- org.openrewrite.gradle.plugins.UpgradePluginVersion:pluginIdPattern: org.springframework.bootnewVersion: 3.2.x- org.openrewrite.java.dependencies.AddDependency:groupId: commons-codecartifactId: commons-codecversion: 1.7.xonlyIfUsing: org.apache.commons.codec..*acceptTransitive: true- org.openrewrite.java.spring.security6.UpgradeSpringSecurity_6_2- org.openrewrite.java.spring.boot3.SpringBootProperties_3_2- org.openrewrite.java.spring.framework.UpgradeSpringFramework_6_1- org.openrewrite.java.spring.cloud2023.UpgradeSpringCloud_2023- org.openrewrite.java.ChangeType:oldFullyQualifiedTypeName: org.springframework.boot.task.TaskSchedulerBuildernewFullyQualifiedTypeName: org.springframework.boot.task.ThreadPoolTaskExecutorBuilder- org.openrewrite.java.ChangeType:oldFullyQualifiedTypeName: org.springframework.boot.task.TaskSchedulerCustomizernewFullyQualifiedTypeName: org.springframework.boot.task.ThreadPoolTaskSchedulerCustomizer- org.openrewrite.java.ChangeType:oldFullyQualifiedTypeName: org.springframework.boot.task.TaskExecutorBuildernewFullyQualifiedTypeName: org.springframework.boot.task.ThreadPoolTaskExecutorBuilder- org.openrewrite.java.ChangeType:oldFullyQualifiedTypeName: org.springframework.boot.task.TaskExecutorCustomizernewFullyQualifiedTypeName: org.springframework.boot.task.ThreadPoolTaskExecutorCustomizer- org.openrewrite.java.ChangeType:oldFullyQualifiedTypeName: org.springframework.boot.autoconfigure.transaction.PlatformTransactionManagerCustomizernewFullyQualifiedTypeName: org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizer- org.openrewrite.java.dependencies.UpgradeDependencyVersion:groupId: org.springdocartifactId: "*"newVersion: 2.5.x- org.openrewrite.hibernate.MigrateToHibernate64- org.openrewrite.java.spring.boot3.RelocateLauncherClasses- org.openrewrite.java.spring.boot3.UpgradeMyBatisToSpringBoot_3_2- org.openrewrite.java.springdoc.UpgradeSpringDoc_2_5
四、排版
项目成功编译后对 Maven 项目配置实施最佳实践
CMD窗口执行命令:
mvn -U org.openrewrite.maven:rewrite-maven-plugin:run -Drewrite.activeRecipes=org.openrewrite.maven.BestPractices -Drewrite.exportDatatables=true
对pom中dependency按groupId,artifactId排序
mvn com.github.ekryd.sortpom:sortpom-maven-plugin:sort -Dsort.sortDependencies=groupId,artifactId -Dsort.createBackupFile=false
五、常见问题
1. pom redis配置变更(多一级data:)
spring: data:redis:database: 5host: 127.0.0.1port: 6379password: 123456timeout: 6000msjedis:pool:max-active: 1000max-wait: -1msmax-idle: 10min-idle: 5
2. Mybatisplus 自动填充功能
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/*** 自动填充功能*/
@Component
@Primary
public class CommonObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {// 使用新API: strictInsertFill 替代 setInsertFieldValByNamethis.strictInsertFill(metaObject, "createdAt", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "createdBy", String.class, "admin");this.strictInsertFill(metaObject, "updateAt", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateBy", String.class, "admin");}@Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, "updateAt", LocalDateTime.class, LocalDateTime.now());this.strictUpdateFill(metaObject, "updateBy", String.class, "admin");}
}
七、附录
openrewrite
upgradetojava21
upgradespringboot_3_2
智能代码重构