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

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

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

我使用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>

其他回答

看看这个答案:

I am creating an installer that runs as a Java JAR file and it needs to unpack WAR and JAR files into appropriate places in the installation directory. The dependency plugin can be used in the package phase with the copy goal and it will download any file in the Maven repository (including WAR files) and write them where ever you need them. I changed the output directory to ${project.build.directory}/classes and then end result is that the normal JAR task includes my files just fine. I can then extract them and write them into the installation directory.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
    <execution>
        <id>getWar</id>
        <phase>package</phase>
        <goals>
            <goal>copy</goal>
        </goals>
        <configuration>
            <artifactItems>
                <artifactItem>
                    <groupId>the.group.I.use</groupId>
                    <artifactId>MyServerServer</artifactId>
                    <version>${env.JAVA_SERVER_REL_VER}</version>
                    <type>war</type>
                    <destFileName>myWar.war</destFileName>
                </artifactItem>
            </artifactItems>
            <outputDirectory>${project.build.directory}/classes</outputDirectory>
        </configuration>
    </execution>
</executions>

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.

如果你想做一个可执行的jar文件,他们也需要设置主类。所以全构型应该是。

    <plugins>
            <plugin>
                 <artifactId>maven-assembly-plugin</artifactId>
                 <executions>
                     <execution>
                          <phase>package</phase>
                          <goals>
                              <goal>single</goal>
                          </goals>
                      </execution>
                  </executions>
                  <configuration>
                       <!-- ... -->
                       <archive>
                           <manifest>
                                 <mainClass>fully.qualified.MainClass</mainClass>
                           </manifest>
                       </archive>
                       <descriptorRefs>
                           <descriptorRef>jar-with-dependencies</descriptorRef>
                      </descriptorRefs>
                 </configuration>
         </plugin>
   </plugins>

这篇文章可能有点老了,但我最近也有同样的问题。John Stauffer提出的第一个解决方案很好,但我在今年春天工作时遇到了一些问题。我使用的spring依赖jar有一些属性文件和xml模式声明,它们共享相同的路径和名称。尽管这些jar来自相同的版本,但jar-with-dependencies maven-goal正在用最后找到的文件覆盖这些文件。

最后,由于spring jar找不到正确的属性文件,应用程序无法启动。在这种情况下,罗普提出的解决方案已经解决了我的问题。

也是从那时起,spring-boot项目现在就存在了。它有一种非常酷的方法来管理这个问题,即提供一个maven目标,该目标重载包目标并提供自己的类装入器。参见弹簧靴参考指南

方法1:将依赖的JAR文件复制到target/lib中,然后将它们添加到MANIFEST中的JAR类路径中:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <configuration>
                <outputDirectory>${project.build.directory}/lib</outputDirectory>
                <excludeTransitive>false</excludeTransitive> 
                <stripVersion>false</stripVersion>
            </configuration>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <!-- Add LIB folder to classPath -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

方法2:解包所有依赖项,并将它们的类和资源重新打包到一个平面JAR中。注意:重叠的资源会随机丢失!

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals><goal>single</goal></goals>
        </execution>
    </executions>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
</plugin>