无需编辑Jar包,如何将LITIEngine作为Java自动模块使用?
我正好遇到过类似的第三方库module-info配置错误的情况,针对你这个场景,有两种优雅的自动化方案,不用每次手动修改Jar包,就能让JPMS把LITIEngine当作自动模块处理。
方案一:使用ModiTect插件移除错误的module-info
ModiTect是专门用于处理Java模块的Maven插件,可以轻松修改或移除Jar中的module-info。在你的pom.xml中添加以下配置:
<build> <plugins> <!-- 移除LITIEngine Jar中的错误module-info --> <plugin> <groupId>org.moditect</groupId> <artifactId>moditect-maven-plugin</artifactId> <version>1.0.0.Final</version> <executions> <execution> <id>clean-litiengine-module-info</id> <phase>process-resources</phase> <goals> <goal>modify-module</goal> </goals> <configuration> <modules> <module> <artifact> <groupId>de.gurkenlabs</groupId> <artifactId>litiengine</artifactId> <version>0.4.18</version> </artifact> <transformations> <transformation> <!-- 直接移除Jar中的错误module-info.class --> <removeModuleInfo/> </transformation> </transformations> </module> </modules> <!-- 修改后的Jar输出目录 --> <outputDirectory>${project.build.directory}/processed-modules</outputDirectory> </configuration> </execution> </executions> </plugin> <!-- 配置编译插件,让它使用处理后的Jar作为模块路径 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <source>13</source> <target>13</target> <compilerArgs> <arg>--module-path</arg> <!-- 把处理后的模块目录和原依赖路径合并 --> <arg>${project.build.directory}/processed-modules:${maven.dependency.classpath}</arg> </compilerArgs> </configuration> </plugin> </plugins> </build>
配置完成后,执行mvn compile时,ModiTect会自动下载LITIEngine的Jar,移除其中错误的module-info.class,然后编译器会把这个修改后的Jar识别为自动模块litiengine,此时你的module-info.java中require litiengine;就能正常工作了。
方案二:使用maven-dependency-plugin解压并移除module-info
如果你不想引入新的插件,也可以用Maven自带的依赖插件来实现:
<build> <plugins> <!-- 解压LITIEngine Jar并排除错误的module-info --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.6.0</version> <executions> <execution> <id>unpack-litiengine</id> <phase>process-resources</phase> <goals> <goal>unpack</goal> </goals> <configuration> <artifactItems> <artifactItem> <groupId>de.gurkenlabs</groupId> <artifactId>litiengine</artifactId> <version>0.4.18</version> <outputDirectory>${project.build.directory}/unpacked-litiengine</outputDirectory> <!-- 排除错误的module-info.class --> <excludes>module-info.class</excludes> </artifactItem> </artifactItems> </configuration> </execution> <!-- 把解压后的内容重新打包成Jar --> <execution> <id>repackage-litiengine</id> <phase>process-resources</phase> <goals> <goal>build-classpath</goal> </goals> <configuration> <outputFile>${project.build.directory}/modified-jars/litiengine-0.4.18.jar</outputFile> <prefix>${project.build.directory}/unpacked-litiengine</prefix> </configuration> </execution> </executions> </plugin> <!-- 配置编译插件使用修改后的Jar --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <source>13</source> <target>13</target> <compilerArgs> <arg>--module-path</arg> <arg>${project.build.directory}/modified-jars:${maven.dependency.classpath}</arg> </compilerArgs> </configuration> </plugin> </plugins> </build>
这个方案先解压Jar并排除错误的module-info,再重新打包成新的Jar,效果和方案一一致,只是步骤稍多。
为什么会出现这个问题?
你遇到的核心问题是:LITIEngine 0.4.18的Jar中错误地包含了一个声明为java.xml.bind的module-info.class,而java.xml.bind是Java的系统模块。当JPMS在module-path上发现这个Jar时,会把它当作系统模块java.xml.bind的补丁,而不是自动模块litiengine,这就导致你无法在自己的模块中声明requires litiengine,还会出现模块引用冲突。
通过移除这个错误的module-info.class,JPMS就会把这个Jar识别为自动模块(自动模块名就是Jar文件名去掉版本号,也就是litiengine),这样你的模块化项目就能正常引用它了。
内容的提问来源于stack exchange,提问作者DynamicField

