首先,您需要不同的编译器。向后兼容性存在限制。据我所知,Oracle JDK 支持当前的减两个主要版本。因此 JDK 11 javac 可以编译 JDK 8 incl。因此,我假设第一个 sn-p 类似于:
<properties>
<java.version>11</java.version>
</properties>
这个设置在每个(简单的)pom.xml 中只能出现一次,因为它会影响maven-compiler-plugin 设置源和目标。我再次假设您有一个包含 JDK 6 代码的源目录和另一个包含 JDK 11 代码的源目录。您的目标是以兼容的方式将所有 JDK 6 源代码绑定到一个 EAR。同时,您的 JDK 11 源代码最终位于不同的 EAR 中,并且必须类似于 JDK 11 字节码。
为 JDK 8 目标编译 JDK 11 源代码是完全不同的——仍然与 JDK 6 VM 不兼容。我还假设仅通过编译器将您的 JDK 11 源代码转换为 JDK 6 字节码既不需要也不容易。
接下来,我假设您在两个 EAR 的类路径中至少有一个共享元素。它可以是您自己的 API JAR 或外部库。这种依赖最终会出现在所谓的父 pom 的dependencyManagement 中。这是包含所有模块定义的同一个 pom。
第三,您需要定义一个 groupId 和各种 artifactId。我强烈建议您至少在 artifactId 中表达 JDK 亲和力。然后,您可以根据 JDK 亲和性来表达依赖关系。骨架(父)pom.xml 可能如下所示:
<project>
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release</artifactId>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>sample-cross-release-api</module>
<module>sample-cross-release-source6</module>
<module>sample-cross-release-source11</module>
<module>sample-cross-release-war6</module>
<module>sample-cross-release-war11</module>
<module>sample-cross-release-ear6</module>
<module>sample-cross-release-ear11</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency><!-- necessary for 6 and 11 source/ WAR/ EAR -->
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-api</artifactId>
<version>${project.version}</version>
<dependency>
<dependency><!-- only 6 is shown, 11 looks the similar -->
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-sources6</artifactId>
<version>${project.version}</version>
<dependency>
<dependency><!-- only 6 is shown, 11 looks the similar -->
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-war6</artifactId>
<version>${project.version}</version>
<dependency>
</dependencies>
</dependencyManagement>
</project>
我省略了源代码和 WAR 部分。但它在sample-cross-release-sources6 上有一个dependency 和-api。 EAR 的 pom.xml 看起来像这样:
<project>
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-ear11</artifactId>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency><!-- does not need version, determined by parent -->
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-api</artifactId>
<dependency>
<dependency><!-- does not need version, determined by parent -->
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-war6</artifactId>
<dependency>
<!-- other dependencies, like logging, persistence... -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compile.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
项目结构在文件系统中将如下所示:
|
+-- pom.xml (parent)
+-- sample-cross-release-api
| +-- pom.xml
| +-- src/main/java
| +-- src/main/resources
| ...
...
+-- sample-cross-release-ear11
+-- pom.xml
...
最后,我敦促您拥有完全独立的 JDK 6 和 JDK 11 代码库/projects/pom.xml-s。不要将它们与父 pom 合并。一旦您尝试设置(Maven-)配置文件以支持不同 JDK/工具链的发布插件,您最终将陷入依赖地狱。它可能适用于简单的情况。一旦你引入静态代码分析、万无一失/故障安全以及大概是 WAR 和 EAR 创建,它就会崩溃。 (我假设 JDK 6 EAR 是使用与 JDK 11 的 JEE 不同的匹配 JEE 依赖项构建的。这反过来又强制使用兼容的 Maven 插件——每个 JDK 都不同。)
而且您永远不会知道:在 JDK 11 上运行的应用程序服务器会禁止第三方库中的反射访问,该第三方库以某种方式最终出现在您 11 的 EAR 类路径中。从一开始就谨慎行事,将不同的 JDK 拆开并仔细检查两次。
为了简洁,我省略了:
- 传递依赖/写 pom 的好风格
-
maven-enforcer-plugin 拥有可重复的构建
- WAR- 和 EAR-Maven-plugins 的使用,因为它们在 JDK-6 和 -11 版本之间在如何设置类路径方面存在显着差异
- 使用toolchains,所以所有开发者都有一个共同的平台,可以传播到构建节点
- 关于 jdeps 的建议,部分原因是 Maven 插件,部分原因是对多版本 jAR 的处理(这将与 JDK 11 依赖项一起显示)
- 允许命令行开关改变构建行为的 Maven 配置文件
- 通过 Maven 发布,引入基于 JDK、Maven 和您的 SCM 的有趣怪癖。
- 静态代码分析,PMD 是在此设置中运行的最灵活之一,即使两个 JDK 具有相同的规则集,而其他 JDK 可能没有或至少不容易(Coverity、Sonarqube、CAST 等)
- 安全检查,org.owasp:dependency-check-maven 会在 JDK 6 分支中触发很多警告,一些库不再针对这个目标 JDK 发展
通常一个父 pom 包含很多 dependencyManagement 和 pluginManagement 所以所有模块 pom 可以省略版本和详细配置。您的方法与此相反,强制 JDK 6 分支和 JDK 11 分支通过同一个父级。它总是从父级强制到模块上,后者不能改变或挑选。
如果从 Ant 切换到 Maven 没有真正的权衡,请不要这样做。 Maven 需要很多合同,尤其是。当涉及到文件系统布局与工件内容时——要构建 WAR/EAR,您要么需要遵守规则,要么需要大量的插件配置。