在 Java 开发中,提到“Java Module 配置”通常有两种情况,你需要根据需求区分:
module-info.java 文件进行强封装和依赖管理。下面我为你分别提供这两种情况的配置指南。
module-info.java)如果你需要让项目具备强封装特性(例如限制别人访问你的内部类、明确依赖关系),你需要配置 JPMS。
module-info.java在源代码根目录(src/main/java/)下创建 module-info.java:
// src/main/java/module-info.java
module com.example.myapp { // 模块名,通常反向域名
// 1. 声明依赖的其他模块
requires java.base; // 基础模块(默认隐式包含,可省略)
requires com.example.mylib; // 依赖另一个自定义模块
requires transitive com.example.utils; // 传递依赖(别人依赖我时,自动获得此依赖)
// 2. 导出包:只有被 exports 的包,其他模块才能调用其中的 public 类
exports com.example.myapp.api;
// 3. 开放包:允许其他模块通过反射(Reflection)访问(Spring/Hibernate/Jackson 等框架必须)
opens com.example.myapp.entity;
// 4. 限定导出(仅对指定模块开放)
exports com.example.myapp.internal to com.example.test;
}
如果你的项目使用了 module-info.java,包结构需要清晰:
my-app
├── pom.xml (或 build.gradle)
└── src
└── main
└── java
├── module-info.java <-- 模块描述符(必须在根目录)
└── com
└── example
└── myapp
├── Main.java
└── api
└── UserService.java
只要你在 src/main/java 下加了 module-info.java,Maven 在 JDK 9+ 环境下会自动将其打包为模块化 JAR。你只需在 pom.xml 中确保 JDK 版本正确:
<properties>
<maven.compiler.release>17</maven.compiler.release>
</properties>
注意:如果你的依赖是老旧的 Jar 包(没有
module-info.java),Java 会将其视为“自动模块(Automatic Module)”,你需要用其自动推断出的模块名(通常是去掉横杠和版本的 Jar 名,如gson)在requires中声明。
# 编译(使用 --module-path 指定依赖模块路径)
javac -d out --module-path libs src/main/java/module-info.java src/main/java/com/example/myapp/*.java
# 打包
jar --create --file myapp.jar --main-class com.example.myapp.Main -C out .
# 运行(使用 -p 替代 -cp,即 module-path)
java -p . -m com.example.myapp/com.example.myapp.Main
如果你只是想把庞大的代码仓库按业务拆分成多个子工程(如 user-module, order-module),不需要 module-info.java,只需配置构建工具。
pom.xml)父工程的打包方式必须是 pom,并声明包含的子模块:
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging> <!-- 核心:必须是 pom -->
<modules>
<module>user-module</module>
<module>order-module</module>
</modules>
user-module/pom.xml)子模块通过 <parent> 标签继承父工程:
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>user-module</artifactId> <!-- 子模块自己的 ID -->
如果 order-module 需要调用 user-module 的代码,只需像普通依赖一样引入:
<!-- order-module 的 pom.xml -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>user-module</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
exports 导致无法访问:即使你的类是 public 的,如果没有在 module-info.java 中用 exports 导出该包,其他模块连编译都通不过。InaccessibleObjectException):如果使用了 Spring Boot、Hibernate 等框架,它们通过反射修改私有字段。你必须在 module-info.java 中用 opens 把对应的实体类包开放出去。com.example.util)绝对不能出现在两个不同的模块/Jar 中,JPMS 严禁分包。module-info.java),建议纯用模块路径(-p)运行。如果强行用传统 -cp 运行,模块系统会被忽略,退化为普通的类路径模式。如果你是在 IntelliJ IDEA 中操作:
src/main/java 右键 New -> module-info.java,IDEA 会自动提示你补全 requires 和 exports。Maven 并勾选 Create from archetype 或手动建 modules 即可,IDEA 会自动识别父子关系。免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。