You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单体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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 11:55:23