当您的应用程序超出了十几行代码时,您可能应该将代码分成多个类。在这一点上,问题是如何分配它们。在Java中,经典格式是Java ARchive,也称为JAR。但是实际应用程序可能依赖于其他JAR。
这篇文章旨在描述创建独立的可执行JAR(也称为uber-JAR或胖JAR)的方法。
什么是可执行JAR?
JAR只是类文件的集合。为了可执行,其META-INF/MANIFEST.MF文件应指向实现该main()方法的类。您可以使用Main-Class属性来执行此操作。这是一个例子:
MainClass有一种static main(String... args)方法
MainClass
static main(String... args)
处理类路径
大多数应用程序依赖现有代码。Java提供了classpath的概念。类路径是运行时将查找以查找依赖代码的路径元素的列表。当运行Java类,定义通过类路径中-cp的命令行选项:
Java运行时通过聚合来自所有引用的JAR的所有类并添加主类来创建类路径。
分发依赖于其他JAR的JAR时会出现新的问题:
Class-Path
因此,您需要根据清单将JAR放在目标文件系统上的相对或绝对位置。这意味着要打开JAR并先阅读清单。 解决这些问题的一种方法是创建一个唯一的部署单元,其中包含来自所有JAR的类,并且可以作为一个工件进行分发。有几种创建此类JAR的选项:
Assembly插件
Apache Assembly插件
Maven的Assembly Plugin使开发人员能够将项目输出组合到一个可分发的存档中,该存档还包含依赖项,模块,站点文档和其他文件。
一个Maven设计规则是每个项目创建一个工件。有一些例外情况,例如Javadocs工件和源工件,但是通常,如果要多个工件,则需要为每个工件创建一个项目。Assembly插件背后的想法是解决此规则。
Assembly插件依赖于特定的assembly.xml配置文件。它允许您选择要包含在工件中的文件。请注意,最终的工件不必是JAR:配置文件可让您在可用格式(例如zip,war等)之间进行选择。
该插件通过提供预定义的程序集来管理常见的用例。自包含的JAR的分布就在其中。配置如下所示:
single
package
运行mvn package产生两个工件:
mvn package
<name>-<version>.jar
<name>-<version>-with-dependencies.jar
第一个JAR的内容与没有该插件时创建的内容相同。第二个是独立的JAR。您可以像这样执行它:
根据项目的不同,它可能会成功执行...。例如,它在示例Spring Boot项目中失败,并显示以下消息:
原因是不同的JAR在同一路径下 提供不同的资源,例如 META-INF/spring.factories。该插件遵循最后写入胜出策略。订单基于JAR的名称。
使用Assembly,您可以排除资源,但不能合并它们。当您需要合并资源时,您可能需要使用Apache Shade插件。
Apache Shade插件
Assembly插件是通用的;Shade插件仅专注于创建独立的JAR的任务。
该插件提供了将工件打包(包括其依赖项)并遮蔽(即重命名)某些依赖项的包的功能。
该插件基于转换器的概念:每个转换器负责处理一种类型的资源。转换器可以按原样复制资源,添加静态内容,将其与其他资源合并等。
虽然您可以开发一个转换器,但是该插件提供了一组现成的转换器:
ApacheLicenseResourceTransformer
ApacheNoticeResourceTransformer
NOTICE
AppendingTransformer
ComponentsXmlResourceTransformer
components.xml
DontIncludeResourceTransformer
GroovyResourceTransformer
IncludeResourceTransformer
ManifestResourceTransformer
MANIFEST
PluginXmlResourceTransformer
plugin.xml
ResourceBundleAppendingTransformer
ServicesResourceTransformer
META-INF/services
XmlAppendingTransformer
PropertiesTransformer
OpenWebBeansPropertiesTransformer
MicroprofileConfigTransformer
上面程序集的Shade插件配置如下:
XML格式
默认情况下,shade目标已绑定到package阶段 该转换器专用于生成清单文件 设置Main-Class条目 将最终的JAR配置为多发行版JAR。当任何初始JAR是多发行版JAR时,这都是必需的 运行mvn package产生两个工件:
<name>-<version>.jar:自包含的可执行文件JAR original-<name>-<version>.jar:没有嵌入式依赖项的“普通” JAR 对于示例项目,最终的可执行文件仍然无法按预期工作。确实,在构建过程中有很多关于重复资源的警告。其中两个阻止示例项目正常工作。为了正确地合并它们,我们需要看一下它们的格式:
original-<name>-<version>.jar
META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat
META-INF/spring.factories
此配置有效!仍然有剩余警告:
Spring Boot插件
Spring Boot插件采用了完全不同的方法。它不会单独合并来自JAR的资源。它增加了相关的JAR ,因为它们是尤伯杯JAR内。为了加载类和资源,它提供了一种特定的类加载机制。显然,它专用于Spring Boot项目。
配置Spring Boot插件很简单:
让我们检查一下最终JAR的结构:
这是我们的示例项目清单的摘录:
如您所见,主类是特定于Spring Boot的类,而“真实”主类在另一个条目下被引用。
有关JAR结构的更多信息,请查看参考文档。
结论 在这篇文章中,我们描述了三种创建独立的可执行JAR的方法:
组装非常适合简单的项目 当项目开始变得更加复杂并且您需要处理重复的文件时,请使用Shade 最后,对于Spring Boot项目,最好的选择是专用插件
原文链接:http://codingdict.com