我想将我的项目打包在一个可执行的JAR中进行分发。

如何使Maven项目将所有依赖JAR打包到输出JAR中?


当前回答

对我有用的是:

  <plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
      <execution>
        <id>unpack-dependencies</id>
        <phase>prepare-package</phase>
        <goals>
          <goal>unpack-dependencies</goal>
        </goals>
        <configuration>
          <outputDirectory>${project.build.directory}/classes</outputDirectory>
        </configuration>
      </execution>

    </executions>
  </plugin>

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <executions>
      <execution>
        <id>unpack-dependencies</id>
        <phase>package</phase>
      </execution>
    </executions>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <classpathPrefix>lib/</classpathPrefix>
          <mainClass>SimpleKeyLogger</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>

我有一个特殊的案例,因为我的依赖是系统一:

<dependency>
  ..
  <scope>system</scope>
  <systemPath>${project.basedir}/lib/myjar.jar</systemPath>
</dependency>

我已经更改了user189057提供的代码,并进行了更改:

maven依赖插件在“准备包”阶段执行我将解压缩的类直接提取到“目标/类”

其他回答

已经有数百万个答案了。我想补充一下,如果您不需要在应用程序中添加entryPoint,那么您不需要<mainClass>。例如,API可能不一定有主方法。

Maven插件配置

  <build>
    <finalName>log-enrichment</finalName>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>

建筑

mvn clean compile assembly:single

验证

ll target/
total 35100
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ./
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ../
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 archive-tmp/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 classes/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-sources/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-test-sources/
-rwxrwx--- 1 root vboxsf 35929841 Sep 29 16:10 log-enrichment-jar-with-dependencies.jar*
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 maven-status/

如果您真的想重新打包单个结果JAR中的其他JAR内容,另一个选项是Maven Assembly插件。它通过<unpack>true</unpack>解包,然后将所有内容重新打包到一个目录中。然后,您将有第二个过程,将其构建到一个大型JAR中。

另一个选项是OneJar插件。这将在一个步骤中执行上述重新打包操作。

我长期使用Maven汇编插件,但我找不到解决“已添加,跳过”问题的方法。现在,我正在使用另一个插件——onejar maven插件。下面是一个示例(mvn包构建JAR文件):

<plugin>
    <groupId>org.dstovall</groupId>
    <artifactId>onejar-maven-plugin</artifactId>
    <version>1.3.0</version>
    <executions>
        <execution>
            <configuration>
                <mainClass>com.company.MainClass</mainClass>
            </configuration>
            <goals>
                <goal>one-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

您需要为该插件添加存储库:

<pluginRepositories>
    <pluginRepository>
        <id>onejar-maven-plugin.googlecode.com</id>
        <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
    </pluginRepository>
</pluginRepositories>

这是我找到的最好的方法:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <version>2.4</version>
  <configuration>
    <archive>
      <manifest>
      <addClasspath>true</addClasspath>
      <mainClass>com.myDomain.etc.MainClassName</mainClass>
      <classpathPrefix>dependency-jars/</classpathPrefix>
      </manifest>
    </archive>
  </configuration>
</plugin>

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>2.5.1</version>
  <executions>
    <execution>
      <id>copy-dependencies</id>
      <phase>package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>
          ${project.build.directory}/dependency-jars/
        </outputDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

使用此配置,所有依赖项都将位于依赖项jar中。我的应用程序没有Main类,只有上下文类,但我的一个依赖项确实有一个Main类(com.myDomain.ec.MainClassName),它启动JMX服务器,并接收start或stop参数。因此,我可以这样启动我的应用程序:

java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start

我尝试了多种解决方案,但这是一种在我们想要创建一个不可执行的胖JAR文件的场景中非常有效的解决方案,该文件包含外部系统的所有内部依赖项,而这些依赖项与之前无关。测试了生产场景。

将其包含在pom.xml文件中:

<?xml version="1.0" encoding="UTF-8"?>
<build>
   <sourceDirectory>src</sourceDirectory>
   <plugins>
      <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>3.8.1</version>
         <configuration>
            <source>1.8</source>
            <target>1.8</target>
         </configuration>
      </plugin>
      <plugin>
         <artifactId>maven-assembly-plugin</artifactId>
         <configuration>
            <descriptorRefs>
               <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
         </configuration>
      </plugin>
   </plugins>
</build>

要运行以构建胖JAR文件的命令:

mvn assembly:assembly