14.7 自动模块
你可能会觉得HttpReader的实现过于底层,希望使用其他的库,譬如Apache项目的httpclient来替换这段逻辑。怎样才能把这个库导入到你的项目中呢?还记得之前学过的requires子句吧?你可以把它加到expenses.readers项目的module-info.java中,指定需要的第三方库。再次运行mvn clean package,看看会发生什么?非常不幸,结果并不是很理想,它抛出了下面的错误:
[ERROR] module not found: httpclient
碰到这个错误的原因是你没有更新你的pom.xml,明确声明对应的依赖。Maven的编译器插件在编译使用了module-info.java的项目时会去下载对应的JAR,并将所有的依赖添加到模块路径上,从而确保在项目中能识别对应的对象,如下所示:
<dependencies><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.3</version></dependency></dependencies>
现在你执行mvn clean package构建项目,结果就正确了。不过,你注意到一些有趣的事情了吗?httpclient库并不是一个Java模块啊。它是你希望以模块方式使用的一个第三方库,可是并没有被“模块化”过。这就是我们想特别介绍的部分,Java会将对应的JAR包转换为所谓的“自动模块”。模块路径上不带module-info.java文件的JAR都会被转换为自动模块。自动模块默认导出其所有的包。自动模块的名字会依据JAR的名字自动创建。不过你也可以通过几种途径修改它的名字,其中最简单的方式是使用jar工具提供的--describe-module参数,如下所示:
jar --file=./expenses.readers/target/dependency/httpclient-4.5.3.jar \--describe-modulehttpclient@4.5.3 automatic
这个例子中,你把模块名改成了httpclient。
最后一步,将JAR文件httpclient添加到模块路径上,运行这个应用:
java --module-path \./expenses.application/target/expenses.application-1.0.jar:\./expenses.readers/target/expenses.readers-1.0.jar \./expenses.readers/target/dependency/httpclient-4.5.3.jar \--module \expenses.application/com.example.expenses.application.ExpensesApplication
注意 如果你使用Maven,有个名叫
moditect的项目对Java 9的模块系统提供了更好的支持,譬如,它可以自动帮助用户生成module-info文件。
