单体Spring Tomcat项目引入Java 9模块的方案咨询
解决方案:混合显式模块与未命名模块的编译配置
你的核心问题是Java模块系统默认不允许显式模块(v2、v2-util)读取未命名模块(src/main/java下的遗留代码)——这是模块系统的设计规则:显式模块只能依赖其他显式声明的模块,而未命名模块不属于任何模块范畴。要实现你的需求,需要通过编译器参数打破这个限制,同时保留新模块之间的模块化隔离。
1. 调整Maven编译配置,允许显式模块读取未命名模块
在pom.xml的maven-compiler-plugin中添加编译参数,让v2模块能够读取未命名模块(用ALL-UNNAMED指代所有未命名模块的内容):
<build> <plugins> <!-- 保留已有的build-helper配置,添加v2和v2-util源码目录 --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>3.4.0</version> <executions> <execution> <id>add-source</id> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources> <source>src/main/v2</source> <source>src/main/v2-util</source> </sources> </configuration> </execution> </executions> </plugin> <!-- 配置编译器参数,允许v2模块读取未命名模块 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <release>17</release> <!-- 替换为你的实际Java版本 --> <compilerArgs> <!-- 让v2模块读取未命名模块 --> <arg>--add-reads</arg> <arg>v2=ALL-UNNAMED</arg> <!-- 如果v2-util也需要访问遗留代码,取消下方注释 --> <!-- <arg>--add-reads</arg> --> <!-- <arg>v2.util=ALL-UNNAMED</arg> --> </compilerArgs> </configuration> </plugin> </plugins> </build>
2. 修正模块间的依赖声明
确保v2和v2-util的module-info.java配置符合你的隔离需求:
v2-util的module-info.java(仅暴露允许v2访问的包)
module v2.util { // 只向v2模块暴露工具包 exports com.mycompany.v2_util to v2; // 若工具类依赖第三方库,添加对应的requires声明 // requires spring.core; }
v2的module-info.java(依赖v2-util,通过编译参数访问遗留代码)
module v2 { // 声明依赖v2-util模块 requires v2.util; // 若v2依赖Spring等第三方库,添加对应的requires声明 // requires spring.context; }
3. 运行时适配(Tomcat部署)
打包war部署到Tomcat时,需要在JVM启动参数中添加允许v2模块读取未命名模块的配置:
--add-reads v2=ALL-UNNAMED
- Linux/macOS:修改
catalina.sh中的JAVA_OPTS - Windows:修改
catalina.bat中的JAVA_OPTS
4. 逐步重构建议
- 当前配置是临时兼容方案,核心是让新模块能正常访问遗留代码,同时保持新模块间的模块化隔离。
- 后续可逐步将遗留代码迁移到新的显式模块中,或给遗留代码所在jar添加
Automatic-Module-Name属性(拆分Maven模块时),最终完全过渡到模块化架构。 - 尽量避免让v2-util直接依赖未命名模块,以v2作为遗留代码与新模块的中间层,降低后续重构复杂度。
内容的提问来源于stack exchange,提问作者Rich
相关产品推荐
相关产品推荐

