使用 maven 构建一个胖罐子
Posted
技术标签:
【中文标题】使用 maven 构建一个胖罐子【英文标题】:Building a fat jar using maven 【发布时间】:2013-04-19 19:40:23 【问题描述】:我有一个要作为 jar 分发的代码库。它还依赖于外部 jar,我想将其捆绑在最终的 jar 中。
我听说这可以使用maven-assembly-plug-in
来完成,但我不明白怎么做。有人可以指点我一些例子。
现在,我正在使用 fat jar 来捆绑最终的 jar。我想用 maven 实现同样的目标。
【问题讨论】:
【参考方案1】:注意:如果你是spring-boot应用,请阅读答案末尾
将以下插件添加到您的pom.xml
最新版本可以found at
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>CHOOSE LATEST VERSION HERE</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
配置此插件后,运行 mvn package
将生成两个 jar:一个仅包含项目类,第二个包含所有依赖项的 fat jar,后缀为“-jar-with-dependencies”。
如果您想在运行时正确设置classpath
,那么还要添加以下插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
对于 Spring Boot 应用程序只使用以下插件(选择合适的版本)
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>$start-class</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
【讨论】:
这个插件的当前版本现在是 2.4 现在已弃用,应改用 maven-shade-plugin。见@phlogratos 答案:***.com/a/16222965/274350。 maven-assembly-plugin 可以最小化 fat jar 的大小吗? @Richard 你在哪里看到它被弃用了?我在这里找不到任何东西maven.apache.org/plugins/maven-assembly-plugin @user3833308 "deprecated" 可能是错误的词,但maven.apache.org/plugins/maven-assembly-plugin 的文档说“如果您的项目想要将您的工件打包在 uber-jar 中,则程序集插件仅提供基本支持。如需更多控制,请使用 Maven Shade 插件。”【参考方案2】:您可以使用maven-shade-plugin。
在您的构建中配置阴影插件后,命令mvn package
将创建一个包含所有依赖项合并到其中的单个 jar。
【讨论】:
现在这是正确的做法。 maven-assembly-plugin 文档指出:“如果您的项目想要将您的工件打包到 uber-jar 中,则程序集插件仅提供基本支持。要获得更多控制,请使用 Maven Shade 插件。” 但是我如何获取单个 .jar 并将其用于发布? 非常感谢!像魅力一样工作! 我不同意现在这是“正确”的做法。如果您只想要基本行为,那么您绝对可以继续使用程序集插件。 shade 插件会做一些高级的事情,比如重写字节码来修改依赖包的名称,一旦你开始使用生产代码,你就会引入额外的风险,如果你没有充分的理由,这是不值得的。【参考方案3】:也许你想要maven-shade-plugin
,捆绑依赖,最小化未使用的代码并隐藏外部依赖以避免冲突。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>true</createDependencyReducedPom>
<dependencyReducedPomLocation>
$java.io.tmpdir/dependency-reduced-pom.xml
</dependencyReducedPomLocation>
<relocations>
<relocation>
<pattern>com.acme.coyote</pattern>
<shadedPattern>hidden.coyote</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
参考资料:
http://maven.apache.org/plugins/maven-shade-plugin/plugin-info.html http://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html【讨论】:
如果遇到Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found
,删除<minimizeJar>true</minimizeJar>
即可。
如果您收到“java.lang.SecurityException: Invalid signature file digest for Manifest main attributes”异常,那么对上述配置部分的添加将有所帮助:***.com/a/6743609/38368【参考方案4】:
实际上,添加
<archive>
<manifest>
<addClasspath>true</addClasspath>
<packageName>com.some.pkg</packageName>
<mainClass>com.MainClass</mainClass>
</manifest>
</archive>
对 maven-jar-plugin 的声明不会为我将主类条目添加到清单文件中。 我必须将它添加到 maven-assembly-plugin 才能在清单中得到它
【讨论】:
【参考方案5】:您可以使用onejar-maven-plugin 进行打包。基本上,它将您的项目及其依赖项组装为一个 jar,不仅包括您的项目 jar 文件,还包括所有外部依赖项作为“jar 的 jar”,例如
<build>
<plugins>
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
注意 1:配置选项在项目 home page 中可用。
注意 2:出于某种原因,onejar-maven-plugin 项目未在 Maven 中心发布。但是jolira.com 跟踪原始项目并将其发布到 groupId com.jolira
。
【讨论】:
是否可以选择要打包的依赖项?例如,如果 a.jar 和 b.jar 是外部 jar,我只想将 a.jar 打包到最终的 jar 中,是否可以/可配置? 我还看到一个罐子的东西也被捆绑在最终罐子里。这大大增加了最终罐子的大小。是否可以选择您打算包含在最终 jar 中的外部 jar?这是一罐日志:pastebin.com/UwniQJ2X 我不知道你是否可以配置包含的内容。基本上,one-jar 包含项目指定的所有依赖项,包括传递依赖项,所以是的,如果您有很多依赖项,最终的 jar 可能会变得很大。为了让 Java 使用“jar of jars”结构,一个 jar 会增加一些开销。【参考方案6】:另一种方法是使用 maven shade 插件来构建 uber-jar
。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version> Your Version Here </version>
<configuration>
<!-- put your configurations here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
【讨论】:
以上是关于使用 maven 构建一个胖罐子的主要内容,如果未能解决你的问题,请参考以下文章
是否可以用@SpringBootApplication main 制作一个带有两个弹簧启动应用程序的胖罐子