使用Maven构建胖罐


118

我有一个要作为jar分发的代码库。它还依赖于外部jar,我想将它们捆绑到最终的jar中。

我听说可以使用完成此操作maven-assembly-plug-in,但我不知道如何操作。有人可以给我指出一些例子。

现在,我正在使用胖罐子捆绑最终的罐子。我想使用Maven实现相同的目的。

Answers:


143

注意:如果您是Spring Boot应用程序,请阅读答案结尾

将以下插件添加到您pom.xml 的最新版本可以在以下位置找到

...
<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:一个仅包含项目类,另一个带有所有后缀“ -jar-with-dependencies”的胖jar。

如果您想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>

对于春季启动应用程序,请使用以下插件(选择合适的版本)

<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>

1
该插件的当前版本为2.4
guerda

13
现在已弃用此方法,应改为使用maven-shade-plugin。参见@phlogratos答案:stackoverflow.com/a/16222965/274350
理查德·尼什

2
Maven-assembly-plugin可以最小化胖子罐的大小吗?
2015年

1
@Richard您在哪里看到它已被弃用?我不能在这里找到任何maven.apache.org/plugins/maven-assembly-plugin
user3833308

3
@ user3833308“过时”可能是错误的词,但在文档maven.apache.org/plugins/maven-assembly-plugin说:“如果你的项目要打包神器在尤伯杯罐子,组装插件只提供基本支持。要获得更多控制权,请使用Maven Shade插件。”
理查德·尼什

55

您可以使用maven-shade-plugin

在构建中配置完遮阳插件后,该命令mvn package将创建一个单个jar,并将所有依赖项合并到其中。


9
现在,这是正确的方法。Maven-assembly-plugin文档指出:“如果您的项目想要将工件打包在uber-jar中,则Assembly插件仅提供基本支持。要进行更多控制,请使用Maven Shade插件。”
理查德·尼什

但是,如何获取单个.jar并将其用于发布?
DanGordon

42

也许您需要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>

参考文献:


如果遇到Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found,只需将其取出<minimizeJar>true</minimizeJar>
koppor

如果收到“ java.lang.SecurityException:清单主要属性的无效签名文件摘要”异常,则对上述配置部分的添加将有所帮助:stackoverflow.com/a/6743609/38368
Danny Varod,

12

实际上,添加

<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罐”,例如

<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:配置选项可在项目主页上找到

注意2:出于某种原因,onejar-maven-plugin项目未在Maven Central中发布。但是jolira.com会跟踪原始项目并使用groupId将其发布到com.jolira


是否可以选择要打包的依赖项?例如,如果a.jar和b.jar是外部jar,而我只想将a.jar打包到最终jar中,是否有可能/可配置?
bianca 2013年

我还看到单罐子的东西也捆绑在最终罐子中。最终罐子的大小增加了很多。是否可以选择要包含在最终罐中的外部罐?这是一个jar日志:pastebin.com/UwniQJ2X
bianca 2013年

我不知道您是否可以配置包含的内容。基本上,一个jar包含项目指定的所有依赖关系,包括传递性依赖关系,因此,是的,如果您有很多依赖关系,则最终的jar可能会变大。为了使Java使用“ jars of jars”结构,一个jar将增加一些开销。
matsev 2013年

2

另一种方法是使用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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.