java8升级到java17的兼容性分析与迁移指南

2025-05-14 09:24:41 189
魁首哥

本文档提供了将项目从 java 8 升级到 java 17 的详细分析和迁移步骤,包括代码修改建议、依赖更新和配置调整。

1. 项目配置更新

1.1 maven 配置

问题位置: pom.xml 及各子模块的 pom.xml


    1.8
    1.8
    1.8

修改建议: 更新 maven 配置以支持 java 17:


    17
    17
    17

1.2 maven 插件更新

问题位置: pom.xml


    org.apache.maven.plugins
    maven-compiler-plugin
    3.8.1
    
        1.8
        1.8
        utf-8
    

修改建议: 更新 maven 编译插件配置:


    org.apache.maven.plugins
    maven-compiler-plugin
    3.10.1
    
        17
        17
        utf-8
        
            --add-opens=java.base/java.lang=all-unnamed
            --add-opens=java.base/java.io=all-unnamed
            --add-opens=java.base/java.util=all-unnamed
            --add-opens=java.base/java.util.concurrent=all-unnamed
        
    

1.3 spring boot 版本更新

问题位置: pom.xml


    org.springframework.boot
    spring-boot-starter-parent
    2.7.18
    

修改建议: 更新 spring boot 版本至少为 2.7.x 或更高版本(推荐 3.x),以确保与 java 17 完全兼容:


    org.springframework.boot
    spring-boot-starter-parent
    3.1.5
    

注意: 如果升级到 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


    jakarta.xml.bind
    jakarta.xml.bind-api
    4.0.0


    org.glassfish.jaxb
    jaxb-runtime
    4.0.2

2.2 javabeans activation framework (jaf)

问题: java 9+ 移除了 javax.activation

修改建议: 添加以下依赖到 pom.xml


    jakarta.activation
    jakarta.activation-api
    2.1.1


    org.eclipse.angus
    angus-activation
    2.0.0

2.3 java annotation api

问题位置: 多个文件中使用了 javax.annotation.*

import javax.annotation.resource;

修改建议: 添加以下依赖到 pom.xml


    jakarta.annotation
    jakarta.annotation-api
    2.1.1

并更新导入语句:

import jakarta.annotation.resource;

2.4 java mail api

问题位置: /core/alarm/impl/emailjobalarm.java

修改建议: 添加以下依赖:


    jakarta.mail
    jakarta.mail-api
    2.1.1


    org.eclipse.angus
    jakarta.mail
    2.0.1

2.5 java servlet api

问题位置: 多个文件中使用了 javax.servlet.*

import javax.servlet.http.httpservletrequest;

修改建议: 添加以下依赖到 pom.xml


    jakarta.servlet
    jakarta.servlet-api
    6.0.0
    provided

并更新导入语句:

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

2.7.18
2021.0.0
2021.1

修改建议: 更新到支持 java 17 的版本:

3.1.5
2022.0.4
2022.0.0.0

6.2 mybatis 和 mybatis-plus

问题位置: pom.xml

3.5.1
4.1.3

修改建议: 更新到支持 java 17 的版本:

3.5.4.1
4.2.0

6.3 shiro

问题位置: pom.xml

1.12.0
3.11.0
3.2.2

修改建议: shiro 1.12.0 已支持 java 17,但建议更新 jwt 库:

4.4.0

6.4 数据库驱动

问题位置: pom.xml

42.2.25
11.2.0.3
4.0
8.0.27

修改建议: 更新到支持 java 17 的版本:

42.6.0
23.3.0.23.09 
12.4.2.jre11 
8.2.0 

并更新依赖声明:



    com.mysql
    mysql-connector-j
    ${mysql-connector-j.version}




    com.oracle.database.jdbc
    ojdbc11
    ${ojdbc.version}




    com.microsoft.sqlserver
    mssql-jdbc
    ${mssql-jdbc.version}

6.5 日志框架

问题位置: pom.xml

2.17.0
1.2.9

修改建议: 更新到支持 java 17 的版本:

2.22.0
1.4.11

6.6 json 处理库

问题位置: pom.xml

1.2.83

修改建议: 更新到支持 java 17 的版本,或考虑切换到 jackson:

2.0.42

并更新依赖:

    com.alibaba.fastjson2
    fastjson2
    ${fastjson2.version}

6.7 其他工具库

问题位置: pom.xml

5.8.25
29.0-jre
2.6
2.11.0
1.9.4

修改建议: 更新到支持 java 17 的版本:

32.1.3-jre
3.13.0 
2.15.0
1.9.4 

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 response = client.send(request, httpresponse.bodyhandlers.ofstring());

11. 集合和流 api 增强

11.1 集合工厂方法

修改建议: 使用 java 9+ 的集合工厂方法创建不可变集合:

// 旧代码
list list = collections.unmodifiablelist(arrays.aslist("a", "b", "c"));
map map = collections.unmodifiablemap(new hashmap() {{
    put("one", 1);
    put("two", 2);
}});

// 新代码
list list = list.of("a", "b", "c");
map 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的资料请关注代码网其它相关文章!

分享
海报
189
上一篇:springboot项目如何开启https服务 下一篇:一文详解Java中的包装类和泛型

忘记密码?

图形验证码