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

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

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


当前回答

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

其他回答

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.

把Maven放在一边,您可以把JAR库放在Main JAR中,但是您需要使用自己的类加载器。

检查这个项目:One-JAR链接文本

您可以使用<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>

你可以使用带有"jar-with-dependencies"描述符的maven-assembly插件来做到这一点。下面是我们的pom.xml的相关代码块:

  <build>
    <plugins>
      <!-- any other plugins -->
      <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>
    </plugins>
  </build>

如果你(像我一样)不是特别喜欢上面描述的带依赖的罐子方法, 我更喜欢的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文件中)。