Java:如何构建基于Maven的项目的独立发行版?

时间:2023-01-12 00:01:57

I often encounter distributions of Java applications or libraries which use Maven as their build tool.

我经常遇到使用Maven作为构建工具的Java应用程序或库的发行版。

Some of them, sadly, don't provide standalone (or redistributable) jars.

遗憾的是,其中一些不提供独立(或可再分发)的罐子。

Is it possible to build Maven-based applications in such a way, that the build result contains all dependencies and can be redistributed to work out-of-the box?

是否有可能以这种方式构建基于Maven的应用程序,构建结果包含所有依赖项并且可以重新分发以便开箱即用?

I tried to build Jackrabbit's OCM module. For some very "intelligent" reasons there is no downloadable standalone version.
So I built Jackrabbit with Maven (the source package of Jackrabbit includes OCM), and got the same jar as found in the apache repository. The jar doesn't contain necessary dependencies and is useless to me.

我试着建立Jackrabbit的OCM模块。出于一些非常“智能”的原因,没有可下载的独立版本。所以我用Maven构建了Jackrabbit(Jackrabbit的源代码包包括OCM),并获得了与apache存储库中相同的jar。 jar不包含必要的依赖项,对我来说没用。

6 个解决方案

#1


Use the Maven Shade plugin

使用Maven Shade插件

...but be careful of the gotchas (similar to the one described further down my answer), which has got a workaround explained here.

...但要小心陷阱(类似于我的答案中进一步描述的那个),这里有一个解决方法。

Also, be ultra careful with the Shade plugin config. I accidentally used double <configuration> tags once, and the transformers didn't apply at all, and the plugin also took the liberty of not warning me.

另外,要小心使用Shade插件配置。我偶然使用了双 标签,并且变压器根本不适用,插件也冒昧地不警告我。

Don't use the Maven Assembly plugin

不要使用Maven Assembly插件

assembly:single will unpack your dependency JARs as-is, and this could not be what you want. E.g. stuff like META-INF/spring.schemas will be overridden with the last Spring dependency JAR that's evaluated, and as such your XSDs won't be found (apart from those in the last JAR, of course). Which is why systems like Alfresco made their AMP plugin which bundles dependencies inside lib/ inside the AMP you're building. The latter raises dependency management issues, though.

assembly:single将按原样解压缩依赖JAR,这可能不是你想要的。例如。像META-INF / spring.schemas这样的东西会被评估的最后一个Spring依赖JAR覆盖,因此你找不到你的XSD(当然除了最后一个JAR中的那些)。这就是为什么像Alfresco这样的系统制作了他们的AMP插件,它将lib内部的依赖关系捆绑在你正在构建的AMP中。然而,后者引发了依赖管理问题。

#2


You may have some luck with the appassembler plugin. Failing that, take a look at the assembly plugin. That's more flexible, but lower level. If you're using the assembly plugin, you may find the chapter on it in maven: the definitive guide to be useful.

你可能对appassembler插件有一些运气。如果做不到这一点,请看一下程序集插件。这更灵活,但水平更低。如果你正在使用汇编插件,你可以在maven中找到它的章节:有用的权威指南。

#3


As Dominic said, using the assembly plugin will do the trick. You would usually configure it inside your own project's POM to gather and package all required dependencies:

正如Dominic所说,使用程序集插件可以解决问题。您通常会在自己项目的POM中配置它来收集和打包所有必需的依赖项:

  ...
  <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
    </configuration>
  </plugin>
  ...

jar-with-dependencies is predefined by the assembly plugin and will include all dependencies in the final package (see the documentation here).

jar-with-dependencies由程序集插件预定义,并将包含最终包中的所有依赖项(请参阅此处的文档)。

If you don't want to use Maven for your own project, you will need to modify the libraries' POMs and repackage them yourself (download the sources, add the above snippet to pom.xml and run mvn package). Beware of duplicate or incompatible transitive dependencies if you use multiple libraries. exclusions might help in that case (see documentation here).

如果您不想将Maven用于您自己的项目,则需要修改库的POM并自行重新打包(下载源代码,将上述代码段添加到pom.xml并运行mvn包)。如果使用多个库,请注意重复或不兼容的传递依赖项。在这种情况下,排除可能有所帮助(请参阅此处的文档)。

#4


As a couple of the posters said, the assembly plugin is a good way of creating a complete jar file, with all project dependencies. However, you don't actually have to modify the pom.xml file. Simply run:

正如一些海报所说,汇编插件是一个创建完整jar文件的好方法,具有所有项目依赖性。但是,您实际上不必修改pom.xml文件。只需运行:

mvn assembly:single -DdescriptorId=jar-with-dependencies

... in order to create a jar file. If you want to do anything more advanced, you should probably modify pom.xml, and create a custom assembly descriptor.

...为了创建一个jar文件。如果你想做更高级的事情,你应该修改pom.xml,并创建一个自定义程序集描述符。

#5


Change the pom.xml file and use the <Embed-Dependency> directive. A similar example can be found here so you can adapt it to your scenario.

更改pom.xml文件并使用 指令。可以在此处找到类似的示例,以便您可以根据您的方案进行调整。

<Embed-Dependency>*;scope=!test;inline=true</Embed-Dependency>

I think this should do the trick.

我认为这应该可以解决问题。


Here is the example at the above URL that seems to give timeout.

以下是上述URL中的示例,它似乎给出了超时。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>br.gov.lexml</groupId>
    <artifactId>toolkit</artifactId>
    <packaging>bundle</packaging>
    <version>3.0</version>
    <parent>
        <artifactId>lexml</artifactId>
        <groupId>br.gov.lexml</groupId>
        <version>1.0</version>
    </parent>
    <build>
        <finalName>Lexml_Toolkit-2.0</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <!--_include>src/toolkit/resources/META-INF/MANIFEST.MF</_include-->

                        <Export-Package>*;-split-package:=merge-last</Export-Package>
                        <Bundle-Activator>br.gov.lexml.borda.Toolkit</Bundle-Activator>
                        <Bundle-Name>Toolkit</Bundle-Name>
                        <Private-Package />
                        <Embed-Dependency>*;scope=!test;inline=true</Embed-Dependency>
                        <Bundle-ClassPath>.,{maven-dependencies}</Bundle-ClassPath>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans-xmlpublic</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
        </dependency>
        <dependency>
            <groupId>br.gov.lexmlbeans</groupId>
            <artifactId>lexmlbeans</artifactId>
            <version>3.0</version>
        </dependency>
    </dependencies>
</project>

#6


I believe the Maven Shade Plugin will satisfy your needs. I use it when I am building command line interface tools to create an Uber JAR including my classes and along with the classes from all my dependencies.

我相信Maven Shade插件可以满足您的需求。我在构建命令行界面工具时使用它来创建包含我的类的Uber JAR以及来自所有依赖项的类。

Its very easy to use and I think this example is self-explanatory.

它非常容易使用,我认为这个例子是不言自明的。

#1


Use the Maven Shade plugin

使用Maven Shade插件

...but be careful of the gotchas (similar to the one described further down my answer), which has got a workaround explained here.

...但要小心陷阱(类似于我的答案中进一步描述的那个),这里有一个解决方法。

Also, be ultra careful with the Shade plugin config. I accidentally used double <configuration> tags once, and the transformers didn't apply at all, and the plugin also took the liberty of not warning me.

另外,要小心使用Shade插件配置。我偶然使用了双 标签,并且变压器根本不适用,插件也冒昧地不警告我。

Don't use the Maven Assembly plugin

不要使用Maven Assembly插件

assembly:single will unpack your dependency JARs as-is, and this could not be what you want. E.g. stuff like META-INF/spring.schemas will be overridden with the last Spring dependency JAR that's evaluated, and as such your XSDs won't be found (apart from those in the last JAR, of course). Which is why systems like Alfresco made their AMP plugin which bundles dependencies inside lib/ inside the AMP you're building. The latter raises dependency management issues, though.

assembly:single将按原样解压缩依赖JAR,这可能不是你想要的。例如。像META-INF / spring.schemas这样的东西会被评估的最后一个Spring依赖JAR覆盖,因此你找不到你的XSD(当然除了最后一个JAR中的那些)。这就是为什么像Alfresco这样的系统制作了他们的AMP插件,它将lib内部的依赖关系捆绑在你正在构建的AMP中。然而,后者引发了依赖管理问题。

#2


You may have some luck with the appassembler plugin. Failing that, take a look at the assembly plugin. That's more flexible, but lower level. If you're using the assembly plugin, you may find the chapter on it in maven: the definitive guide to be useful.

你可能对appassembler插件有一些运气。如果做不到这一点,请看一下程序集插件。这更灵活,但水平更低。如果你正在使用汇编插件,你可以在maven中找到它的章节:有用的权威指南。

#3


As Dominic said, using the assembly plugin will do the trick. You would usually configure it inside your own project's POM to gather and package all required dependencies:

正如Dominic所说,使用程序集插件可以解决问题。您通常会在自己项目的POM中配置它来收集和打包所有必需的依赖项:

  ...
  <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
    </configuration>
  </plugin>
  ...

jar-with-dependencies is predefined by the assembly plugin and will include all dependencies in the final package (see the documentation here).

jar-with-dependencies由程序集插件预定义,并将包含最终包中的所有依赖项(请参阅此处的文档)。

If you don't want to use Maven for your own project, you will need to modify the libraries' POMs and repackage them yourself (download the sources, add the above snippet to pom.xml and run mvn package). Beware of duplicate or incompatible transitive dependencies if you use multiple libraries. exclusions might help in that case (see documentation here).

如果您不想将Maven用于您自己的项目,则需要修改库的POM并自行重新打包(下载源代码,将上述代码段添加到pom.xml并运行mvn包)。如果使用多个库,请注意重复或不兼容的传递依赖项。在这种情况下,排除可能有所帮助(请参阅此处的文档)。

#4


As a couple of the posters said, the assembly plugin is a good way of creating a complete jar file, with all project dependencies. However, you don't actually have to modify the pom.xml file. Simply run:

正如一些海报所说,汇编插件是一个创建完整jar文件的好方法,具有所有项目依赖性。但是,您实际上不必修改pom.xml文件。只需运行:

mvn assembly:single -DdescriptorId=jar-with-dependencies

... in order to create a jar file. If you want to do anything more advanced, you should probably modify pom.xml, and create a custom assembly descriptor.

...为了创建一个jar文件。如果你想做更高级的事情,你应该修改pom.xml,并创建一个自定义程序集描述符。

#5


Change the pom.xml file and use the <Embed-Dependency> directive. A similar example can be found here so you can adapt it to your scenario.

更改pom.xml文件并使用 指令。可以在此处找到类似的示例,以便您可以根据您的方案进行调整。

<Embed-Dependency>*;scope=!test;inline=true</Embed-Dependency>

I think this should do the trick.

我认为这应该可以解决问题。


Here is the example at the above URL that seems to give timeout.

以下是上述URL中的示例,它似乎给出了超时。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>br.gov.lexml</groupId>
    <artifactId>toolkit</artifactId>
    <packaging>bundle</packaging>
    <version>3.0</version>
    <parent>
        <artifactId>lexml</artifactId>
        <groupId>br.gov.lexml</groupId>
        <version>1.0</version>
    </parent>
    <build>
        <finalName>Lexml_Toolkit-2.0</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <!--_include>src/toolkit/resources/META-INF/MANIFEST.MF</_include-->

                        <Export-Package>*;-split-package:=merge-last</Export-Package>
                        <Bundle-Activator>br.gov.lexml.borda.Toolkit</Bundle-Activator>
                        <Bundle-Name>Toolkit</Bundle-Name>
                        <Private-Package />
                        <Embed-Dependency>*;scope=!test;inline=true</Embed-Dependency>
                        <Bundle-ClassPath>.,{maven-dependencies}</Bundle-ClassPath>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans-xmlpublic</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
        </dependency>
        <dependency>
            <groupId>br.gov.lexmlbeans</groupId>
            <artifactId>lexmlbeans</artifactId>
            <version>3.0</version>
        </dependency>
    </dependencies>
</project>

#6


I believe the Maven Shade Plugin will satisfy your needs. I use it when I am building command line interface tools to create an Uber JAR including my classes and along with the classes from all my dependencies.

我相信Maven Shade插件可以满足您的需求。我在构建命令行界面工具时使用它来创建包含我的类的Uber JAR以及来自所有依赖项的类。

Its very easy to use and I think this example is self-explanatory.

它非常容易使用,我认为这个例子是不言自明的。