本文档提供了将项目从 java 8 升级到 java 17 的详细分析和迁移步骤,包括代码修改建议、依赖更新和配置调整。
1. 项目配置更新
1.1 maven 配置
问题位置: pom.xml
及各子模块的 pom.xml
<properties> <java.version>1.8</java.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties>
修改建议: 更新 maven 配置以支持 java 17:
<properties> <java.version>17</java.version> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties>
1.2 maven 插件更新
问题位置: pom.xml
<plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-compiler-plugin</artifactid> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>utf-8</encoding> </configuration> </plugin>
修改建议: 更新 maven 编译插件配置:
<plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-compiler-plugin</artifactid> <version>3.10.1</version> <configuration> <source>17</source> <target>17</target> <encoding>utf-8</encoding> <compilerargs> <arg>--add-opens=java.base/java.lang=all-unnamed</arg> <arg>--add-opens=java.base/java.io=all-unnamed</arg> <arg>--add-opens=java.base/java.util=all-unnamed</arg> <arg>--add-opens=java.base/java.util.concurrent=all-unnamed</arg> </compilerargs> </configuration> </plugin>
1.3 spring boot 版本更新
问题位置: pom.xml
<parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.7.18</version> <relativepath/> </parent>
修改建议: 更新 spring boot 版本至少为 2.7.x 或更高版本(推荐 3.x),以确保与 java 17 完全兼容:
<parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>3.1.5</version> <relativepath/> </parent>
注意: 如果升级到 spring boot 3.x,需要同时处理 jakarta ee 相关的包名变更(javax.* 变为 jakarta.*)。
2. 移除的 java ee 模块
java 9 及以上版本移除了许多 java ee 模块,这些模块需要作为单独的依赖项添加。
2.1 jaxb (java architecture for xml binding)
问题: java 9+ 移除了 javax.xml.bind
包
修改建议: 添加以下依赖到 pom.xml
:
<dependency> <groupid>jakarta.xml.bind</groupid> <artifactid>jakarta.xml.bind-api</artifactid> <version>4.0.0</version> </dependency> <dependency> <groupid>org.glassfish.jaxb</groupid> <artifactid>jaxb-runtime</artifactid> <version>4.0.2</version> </dependency>
2.2 javabeans activation framework (jaf)
问题: java 9+ 移除了 javax.activation
包
修改建议: 添加以下依赖到 pom.xml
:
<dependency> <groupid>jakarta.activation</groupid> <artifactid>jakarta.activation-api</artifactid> <version>2.1.1</version> </dependency> <dependency> <groupid>org.eclipse.angus</groupid> <artifactid>angus-activation</artifactid> <version>2.0.0</version> </dependency>
2.3 java annotation api
问题位置: 多个文件中使用了 javax.annotation.*
包
import javax.annotation.resource;
修改建议: 添加以下依赖到 pom.xml
:
<dependency> <groupid>jakarta.annotation</groupid> <artifactid>jakarta.annotation-api</artifactid> <version>2.1.1</version> </dependency>
并更新导入语句:
import jakarta.annotation.resource;
2.4 java mail api
问题位置: /core/alarm/impl/emailjobalarm.java
修改建议: 添加以下依赖:
<dependency> <groupid>jakarta.mail</groupid> <artifactid>jakarta.mail-api</artifactid> <version>2.1.1</version> </dependency> <dependency> <groupid>org.eclipse.angus</groupid> <artifactid>jakarta.mail</artifactid> <version>2.0.1</version> </dependency>
2.5 java servlet api
问题位置: 多个文件中使用了 javax.servlet.*
包
import javax.servlet.http.httpservletrequest;
修改建议: 添加以下依赖到 pom.xml
:
<dependency> <groupid>jakarta.servlet</groupid> <artifactid>jakarta.servlet-api</artifactid> <version>6.0.0</version> <scope>provided</scope> </dependency>
并更新导入语句:
import jakarta.servlet.http.httpservletrequest;
3. 反射 api 变更
3.1 反射访问非公共成员
问题位置:
xxx/common/util/reflecthelper.java
xxx/config/mybatis/mybatisinterceptor.java
xxx/calc/utils/accessdbutils.java
问题描述: java 9+ 对反射 api 进行了更严格的封装,特别是对非公共成员的访问限制更严格。
修改建议:
1.确保在访问非公共成员时显式设置可访问性,并在使用后恢复:
try { field.setaccessible(true); object value = field.get(object); // 使用 value return value; } finally { field.setaccessible(false); }
2.如果在运行时遇到 inaccessibleobjectexception
,需要添加 jvm 参数:
--add-opens java.base/java.lang=all-unnamed --add-opens java.base/java.util=all-unnamed
3.2 反射获取方法和字段
问题位置:
xxx/service/impl/heatingdeviceserviceimpl.java
修改建议:
- 使用
class.getdeclaredmethod()
代替class.getmethod()
来获取非公共方法 - 确保正确处理泛型类型
- 添加适当的异常处理
try { method method = clazz.getdeclaredmethod(methodname, parametertypes); method.setaccessible(true); return method.invoke(object, args); } catch (nosuchmethodexception | illegalaccessexception | invocationtargetexception e) { throw new runtimeexception("反射调用方法失败", e); } finally { // 可选:恢复访问控制 }
4. 内部 api 使用
4.1 sun.* 包使用
问题描述: java 9+ 严格限制了对 sun.*
包的访问。
修改建议:
- 检查项目中是否使用了
sun.*
包下的类 - 如果有,寻找标准 api 替代方案
- 如果必须使用,考虑使用
--add-exports
或--add-opens
命令行参数
5. 语言特性优化
5.1 switch 表达式
问题位置:
xxx/common/util/text/convert.java
xxx/common/system/query/querygenerator.java
xxx/biz/service/impl/noderelationconvertserviceimpl.java
修改建议: 使用 java 12+ 的 switch 表达式语法,更简洁、更安全:
// 旧代码 double result; switch (operator) { case "+": result = num1 + num2; break; case "-": result = num1 - num2; break; // ... } return result; // 新代码 double result = switch (operator) { case "+" -> num1 + num2; case "-" -> num1 - num2; case "*" -> num1 * num2; case "/" -> { if (num2 == 0) { log.warn("除数不能为零"); yield 0.0; } yield num1 / num2; } default -> { log.warn("不支持的操作符: {}", operator); yield 0.0; } }; return result;
5.2 文本块
问题位置: 项目中有多处使用长字符串拼接的代码
修改建议: 使用 java 15+ 的文本块特性,提高代码可读性:
// 旧代码 string sql = "select * " + "from users " + "where status = 'active' " + "and created_date > ?"; // 新代码 string sql = """ select * from users where status = 'active' and created_date > ? """;
5.3 instanceof 模式匹配
问题位置:
xxx/common/aspect/typetransaspect.java
修改建议: 使用 java 16+ 的 instanceof 模式匹配,简化类型检查和转换:
// 旧代码 if (result instanceof result) { if (((result) result).getdata() instanceof ipage) { // 使用 ((result) result).getdata() } } // 新代码 if (result instanceof result res && res.getdata() instanceof ipage page) { // 直接使用 page }
5.4 record 类型
修改建议: 对于简单的数据传输对象,考虑使用 java 16+ 的 record 类型:
// 旧代码 public class userdto { private final string name; private final string email; public userdto(string name, string email) { this.name = name; this.email = email; } // getters, equals, hashcode, tostring } // 新代码 public record userdto(string name, string email) {}
6. 第三方库兼容性
6.1 spring boot 和 spring framework
问题位置: pom.xml
<springboot.version>2.7.18</springboot.version> <spring-cloud.version>2021.0.0</spring-cloud.version> <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
修改建议: 更新到支持 java 17 的版本:
<springboot.version>3.1.5</springboot.version> <spring-cloud.version>2022.0.4</spring-cloud.version> <spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version>
6.2 mybatis 和 mybatis-plus
问题位置: pom.xml
<mybatis-plus.version>3.5.1</mybatis-plus.version> <dynamic-datasource-spring-boot-starter.version>4.1.3</dynamic-datasource-spring-boot-starter.version>
修改建议: 更新到支持 java 17 的版本:
<mybatis-plus.version>3.5.4.1</mybatis-plus.version> <dynamic-datasource-spring-boot-starter.version>4.2.0</dynamic-datasource-spring-boot-starter.version>
6.3 shiro
问题位置: pom.xml
<shiro.version>1.12.0</shiro.version> <java-jwt.version>3.11.0</java-jwt.version> <shiro-redis.version>3.2.2</shiro-redis.version>
修改建议: shiro 1.12.0 已支持 java 17,但建议更新 jwt 库:
<java-jwt.version>4.4.0</java-jwt.version>
6.4 数据库驱动
问题位置: pom.xml
<postgresql.version>42.2.25</postgresql.version> <ojdbc6.version>11.2.0.3</ojdbc6.version> <sqljdbc4.version>4.0</sqljdbc4.version> <mysql-connector-java.version>8.0.27</mysql-connector-java.version>
修改建议: 更新到支持 java 17 的版本:
<postgresql.version>42.6.0</postgresql.version> <ojdbc.version>23.3.0.23.09</ojdbc.version> <!-- 替换 ojdbc6 --> <mssql-jdbc.version>12.4.2.jre11</mssql-jdbc.version> <!-- 替换 sqljdbc4 --> <mysql-connector-j.version>8.2.0</mysql-connector-j.version> <!-- 替换 mysql-connector-java -->
并更新依赖声明:
<!-- mysql --> <dependency> <groupid>com.mysql</groupid> <artifactid>mysql-connector-j</artifactid> <version>${mysql-connector-j.version}</version> </dependency> <!-- oracle --> <dependency> <groupid>com.oracle.database.jdbc</groupid> <artifactid>ojdbc11</artifactid> <version>${ojdbc.version}</version> </dependency> <!-- sql server --> <dependency> <groupid>com.microsoft.sqlserver</groupid> <artifactid>mssql-jdbc</artifactid> <version>${mssql-jdbc.version}</version> </dependency>
6.5 日志框架
问题位置: pom.xml
<log4j2.version>2.17.0</log4j2.version> <logback.version>1.2.9</logback.version>
修改建议: 更新到支持 java 17 的版本:
<log4j2.version>2.22.0</log4j2.version> <logback.version>1.4.11</logback.version>
6.6 json 处理库
问题位置: pom.xml
<fastjson.version>1.2.83</fastjson.version>
修改建议: 更新到支持 java 17 的版本,或考虑切换到 jackson:
<fastjson2.version>2.0.42</fastjson2.version>
并更新依赖:
<groupid>com.alibaba.fastjson2</groupid> <artifactid>fastjson2</artifactid> <version>${fastjson2.version}</version> </dependency>
6.7 其他工具库
问题位置: pom.xml
<hutool.version>5.8.25</hutool.version> <guava.version>29.0-jre</guava.version> <commons.version>2.6</commons.version> <commons-io.version>2.11.0</commons-io.version> <commons-beanutils.version>1.9.4</commons-beanutils.version>
修改建议: 更新到支持 java 17 的版本:
<guava.version>32.1.3-jre</guava.version> <commons-lang3.version>3.13.0</commons-lang3.version> <!-- 替换 commons.version --> <commons-io.version>2.15.0</commons-io.version> <commons-beanutils.version>1.9.4</commons-beanutils.version> <!-- 已是最新版本 -->
7. 模块系统兼容性
非模块化应用的兼容性
问题描述: java 9+ 引入了模块系统,可能会影响非模块化应用的行为。
修改建议:
- 添加
--add-modules
参数以访问已移除的模块 - 添加
--add-opens
参数以允许反射访问 - 考虑将应用迁移到模块系统
8. 安全相关变更
8.1 加密算法支持
问题位置:
xxx/common/util/security/securitytools.java
xxx/system/service/util/securityutil.java
问题描述: java 17 可能移除了一些不安全的加密算法。
修改建议:
- 检查使用的加密算法是否在 java 17 中仍然受支持
- 更新到更安全的算法和更长的密钥长度
- 使用 java 17 的新安全特性
8.2 tls 配置
问题位置:
xxx/common/util/httputils.java
问题描述: java 17 默认禁用了一些不安全的 tls 版本和密码套件。
修改建议:
- 更新 ssl/tls 配置,使用 tls 1.3 或 tls 1.2
- 移除对不安全密码套件的支持
- 使用更安全的证书验证机制
9. 字符串和文本处理
9.1 字符串处理方法
问题描述: java 11+ 引入了许多新的字符串处理方法。
修改建议: 利用 java 11+ 新增的字符串处理方法提高代码效率:
- 使用
string.strip()
代替string.trim()
- 使用
string.isblank()
检查空白字符串 - 使用
string.lines()
处理多行文本 - 使用
string.repeat(n)
重复字符串
9.2 正则表达式改进
问题描述: java 11+ 改进了正则表达式 api。
修改建议: 利用 java 11+ 改进的正则表达式 api:
- 使用
pattern.asmatchpredicate()
创建谓词 - 使用命名捕获组简化正则表达式
10. 网络 api 变更
http 客户端
问题位置:
xxx/calc/utils/sslclient.java
问题描述: java 11 引入了新的 http 客户端 api,旧的 http 客户端 api 可能在未来版本中被移除。
修改建议: 考虑使用 java 11+ 的新 http 客户端 api:
httpclient client = httpclient.newbuilder() .version(httpclient.version.http_2) .followredirects(httpclient.redirect.normal) .connecttimeout(duration.ofseconds(20)) .sslcontext(sslcontext) .build(); httprequest request = httprequest.newbuilder() .uri(uri.create(url)) .header("content-type", "application/json") .post(httprequest.bodypublishers.ofstring(jsonbody)) .build(); httpresponse<string> response = client.send(request, httpresponse.bodyhandlers.ofstring());
11. 集合和流 api 增强
11.1 集合工厂方法
修改建议: 使用 java 9+ 的集合工厂方法创建不可变集合:
// 旧代码 list<string> list = collections.unmodifiablelist(arrays.aslist("a", "b", "c")); map<string, integer> map = collections.unmodifiablemap(new hashmap<string, integer>() {{ put("one", 1); put("two", 2); }}); // 新代码 list<string> list = list.of("a", "b", "c"); map<string, integer> map = map.of("one", 1, "two", 2);
11.2 stream api 增强
修改建议: 利用 java 9+ 增强的 stream api:
- 使用
stream.ofnullable()
处理可能为 null 的元素 - 使用
stream.iterate()
的新重载方法 - 使用
takewhile()
和dropwhile()
方法 - 使用
stream.tolist()
代替collect(collectors.tolist())
12. 测试建议
在迁移到 java 17 后,建议进行以下测试:
- 编译测试:确保所有代码都能在 java 17 下编译通过
- 单元测试:运行所有单元测试,确保功能正常
- 集成测试:测试与外部系统的集成
- 性能测试:java 17 在性能方面有显著改进,但某些情况下可能需要调整
- 安全测试:确保加密和安全相关功能正常工作
13. 迁移步骤建议
1.准备阶段
- 创建项目分支进行迁移
- 更新 jdk 版本到 java 17
- 更新 maven 配置
2.依赖更新阶段
- 更新 spring boot 和 spring framework
- 更新数据库驱动
- 更新其他第三方库
3.代码修改阶段
- 添加缺失的 java ee 模块依赖
- 修复反射 api 使用
- 处理内部 api 访问问题
- 更新包导入(javax.* → jakarta.*,如果使用 spring boot 3)
4.优化阶段
- 利用 java 9-17 的新特性优化代码
- 更新安全相关配置
- 更新网络 api 使用
5.测试阶段
- 运行单元测试
- 进行集成测试
- 进行性能测试
6.部署阶段
- 更新部署脚本和配置
- 在测试环境部署
- 监控应用性能和稳定性
结论
将项目从 java 8 升级到 java 17 是一项重要的工作,可以带来性能改进、安全增强和新特性支持。主要的迁移工作包括:
- 更新 maven 配置和依赖
- 添加被移除的 java ee 模块依赖
- 修复反射 api 使用
- 处理内部 api 访问问题
- 更新第三方库版本
- 利用 java 9-17 的新特性优化代码
通过系统性地解决这些问题,项目可以顺利迁移到 java 17,并充分利用新版本带来的好处。
以上就是java8升级到java17的兼容性分析与迁移指南的详细内容,更多关于java8升级java17的资料请关注代码网其它相关文章!
发表评论