2.5 模块化迁移策略:从传统项目到模块化系统
模块化迁移策略:从传统项目到模块化系统
将传统 Java 项目迁移至 JDK 9 模块化系统是一项系统性工程,需分阶段实施以降低风险。以下是详细的迁移策略、工具使用和实战示例。
1. 迁移阶段划分
| 阶段 | 目标 | 关键操作 |
|---|---|---|
| 阶段1:兼容性验证 | 确保项目能在 JDK 9 上无模块化运行 | 使用类路径运行,处理废弃 API 和依赖冲突 |
| 阶段2:模块化试点 | 部分代码转为模块,依赖自动模块(非模块化 JAR) | 创建 module-info.java,逐步迁移核心模块 |
| 阶段3:完整模块化 | 全项目模块化,显式管理所有依赖 | 重构模块结构,移除自动模块依赖 |
2. 阶段1:兼容性验证
目标
在不修改代码的情况下,验证项目在 JDK 9 上的运行能力。
关键步骤
-
编译与运行测试
javac -d out -classpath lib/*.jar src/**/*.java java -classpath out:lib/*.jar com.example.Main -
处理兼容性问题
- 废弃 API 检测:
jdeprscan --release 9 myapp.jar - 内部 API 访问:
- 错误示例:
sun.misc.BASE64Encoder不可访问。 - 修复方案:替换为标准 API(
java.util.Base64)。
- 错误示例:
- 废弃 API 检测:
-
依赖冲突排查
- 工具:使用
jdeps分析依赖树:jdeps --class-path lib/*.jar -recursive myapp.jar
- 工具:使用
3. 阶段2:模块化试点
目标
将部分代码转换为模块,依赖未模块化的第三方库作为自动模块。
关键步骤
-
创建初始模块
- 选择核心模块(如
com.utils),添加module-info.java:module com.utils { exports com.utils; requires transitive org.apache.commons.lang3; // 自动模块名:commons.lang3 }
- 选择核心模块(如
-
模块化编译与运行
javac -d out --module-source-path src --module com.utils java --module-path out:lib -m com.utils/com.example.Main -
处理自动模块依赖
- 自动模块命名规则:
- JAR 文件名
log4j-api-2.17.1.jar→ 模块名log4j.api。
- JAR 文件名
- 依赖传递:自动模块默认依赖所有模块,但需显式声明核心 JDK 模块。
- 自动模块命名规则:
4. 阶段3:完整模块化
目标
全项目模块化,显式管理所有依赖(包括第三方库)。
关键步骤
-
重构模块结构
- 模块拆分:按功能拆分模块(如
com.user、com.order)。 - 模块描述符:为每个模块编写
module-info.java。
- 模块拆分:按功能拆分模块(如
-
处理第三方库
- 方案1:等待库官方提供模块化版本(如 Log4j 2.17+)。
- 方案2:手动为库添加模块描述符(生成
module-info.java)。
-
显式依赖管理
module com.myapp { requires java.sql; requires com.utils; requires org.apache.logging.log4j; // 显式声明 Log4j 模块 } -
生成定制化 JRE
jlink --module-path $JAVA_HOME/jmods:mods \ --add-modules com.myapp,java.sql \ --output myapp-runtime
5. 迁移工具链
| 工具 | 用途 | 示例命令 |
|---|---|---|
| jdeps | 分析依赖关系和模块兼容性 | jdeps --generate-module-info ./out myapp.jar |
| jdeprscan | 检测废弃 API 使用 | jdeprscan --release 9 myapp.jar |
| jlink | 生成最小化 JRE | jlink --add-modules java.base... |
| jmod | 创建 JMOD 文件(可选) | jmod create --class-path ... |
6. 常见问题与解决方案
| 问题 | 解决方案 |
|---|---|
| 模块依赖未找到 | 检查 requires 声明,确保依赖模块在模块路径中,或添加 --add-modules <模块名>。 |
| 反射访问失败(如 Hibernate) | 使用 opens 开放包权限:opens com.myapp.model to org.hibernate。 |
| 自动模块名冲突 | 重命名 JAR 文件(如 my-lib-1.0.jar → mylib.jar)以生成唯一模块名。 |
| 性能下降 | 检查垃圾回收配置(如 -XX:+UseG1GC),优化模块依赖减少加载时间。 |
7. 迁移最佳实践
- 分阶段实施:
- 先迁移底层工具模块,再逐步向上层业务模块推进。
- 自动化测试:
- 在每个阶段运行单元测试和集成测试(如 JUnit + CI/CD)。
- 依赖管理:
- 优先选择已适配 JDK 9 的第三方库(如 Spring 5、Hibernate 5.3+)。
- 文档与协作:
- 维护模块依赖图和迁移日志,与团队共享知识。
8. 实战示例:迁移 Spring Boot 应用
步骤1:兼容性验证
- 处理问题:
- 替换
javax.xml.bind(JDK 9 中已移除)为第三方实现(如org.glassfish.jaxb)。 - 添加
--add-opens参数开放反射权限:java --add-opens java.base/java.lang=ALL-UNNAMED -jar myapp.jar
- 替换
步骤2:模块化核心组件
- 模块描述符:
module com.myapp.core { requires spring.boot; requires spring.context; opens com.myapp.model to spring.core; // 允许 Spring 反射扫描 }
步骤3:生成定制化 JRE
jlink --module-path $JAVA_HOME/jmods:mods \ --add-modules com.myapp.core,java.sql \ --output springboot-runtime
9. 总结
模块化迁移需结合工具链、分阶段策略和严格测试,核心在于渐进式重构和显式依赖管理。通过模块化,项目将获得更强的封装性、更清晰的架构和更高效的运行时,为后续技术演进(如云原生、微服务)奠定基础。
相关文章:
2.5 模块化迁移策略:从传统项目到模块化系统
模块化迁移策略:从传统项目到模块化系统 将传统 Java 项目迁移至 JDK 9 模块化系统是一项系统性工程,需分阶段实施以降低风险。以下是详细的迁移策略、工具使用和实战示例。 1. 迁移阶段划分 阶段目标关键操作阶段1:兼容性验证确保项目能在…...
java商城解决方案
数字化时代,电子商务已成为企业拓展市场的重要渠道。对于想要建立在线商店的企业来说,选择正确的技术堆栈至关重要。 Java作为一种成熟且广泛使用的编程语言,为构建购物中心提供了强大的功能和灵活性。 商城Java源码:商城开发的核…...
算法-哈希表篇05-四数相加II
四数相加II 力扣题目链接 题目描述 给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 < i, j, k, l < n nums1[i] nums2[j] nums3[k] nums4[l] 0 解题思路 把数…...
WPS或word接入智能AI
DeepSeek接入WPS 配置WPS (1)下载 OfficeAl助手插件: 插件下载地址:https://www.office-ai.cn/。 安装插件后,打开WPS,菜单栏会新增"OfficeAl助手”选项卡。 如果没有出现, 左上找到文件菜单 -> 选项 ,在…...
Leetcode:学习记录
一、滑动窗口 1. 找出数组中元素和大于给定值的子数组的最小长度 右指针从左到右遍历,在每个右指针下,如果去掉左边元素的元素和大于等于给定值则左指针右移一次,直到小于给定值,右指针右移一个。 2.找到乘积小于给定值的子数组…...
86.在 Vue 3 中使用 OpenLayers 自定义组件(放大、缩小、长度测量、面积测量)
摘要 在 WebGIS 开发中,OpenLayers 是一个非常强大的开源地图库,它可以在 Web 应用中渲染高效的地图。本篇文章将介绍如何在 Vue 3 中使用 OpenLayers,并封装一个自定义地图控件组件,实现地图的放大、缩小、长度测量和面积测量功能…...
http 与 https 的区别?
HTTP(超文本传输协议)和 HTTPS(安全超文本传输协议)是互联网通信的基础协议。随着网络技术的发展和安全需求的提升,HTTPS变得越来越重要。本文将深入探讨HTTP与HTTPS之间的区别,包括其工作原理、安全性、性能、应用场景及未来发展等。 1. HTTP与HTTPS的基本概念 1.1 HT…...
SAIL-RK3576单板运行7b的deepseek对话模型
大概流程: 使用ollama工具进行deepseek的模型部署和使用,先安装ollama工具,在使用ollama工具拉去deepseek模型,最后使用ollama工具加载deepseek模型进行对话...
独立C++ asio库实现的UDP Server
以下是一个使用独立的 C Asio 库实现的 UDP 服务器的示例代码。这个 UDP 服务器可以监听指定端口,接收客户端发送的数据,并将接收到的数据原样返回给客户端。 #include <iostream> #include <asio.hpp> #include <array>class UdpSer…...
SQL Server STUFF 函数的用法及应用场景
在 SQL Server 中,STUFF 函数是一种强大的字符串处理工具,常用于删除指定位置的字符并插入新的字符。通过这个函数,开发者能够灵活地修改字符串,从而在数据处理、字符串拼接和格式化等方面大显身手。本文将深入探讨 STUFF 函数的语…...
MongoDB进阶篇-索引
文章目录 1. 索引概述 2. 索引的类型 2.1 单字段索引 2.2 复合索引 2.3 其他索引 2.3.1 地理空间索引(Geospatial Index) 2.3.2 文本索引(Text Indexes) 2.3.3 哈希索引(Hashed Indexes) 3. 索引相关操作 3.1 查看索引 3.2 创建索引 3.3.1 创建单字段索引 3.3.2 创建复合…...
《机器学习数学基础》补充资料:柯西—施瓦茨不等式以及相关证明
《机器学习数学基础》 153 页,针对图 3-4-3,提出了一个问题:“点 A A A 到 W \mathbb{W} W 上的一个点的距离有无穷多个。现在,我们最关心的是其中最短的那个,怎么找?请参阅 3.6 节。”并且,在…...
VisionPro 划痕检测小练习
划痕检测,我这里用到的是Sobel算子和blob斑点匹配以及blob里面的形态学调整 Sobel 是一种在数字图像处理和计算机视觉领域广泛应用的算法,主要用于边缘检测 脚本展示 #region namespace imports using System; using System.Collections; using System.Drawing; …...
解析 2025 工业边缘计算:三大技术风向的影响力
工业数字化转型的加速,工业边缘计算市场正呈现出蓬勃发展的态势。展望 2025 年,以下三大技术将成为引领工业边缘计算发展的重要风向标。 其一,人工智能与边缘计算的深度融合。人工智能技术将更广泛地应用于工业边缘设备,实现更智…...
企语企业管理系iFair(F23.2_a0)在Debian操作系统中的安装
起因:在安装了F24.8版本后,发现生产用环境和测试、开发用环境还是分开的好。 旧版的用来实验、测试,新版的一步一步小心的配置、使用是比较稳妥的操作。因此,决定在KVM虚拟机上搭建一个F23.2版本的企语系统。 一、 存在的问题 而…...
如何在Flask中处理静态文件
哈喽,大家好,我是木头左! 本文将详细介绍如何在Flask中处理静态文件,包括如何配置静态文件夹、如何访问静态文件以及如何处理静态文件的缓存问题。 配置静态文件夹 在Flask中,你可以通过static_folder参数来指定静态文件夹。默认情况下,Flask会在项目的根目录下寻找名为…...
无人机飞行试验大纲
无人机飞行试验大纲 编制日期:2025年02月11日 一、试验目的与背景 本次无人机飞行试验旨在验证无人机的飞行性能、控制系统稳定性、机体结构强度以及各项任务执行能力。随着无人机技术在各个领域的广泛应用,对其性能进行全面、系统的测试显得…...
C语言初阶牛客网刷题——JZ65 不用加减乘除做加法】【难度:简单】
1. 题目描述 牛客网OJ题链接 写一个函数,求两个整数之和,要求在函数体内不得使用、-、*、/四则运算符号。 2. 分析 十进制相加思想: 157 , 先计算不考虑进位的相加结果 12 (因为 57 的不考虑进位的结果是 2 &#x…...
git 记录
git 记录 报错warning: unknown value given to http.version: 2 报错 warning: unknown value given to http.version: ‘2’ 删除指定http版本 git config --global --unset http.version...
PyTorch Lightning Trainer介绍
PyTorch Lightning 的 Trainer 是框架的核心类,负责自动化训练流程、分布式训练、日志记录、模型保存等复杂操作。通过配置参数即可快速实现高效训练,无需手动编写循环代码。以下是详细介绍和使用示例: Trainer 的核心功能 自动化训练循环 自…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
