如何使用 Maven Shade 创建 Fat Jar?

问题描述 投票:0回答:0

我正在尝试使用 Maven 创建一个 fat jar。每个人都说 Shade 插件是最简单的方法,所以这就是我正在尝试的。我已经尝试了很多示例项目。它们在使用的 XML 标签和 XML 的嵌套方式上都略有不同,这令人困惑和沮丧,但它们都对我不起作用,而且它们都太晦涩了,我无法说出它们为什么不起作用。

我试图将问题归结为最小可行的 Hello World 项目。

这里是项目结构:

  ├── pom.xml
  └── src
      └── main
          └── java
              └── org
                  └── example
                      └── Hello.java

我的 Hello.java 看起来像这样:

package org.example;

import gnu.getopt.Getopt;

public class Hello {
    public static void main(String[] args) {
        Getopt g = new Getopt("hello", args, "x");

        int c;
        while ((c = g.getopt()) != -1) {
            switch (c) {
                case 'x' -> System.out.println("Hello X!");
                default -> System.out.println("Error " + c);
            }
        }
        System.out.println("Goodbye");
    }
};

我的 pom.xml 看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>hello-fat-jar</artifactId>
  <version>0.1-SNAPSHOT</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target> 
    <maven.compiler.release>17</maven.compiler.release> 
  </properties>

  <dependencies>
    <!-- https://mvnrepository.com/artifact/gnu.getopt/java-getopt -->
    <dependency>
      <groupId>gnu.getopt</groupId>
      <artifactId>java-getopt</artifactId>
      <version>1.0.13</version>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-shade-plugin</artifactId>
          <version>3.4.1</version>
          <executions>
            <execution>
              <phase>package</phase>
              <goals>
                <goal>shade</goal>
              </goals>
              <configuration>
                <transformers>
                  <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">i
                    <mainClass>org.example.Hello</mainClass>
                  </transformer>
                </transformers>
              </configuration>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

到目前为止一切顺利。我做一个 mvn clean package:

$ mvn clean package
[INFO] Scanning for projects...
[INFO] 
[INFO] ---------------------< org.example:hello-fat-jar >----------------------
[INFO] Building hello-fat-jar 0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from central: https://repo.maven.apache.org/maven2/gnu/getopt/java-getopt/1.0.13/java-getopt-1.0.13.pom
Downloaded from central: https://repo.maven.apache.org/maven2/gnu/getopt/java-getopt/1.0.13/java-getopt-1.0.13.pom (2.0 kB at 9.5 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/gnu/getopt/java-getopt/1.0.13/java-getopt-1.0.13.jar
Downloaded from central: https://repo.maven.apache.org/maven2/gnu/getopt/java-getopt/1.0.13/java-getopt-1.0.13.jar (60 kB at 1.8 MB/s)
[INFO] 
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ hello-fat-jar ---
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-fat-jar ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory HOME/src/java/hello-fat-jar/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello-fat-jar ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to HOME/src/java/hello-fat-jar/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-fat-jar ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory HOME/src/java/hello-fat-jar/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello-fat-jar ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello-fat-jar ---
[INFO] No tests to run.
[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-fat-jar ---
[INFO] Building jar: HOME/src/java/hello-fat-jar/target/hello-fat-jar-0.1-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.595 s
[INFO] Finished at: 2023-03-24T16:30:35-07:00
[INFO] ------------------------------------------------------------------------

可以看到依赖已经下载好了:

$ ls ~/.m2/repository/gnu/getopt/java-getopt/1.0.13
java-getopt-1.0.13.jar  java-getopt-1.0.13.jar.sha1  java-getopt-1.0.13.pom  java-getopt-1.0.13.pom.sha1  _remote.repositories

但是它并没有创建一个fat jar:

$ jar tf target/hello-fat-jar-0.1-SNAPSHOT.jar
META-INF/
META-INF/MANIFEST.MF
org/
org/example/
org/example/Hello.class
META-INF/maven/
META-INF/maven/org.example/
META-INF/maven/org.example/hello-fat-jar/
META-INF/maven/org.example/hello-fat-jar/pom.xml
META-INF/maven/org.example/hello-fat-jar/pom.properties

当我尝试运行它时,它抱怨没有主要的清单属性,据说 shade 插件应该设置:

$ java -jar target/hello-fat-jar-0.1-SNAPSHOT.jar
no main manifest attribute, in target/hello-fat-jar-0.1-SNAPSHOT.jar

我可以通过添加带有

maven-jar-plugin
<mainClass>
来绕过主清单,但它仍然不是一个胖罐子并且找不到 Getopt 依赖项。阴影插件也应该设置主类,但它没有这样做。我想了解为什么它不起作用,并修复它,而不是依赖一个破旧的创可贴。

但是代码和jar还是不错的!我可以使用显式类路径运行它:

$ java -cp target/hello-fat-jar-0.1-SNAPSHOT.jar:$HOME/.m2/repository/gnu/getopt/java-getopt/1.0.13/java-getopt-1.0.13.jar org.example.Hello -x
Hello X!
Goodbye

(不管它值多少钱,这是我能找到的最简洁的教程:https://javahelps.com/how-to-create-a-fat-jar-using-maven

我做错了什么?我如何使用 shade 插件创建一个 fat jar?

更新:根据 tgdavies 的评论,我删除了

<pluginManagement>
标签,一切都按预期进行。 (插件管理来自 maven
archetype:generate
目标。)

java maven maven-shade-plugin
© www.soinside.com 2019 - 2024. All rights reserved.