当前位置: 首页 > news >正文

2.5 模块化迁移策略:从传统项目到模块化系统


模块化迁移策略:从传统项目到模块化系统

将传统 Java 项目迁移至 JDK 9 模块化系统是一项系统性工程,需分阶段实施以降低风险。以下是详细的迁移策略、工具使用和实战示例。


1. 迁移阶段划分
阶段目标关键操作
阶段1:兼容性验证确保项目能在 JDK 9 上无模块化运行使用类路径运行,处理废弃 API 和依赖冲突
阶段2:模块化试点部分代码转为模块,依赖自动模块(非模块化 JAR)创建 module-info.java,逐步迁移核心模块
阶段3:完整模块化全项目模块化,显式管理所有依赖重构模块结构,移除自动模块依赖

2. 阶段1:兼容性验证
目标

在不修改代码的情况下,验证项目在 JDK 9 上的运行能力。

关键步骤
  1. 编译与运行测试

    javac -d out -classpath lib/*.jar src/**/*.java  
    java -classpath out:lib/*.jar com.example.Main  
    
  2. 处理兼容性问题

    • 废弃 API 检测
      jdeprscan --release 9 myapp.jar  
      
    • 内部 API 访问
      • 错误示例sun.misc.BASE64Encoder 不可访问。
      • 修复方案:替换为标准 API(java.util.Base64)。
  3. 依赖冲突排查

    • 工具:使用 jdeps 分析依赖树:
      jdeps --class-path lib/*.jar -recursive myapp.jar  
      

3. 阶段2:模块化试点
目标

将部分代码转换为模块,依赖未模块化的第三方库作为自动模块。

关键步骤
  1. 创建初始模块

    • 选择核心模块(如 com.utils),添加 module-info.java
      module com.utils {  exports com.utils;  requires transitive org.apache.commons.lang3; // 自动模块名:commons.lang3  
      }  
      
  2. 模块化编译与运行

    javac -d out --module-source-path src --module com.utils  
    java --module-path out:lib -m com.utils/com.example.Main  
    
  3. 处理自动模块依赖

    • 自动模块命名规则
      • JAR 文件名 log4j-api-2.17.1.jar → 模块名 log4j.api
    • 依赖传递:自动模块默认依赖所有模块,但需显式声明核心 JDK 模块。

4. 阶段3:完整模块化
目标

全项目模块化,显式管理所有依赖(包括第三方库)。

关键步骤
  1. 重构模块结构

    • 模块拆分:按功能拆分模块(如 com.usercom.order)。
    • 模块描述符:为每个模块编写 module-info.java
  2. 处理第三方库

    • 方案1:等待库官方提供模块化版本(如 Log4j 2.17+)。
    • 方案2:手动为库添加模块描述符(生成 module-info.java)。
  3. 显式依赖管理

    module com.myapp {  requires java.sql;  requires com.utils;  requires org.apache.logging.log4j; // 显式声明 Log4j 模块  
    }  
    
  4. 生成定制化 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生成最小化 JREjlink --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.jarmylib.jar)以生成唯一模块名。
性能下降检查垃圾回收配置(如 -XX:+UseG1GC),优化模块依赖减少加载时间。

7. 迁移最佳实践
  1. 分阶段实施
    • 先迁移底层工具模块,再逐步向上层业务模块推进。
  2. 自动化测试
    • 在每个阶段运行单元测试和集成测试(如 JUnit + CI/CD)。
  3. 依赖管理
    • 优先选择已适配 JDK 9 的第三方库(如 Spring 5、Hibernate 5.3+)。
  4. 文档与协作
    • 维护模块依赖图和迁移日志,与团队共享知识。

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 模块化迁移策略:从传统项目到模块化系统

模块化迁移策略&#xff1a;从传统项目到模块化系统 将传统 Java 项目迁移至 JDK 9 模块化系统是一项系统性工程&#xff0c;需分阶段实施以降低风险。以下是详细的迁移策略、工具使用和实战示例。 1. 迁移阶段划分 阶段目标关键操作阶段1&#xff1a;兼容性验证确保项目能在…...

java商城解决方案

数字化时代&#xff0c;电子商务已成为企业拓展市场的重要渠道。对于想要建立在线商店的企业来说&#xff0c;选择正确的技术堆栈至关重要。 Java作为一种成熟且广泛使用的编程语言&#xff0c;为构建购物中心提供了强大的功能和灵活性。 商城Java源码&#xff1a;商城开发的核…...

算法-哈希表篇05-四数相加II

四数相加II 力扣题目链接 题目描述 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l < n nums1[i] nums2[j] nums3[k] nums4[l] 0 解题思路 把数…...

WPS或word接入智能AI

DeepSeek接入WPS 配置WPS &#xff08;1&#xff09;下载 OfficeAl助手插件: 插件下载地址:https://www.office-ai.cn/。 安装插件后&#xff0c;打开WPS&#xff0c;菜单栏会新增"OfficeAl助手”选项卡。 如果没有出现&#xff0c; 左上找到文件菜单 -> 选项 ,在…...

Leetcode:学习记录

一、滑动窗口 1. 找出数组中元素和大于给定值的子数组的最小长度 右指针从左到右遍历&#xff0c;在每个右指针下&#xff0c;如果去掉左边元素的元素和大于等于给定值则左指针右移一次&#xff0c;直到小于给定值&#xff0c;右指针右移一个。 2.找到乘积小于给定值的子数组…...

86.在 Vue 3 中使用 OpenLayers 自定义组件(放大、缩小、长度测量、面积测量)

摘要 在 WebGIS 开发中&#xff0c;OpenLayers 是一个非常强大的开源地图库&#xff0c;它可以在 Web 应用中渲染高效的地图。本篇文章将介绍如何在 Vue 3 中使用 OpenLayers&#xff0c;并封装一个自定义地图控件组件&#xff0c;实现地图的放大、缩小、长度测量和面积测量功能…...

http 与 https 的区别?

HTTP(超文本传输协议)和 HTTPS(安全超文本传输协议)是互联网通信的基础协议。随着网络技术的发展和安全需求的提升,HTTPS变得越来越重要。本文将深入探讨HTTP与HTTPS之间的区别,包括其工作原理、安全性、性能、应用场景及未来发展等。 1. HTTP与HTTPS的基本概念 1.1 HT…...

SAIL-RK3576单板运行7b的deepseek对话模型

大概流程&#xff1a; 使用ollama工具进行deepseek的模型部署和使用&#xff0c;先安装ollama工具&#xff0c;在使用ollama工具拉去deepseek模型&#xff0c;最后使用ollama工具加载deepseek模型进行对话...

独立C++ asio库实现的UDP Server

以下是一个使用独立的 C Asio 库实现的 UDP 服务器的示例代码。这个 UDP 服务器可以监听指定端口&#xff0c;接收客户端发送的数据&#xff0c;并将接收到的数据原样返回给客户端。 #include <iostream> #include <asio.hpp> #include <array>class UdpSer…...

SQL Server STUFF 函数的用法及应用场景

在 SQL Server 中&#xff0c;STUFF 函数是一种强大的字符串处理工具&#xff0c;常用于删除指定位置的字符并插入新的字符。通过这个函数&#xff0c;开发者能够灵活地修改字符串&#xff0c;从而在数据处理、字符串拼接和格式化等方面大显身手。本文将深入探讨 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 页&#xff0c;针对图 3-4-3&#xff0c;提出了一个问题&#xff1a;“点 A A A 到 W \mathbb{W} W 上的一个点的距离有无穷多个。现在&#xff0c;我们最关心的是其中最短的那个&#xff0c;怎么找&#xff1f;请参阅 3.6 节。”并且&#xff0c;在…...

VisionPro 划痕检测小练习

划痕检测,我这里用到的是Sobel算子和blob斑点匹配以及blob里面的形态学调整 Sobel 是一种在数字图像处理和计算机视觉领域广泛应用的算法&#xff0c;主要用于边缘检测 脚本展示 #region namespace imports using System; using System.Collections; using System.Drawing; …...

解析 2025 工业边缘计算:三大技术风向的影响力

工业数字化转型的加速&#xff0c;工业边缘计算市场正呈现出蓬勃发展的态势。展望 2025 年&#xff0c;以下三大技术将成为引领工业边缘计算发展的重要风向标。 其一&#xff0c;人工智能与边缘计算的深度融合。人工智能技术将更广泛地应用于工业边缘设备&#xff0c;实现更智…...

企语企业管理系iFair(F23.2_a0)在Debian操作系统中的安装

起因&#xff1a;在安装了F24.8版本后&#xff0c;发现生产用环境和测试、开发用环境还是分开的好。 旧版的用来实验、测试&#xff0c;新版的一步一步小心的配置、使用是比较稳妥的操作。因此&#xff0c;决定在KVM虚拟机上搭建一个F23.2版本的企语系统。 一、 存在的问题 而…...

如何在Flask中处理静态文件

哈喽,大家好,我是木头左! 本文将详细介绍如何在Flask中处理静态文件,包括如何配置静态文件夹、如何访问静态文件以及如何处理静态文件的缓存问题。 配置静态文件夹 在Flask中,你可以通过static_folder参数来指定静态文件夹。默认情况下,Flask会在项目的根目录下寻找名为…...

无人机飞行试验大纲

‌无人机飞行试验大纲‌ ‌编制日期‌&#xff1a;2025年02月11日 ‌一、试验目的与背景‌ 本次无人机飞行试验旨在验证无人机的飞行性能、控制系统稳定性、机体结构强度以及各项任务执行能力。随着无人机技术在各个领域的广泛应用&#xff0c;对其性能进行全面、系统的测试显得…...

C语言初阶牛客网刷题——JZ65 不用加减乘除做加法】【难度:简单】

1. 题目描述 牛客网OJ题链接 写一个函数&#xff0c;求两个整数之和&#xff0c;要求在函数体内不得使用、-、*、/四则运算符号。 2. 分析 十进制相加思想&#xff1a; 157 &#xff0c; 先计算不考虑进位的相加结果 12 &#xff08;因为 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 是框架的核心类&#xff0c;负责自动化训练流程、分布式训练、日志记录、模型保存等复杂操作。通过配置参数即可快速实现高效训练&#xff0c;无需手动编写循环代码。以下是详细介绍和使用示例&#xff1a; Trainer 的核心功能 自动化训练循环 自…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

DAY 45 超大力王爱学Python

来自超大力王的友情提示&#xff1a;在用tensordoard的时候一定一定要用绝对位置&#xff0c;例如&#xff1a;tensorboard --logdir"D:\代码\archive (1)\runs\cifar10_mlp_experiment_2" 不然读取不了数据 知识点回顾&#xff1a; tensorboard的发展历史和原理tens…...