在这个简短的教程中,我想向你展示如何配置新的Java 9启用的Maven项目。
TL; DR
您可以在这里找到一个示例项目:https//github.com/springuni/springuni-java9。
模块
我们以前也可以在Maven(也有Gradle,Ant等)中创建了多个模块项目,但是它们并不是严格的模块。他们似乎是独立的代码库,没有一个标准的方法来定义这些模块提供和需要的功能。使用构建系统,您可以声明依赖关系,但是模块本身并不负责管理自己的依赖关系并提供服务。
在大型项目中,当多个版本的同一个库被拉入作为传递依赖关系的副作用时,开发人员很快就会遇到jar-hell。
Java 9的变化如何减轻这一点,您现在可以正式声明module-info.java封装以下信息的模块。
- 模块名称
- 该模块依赖的其他模块
- 该模块提供了其他模块
许多知名的库(library )预计将迁移到Java 9的模块系统,因此他们可以共享其公共API并使用此机制来隐藏其内部。
但有一点值得注意的是,如果您将来需要使用这样的库(library),那么您将要做什么呢?这是一个合理的问题,这里就是模块类型。
模块类型
模块只是以前的简单的旧JAR文件,但是从Java 9开始,它们将包含一个我上面提到的一个特殊的module-info.java。还有一个称为模块路径的新概念,它是众所周知的类路径的兄弟。
说到这里有四种模块类型:
- 命名的模块(也称为应用程序模块)包含上述module-info.java
- 平台模块(类似于前者,但这些都是随JDK一起发货)
- 自动模块是在模块路径上提供的那些旧JAR
- 未命名的模块是标准类路径上列出的所有内容
对Maven用户的影响
像Maven这样的构建工具必须要处理JDK的新结构,也就是module-info.java模块路径。他们有一个Wiki页面,其中列出了Java 9的所有插件要求。
编译器插件
为了能够使用JDK 9的模块系统maven-compiler-plugin版本3.6.1或更高版本是必需的。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
工具链插件
这或多或少是可选的,但是我强烈建议您使用它。Java 9尚未发布,我们仍在使用Java 8(或Java 7)进行生产项目,并且不舒服地更改所有的环境变量,并将其指向JDK 9的主目录,我们一直想要实验它。 maven-toolchains-plugin使您能够轻松地使用各种环境。
创建$HOME/.m2/toolchains.xml(或 %USERPROFILE%\.m2\toolchains.xml在Windows上),如果你还没有的话。
<toolchains>
<toolchain>
<type>jdk</type>
<provides>
<version>9</version>
<vendor>oracle</vendor>
</provides>
<configuration>
<!-- Change path to JDK9 -->
<jdkHome>/opt/oracle/jdk-9</jdkHome>
</configuration>
</toolchain>
<toolchain>
<type>jdk</type>
<provides>
<version>1.8</version>
<vendor>oracle</vendor>
</provides>
<configuration>
<jdkHome>/opt/oracle/jdk-1.8.0.65</jdkHome>
</configuration>
</toolchain>
</toolchains>
将路径更改为实际的JDK安装。之后,工具链插件可以添加到您的项目中。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-toolchains-plugin</artifactId>
<version>1.1</version>
<configuration>
<toolchains>
<jdk>
<version>9</version>
<vendor>oracle</vendor>
</jdk>
</toolchains>
</configuration>
<executions>
<execution>
<goals>
<goal>toolchain</goal>
</goals>
</execution>
</executions>
</plugin>
启用Java 9语言支持
从JDK 9 b72开始,有个新功能将成为可用:javac –release命令行选项。简而言之,要使用javac交叉编译到较旧版本的平台,将设置-source和-target选项设置为较旧的值是不够的; 在bootclasspath也必须设置对应于旧版本了。设置bootclasspath经常被遗忘并获取所需的信息可能不方便。
该–release标志着javac解决了这两个缺点。在交叉编译时仅需要设置单个标志,相比以前需要设置三个标志(source,-target,-bootclasspath)和这样所需要的信息都被包括在JDK。接受的参数值为–release6,7,8和9。
<properties>
<maven.compiler.release>9</maven.compiler.release>
<maven.compiler.source>1.9</maven.compiler.source>
<maven.compiler.target>1.9</maven.compiler.target>
...
</properties>
属性 maven.compiler.release直接映射到该–release标志javac,而另外两个属性只对IntelliJ有必要 ,用来了解源码兼容性。
已知的问题
不幸的是,在写作时有测试编译失败。这是由于JDK-8178012引入的一个突破性的改变 ,它删除了-Xmodule编译器标志。希望MCOMPILER-294可以很快得到修复,但同时也可以禁用编译测试源。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<!--
Fix breaking change introduced by JDK-8178012: Finish removal of -Xmodule Reference: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8178012 -->
<executions>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
<configuration>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>