有没有办法强制maven(2.0.9)将所有依赖项包含在一个jar文件中?

我有一个项目的构建到一个单一的jar文件。我希望依赖的类也能复制到jar中。

更新:我知道我不能只在jar文件中包含一个jar文件。我正在寻找一种方法来解包指定为依赖项的jar,并将类文件打包到我的jar中。


当前回答

http://fiji.sc/Uber-JAR提供了一个很好的解释:

There are three common methods for constructing an uber-JAR: Unshaded. Unpack all JAR files, then repack them into a single JAR. Pro: Works with Java's default class loader. Con: Files present in multiple JAR files with the same path (e.g., META-INF/services/javax.script.ScriptEngineFactory) will overwrite one another, resulting in faulty behavior. Tools: Maven Assembly Plugin, Classworlds Uberjar Shaded. Same as unshaded, but rename (i.e., "shade") all packages of all dependencies. Pro: Works with Java's default class loader. Avoids some (not all) dependency version clashes. Con: Files present in multiple JAR files with the same path (e.g., META-INF/services/javax.script.ScriptEngineFactory) will overwrite one another, resulting in faulty behavior. Tools: Maven Shade Plugin JAR of JARs. The final JAR file contains the other JAR files embedded within. Pro: Avoids dependency version clashes. All resource files are preserved. Con: Needs to bundle a special "bootstrap" classloader to enable Java to load classes from the wrapped JAR files. Debugging class loader issues becomes more complex. Tools: Eclipse JAR File Exporter, One-JAR.

其他回答

我发现这是最明确的答案;这里的其他答案是缺少一些对我来说不明显的东西,例如MVN清洁包命令,以及单独添加插件作为依赖项。所有这些对于更习惯的专业用户来说可能是显而易见的。

https://howtodoinjava.com/maven/executable-jar-with-dependencies/

您可以使用<classifier>标记来使用新创建的jar。

<dependencies>
    <dependency>
        <groupId>your.group.id</groupId>
        <artifactId>your.artifact.id</artifactId>
        <version>1.0</version>
        <type>jar</type>
        <classifier>jar-with-dependencies</classifier>
    </dependency>
</dependencies>

我试图做一些类似的事情,但我不希望所有的罐子都包括在内。我想从给定的依赖项中包含一些特定的目录。另外,分类器标签已经被占用,所以我不能做:

<dependencies>
    <dependency>
        <groupId>your.group.id</groupId>
        <artifactId>your.artifact.id</artifactId>
        <version>1.0</version>
        <type>jar</type>
        <classifier>jar-with-dependencies</classifier>
    </dependency>
</dependencies>

我使用maven-dependency-plugin和unpack goal 并将我想要的内容解压缩到${project.build。目录}/类,否则将省略 因为它在classes目录中,maven最终将它放在jar中

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>unpack</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>unpack</goal>
            </goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>my.group</groupId>
                        <artifactId>my.artifact</artifactId>
                        <classifier>occupied</classifier>
                        <version>1.0</version>
                        <type>jar</type>
                    </artifactItem>
                </artifactItems>
                <outputDirectory>${project.build.directory}/classes</outputDirectory>
                <includes>aaa/**, bbb/**, ccc/**</includes>
            </configuration>
        </execution>
    </executions>
</plugin>

如果你(像我一样)不是特别喜欢上面描述的带依赖的罐子方法, 我更喜欢的maven解决方案是简单地建立一个war项目, 即使你只是在构建一个独立的Java应用程序:

Make a normal maven jar-project, that will build your jar-file (without the dependencies). Also, setup a maven war-project (with only an empty src/main/webapp/WEB-INF/web.xml file, which will avoid a warning/error in the maven-build), that only has your jar-project as a dependency, and make your jar-project a <module> under your war-project. (This war-project is only a simple trick to wrap all your jar-file dependencies into a zip-file.) Build the war-project to produce the war-file. In the deployment-step, simply rename your .war-file to *.zip and unzip it.

你现在应该有一个lib目录(你可以移动到你想要的地方),里面有你的jar和运行应用程序所需的所有依赖项:

java -cp 'path/lib/*' MainClass

(类路径中的通配符在Java-6或更高版本中有效)

我认为这样在maven中设置起来更简单(不需要使用汇编插件),而且可以更清楚地看到应用程序结构(您将在普通视图中看到所有依赖jar的版本号,并避免将所有内容都塞进一个jar文件中)。

这是maven插件。它可用于打包和重命名依赖项(以忽略类路径上的依赖项问题)。