我对 Maven 不是很有经验,在尝试多模块项目时,我开始想知道如何为父 Maven pom 中的所有子模块指定 Java 版本。直到今天我只使用:
<properties> <java.version>1.8</java.version> </properties>
…但是在研究时我发现您还可以在 Maven 编译器插件中指定 Java 版本,如下所示:
<plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins>
然后将其包装到插件管理标签中以启用子 poms 的使用。所以第一个问题是这样的:
在属性和 Maven 编译器插件中设置 Java 版本有什么区别?
我找不到明确的答案,但在研究过程中我发现您也可以通过这种方式指定 Java 版本:
<properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties>
…这表明即使我没有明确声明它也存在编译器插件。运行mvn package输出
mvn package
maven-compiler-plugin:3.1:compile (default-compile) @ testproj ---
…以及我没有声明的其他一些插件。
那么这些插件是 Maven pom 的默认隐藏部分吗? 在属性和 Maven 插件配置元素中设置源/目标之间有什么区别吗?
其他一些问题是 - 应该使用哪种方式(如果它们不相等,何时使用)?哪一个最适合多模块项目,如果 pom 中指定的 Java 版本与指定的版本不同会发生什么JAVA_HOME?
JAVA_HOME
如何指定JDK版本?
使用以下三种方式中的任何一种:(1) Spring Boot 功能,或使用 Maven 编译器插件与 (2) source&target或 (3) 与release.
source
target
release
<java.version>
1.8
如果您使用 Spring Boot,请随意使用它。
maven-compiler-plugin
maven.compiler.source
maven.compiler.target
那确实是:
相当于:
根据编译器插件的 Maven 文档, 因为编译器配置中的<source>和<target>元素使用属性maven.compiler.source以及maven.compiler.target是否已定义。
<source>
<target>
资源 Java 编译器的-source参数。 默认值为:1.6。 用户属性是:maven.compiler.source。 目标 Java 编译器的-target参数。 默认值为:1.6。 用户属性是:maven.compiler.target。
资源
Java 编译器的-source参数。 默认值为:1.6。 用户属性是:maven.compiler.source。
-source
1.6
目标
Java 编译器的-target参数。 默认值为:1.6。 用户属性是:maven.compiler.target。
-target
关于 和 的默认值source, target请注意, 自从3.8.0maven 编译器以来,默认值已从 更改1.5为1.6。
3.8.0
1.5
3.6
org.apache.maven.plugins maven-compiler-plugin 3.8.0 9
您也可以声明:
<properties> <maven.compiler.release>9</maven.compiler.release> </properties>
但此时它不会起作用,因为maven-compiler-plugin您使用的默认版本不依赖于足够新的版本。
Mavenrelease参数传达 release:我们可以从 Java 9 传递的新 JVM 标准选项:
针对特定 VM 版本的公共、受支持和记录的 API 进行编译。
source这种方式提供了一种为、target和bootstrapJVM 选项指定相同版本的标准方式。 请注意,指定bootstrap是交叉编译的好习惯,如果您不进行交叉编译也不会受到伤害。
bootstrap
指定 JDK 版本的最佳方法是什么?
<java.version>只有在使用 Spring Boot 时才允许使用第一种方式 ( )。
对于 Java 8 及以下版本:
关于其他两种方式:评估maven.compiler.source/maven.compiler.target属性 或 使用maven- compiler-plugin,您可以使用其中一种。它没有改变任何事实,因为最终这两种解决方案依赖于相同的属性和相同的机制:maven 核心编译器插件。
maven- compiler-plugin
好吧,如果您不需要在编译器插件中指定除 Java 版本之外的其他属性或行为,那么使用这种方式更有意义,因为这样更简洁:
从 Java 9 开始:
论点(第三release点)是一种强烈考虑是否要对源和目标使用相同版本的方法。
如果 JAVA_HOME 中的 JDK 与 pom.xml 中指定的版本不同,会发生什么情况?
如果 JDK 引用的 JDK 与 pom 中指定的版本兼容,这不是问题,JAVA_HOME但为了确保更好的交叉编译兼容性,请考虑添加JVM 选项,并将版本bootstrap的路径作为值。rt.jar``target
rt.jar``target
需要考虑的重要一点是 Maven 配置中的source和target版本不应优于JAVA_HOME. 较旧版本的 JDK 无法与较新版本一起编译,因为它不知道其规范。
如何处理JAVA_HOME引用的JDK与pom中指定的java目标和/或源版本不兼容的情况?
例如,如果您JAVA_HOME引用 JDK 1.7 并且您在 pom.xml 的编译器配置中指定 JDK 1.8 作为源和目标,这将是一个问题,因为如上所述,JDK 1.7 不知道如何编译. 从它的角度来看,它是一个未知的JDK版本,因为它是在它之后发布的。 在这种情况下,您应该配置 Maven 编译器插件以通过以下方式指定 JDK:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <compilerVersion>1.8</compilerVersion> <fork>true</fork> <executable>D:\jdk1.8\bin\javac</executable> </configuration> </plugin>
您可以在带有 maven compiler plugin 的示例中获得更多详细信息。
它没有被问到,但可能更复杂的情况是您指定源而不是目标。它可能会根据源版本在目标中使用不同的版本。规则是特别的:您可以在交叉编译选项部分阅读它们。
为什么编译器插件在执行 Mavenpackage目标时在输出中被跟踪,即使您没有在 pom.xml 中指定它?
package
为了编译你的代码并且更普遍地执行 Maven 目标所需的所有任务,Maven 需要工具。因此,它使用核心 Maven 插件(您可以通过其groupId:识别核心 Maven 插件org.apache.maven.plugins)来完成所需的任务:用于编译类的编译器插件,用于执行测试的测试插件等等......所以,即使你不声明这些插件,它们被绑定到 Maven 生命周期的执行。 在 Maven 项目的根目录中,您可以运行命令 :mvn help:effective-pom以有效使用最终的 pom。在其他信息中,您可以看到 Maven 附加的插件(在您的 pom.xml 中指定或未指定)、使用的版本、它们的配置以及生命周期每个阶段的执行目标。
groupId
org.apache.maven.plugins
mvn help:effective-pom
在mvn help:effective-pom命令的输出中,您可以在元素中看到这些核心插件的声明<build><plugins>,例如:
<build><plugins>
... <plugin> <artifactId>maven-clean-plugin</artifactId> <version>2.5</version> <executions> <execution> <id>default-clean</id> <phase>clean</phase> <goals> <goal>clean</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>2.6</version> <executions> <execution> <id>default-testResources</id> <phase>process-test-resources</phase> <goals> <goal>testResources</goal> </goals> </execution> <execution> <id>default-resources</id> <phase>process-resources</phase> <goals> <goal>resources</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <executions> <execution> <id>default-compile</id> <phase>compile</phase> <goals> <goal>compile</goal> </goals> </execution> <execution> <id>default-testCompile</id> <phase>test-compile</phase> <goals> <goal>testCompile</goal> </goals> </execution> </executions> </plugin> ...
您可以在 Maven 文档中的 Maven 生命周期介绍中获得有关它的更多信息。
不过,当您想将这些插件配置为其他值作为默认值时(例如,当您在 pom.xml 中声明 maven-compiler 插件以调整要使用的 JDK 版本时,您可以声明这些插件)或当您想要添加一些在 Maven 生命周期中默认不使用的插件执行。