如何告诉 Maven 构建可执行 jar

发布于 2024-10-18 23:50:58 字数 5163 浏览 2 评论 0原文

这看起来应该很简单,但我还没有弄清楚,也没有从阅读文档和搜索网络中得到太多帮助。为了学习在多模块项目中使用 Maven (2.2.1),我使用 Maven 创建了一个简单的项目 P,其中包含类 C(包含 main)和子类 S。当我运行 mvn install< /code> 构建运行并生成 BUILD SUCCESSFUL 消息。但是,当我运行生成的 C jar 时,出现异常:“Exception in thread "main" java.lang.NoClassDefFoundError: P/S”

目录结构(不显示 src 等子目录)为:

P
|--C
|--S

目前 P 目录下的 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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>P</groupId>
  <artifactId>P</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>P</name>
  <url>http://maven.apache.org</url>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>P</groupId>
        <artifactId>C</artifactId>
        <version>${project.version}</version>
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>P</groupId>
        <artifactId>S</artifactId>
        <version>${project.version}</version>  
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>P.C</mainClass>
              <packageName>P.C</packageName>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <modules>
    <module>C</module>
    <module>S</module>
  </modules>

</project>

C 目录下的 pom.xml 为:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <artifactId>P</artifactId>
    <groupId>P</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <groupId>P</groupId>
  <artifactId>C</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>C</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>P</groupId>
      <artifactId>S</artifactId>
      <version>${project.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

S 目录下的 pom.xml 为:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <artifactId>P</artifactId>
    <groupId>P</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <groupId>P</groupId>
  <artifactId>S</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>S</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

以上都是经过多次尝试后的最新版本。

对于这个简单的学习练习,Java 类是:

P/C/src/main/java/P/C.java:

package P;

public class C
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
        S o = new S();
        o.sayHey();
    }
}

和 S/src/main/java/P/S.java:

package P;

public class S
{
    public void sayHey()
    {
        System.out.println("Hey!");
    }
}

那么,我如何告诉 Maven将S类包含在C jar中?

This seems like it should be simple, but I've not figured it out and haven't gotten much help from reading the docs and searching the web. In an effort to learn to use Maven (2.2.1) with a multimodule project, I've used Maven to create a simple project P with a class C (containing main) and subclass S. When I run mvn install the build runs and produces a BUILD SUCCESSFUL message. However, when I run the resulting C jar, I get an exception: "Exception in thread "main" java.lang.NoClassDefFoundError: P/S"

The directory structure (not showing the src, etc. subdirectories) is:

P
|--C
|--S

The pom.xml in directory P currently is:

<?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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>P</groupId>
  <artifactId>P</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>P</name>
  <url>http://maven.apache.org</url>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>P</groupId>
        <artifactId>C</artifactId>
        <version>${project.version}</version>
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>P</groupId>
        <artifactId>S</artifactId>
        <version>${project.version}</version>  
        <scope>compile</scope>
      </dependency>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>3.8.1</version>
        <scope>test</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <mainClass>P.C</mainClass>
              <packageName>P.C</packageName>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <modules>
    <module>C</module>
    <module>S</module>
  </modules>

</project>

The pom.xml in C is:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <artifactId>P</artifactId>
    <groupId>P</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <groupId>P</groupId>
  <artifactId>C</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>C</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>P</groupId>
      <artifactId>S</artifactId>
      <version>${project.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

and the pom.xml in S is:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <artifactId>P</artifactId>
    <groupId>P</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <groupId>P</groupId>
  <artifactId>S</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>S</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

The above are all the latest versions after several attempts.

For this simple learning exercise, the Java classes are:

P/C/src/main/java/P/C.java:

package P;

public class C
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
        S o = new S();
        o.sayHey();
    }
}

and S/src/main/java/P/S.java:

package P;

public class S
{
    public void sayHey()
    {
        System.out.println("Hey!");
    }
}

So, how do I tell Maven to include the S class in the C jar?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦回梦里 2024-10-25 23:50:58

默认情况下,Maven 不包含工件中的依赖项:要运行 P,您的类路径中仍然需要 S。

这通常不是问题,因为 Maven 本身使用传递依赖项:例如,如果您有另一个项目依赖于 P,它会自动将 P 和 S 放入您的类路径中。

如果你想创建一个“uber-jar”:一个包含所有依赖项的自包含 jar,请查看“shade”插件: http://maven.apache.org/plugins/maven-shade-plugin/

Maven does not include dependencies in artifacts by default: to run P you still need S in your classpath.

That isn't normally an issue as maven itself uses transitive dependencies: for example, if you have another project depend on P, it will automatically put both P and S in your classpath.

If you want to create a 'uber-jar': a self contained jar containing all dependencies, look at the 'shade' plugin: http://maven.apache.org/plugins/maven-shade-plugin/

江湖正好 2024-10-25 23:50:58

经过更多研究,我找到了一种告诉 Maven 构建一个包含所有需要的类的 jar 文件的方法。我唯一需要更改的 pom 位于 P 目录中。首先,必须从构建插件部分删除以下部分:

    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
      <archive>
        <manifest>
          <mainClass>P.C</mainClass>
          <packageName>P.C</packageName>
        </manifest>
      </archive>
    </configuration>

在其位置我放置:

    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
      <execution>
        <id>create-executable-jar</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>P.C</mainClass>
              <packageName>P.C</packageName>
            </manifest>
          </archive>
        </configuration>
      </execution>
    </executions>

After more research, I've found a means of telling Maven to build a jar file which includes all the needed classes. The only pom I had to change was in the P directory. First, the following section had to be removed from the build-plugins section:

    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
      <archive>
        <manifest>
          <mainClass>P.C</mainClass>
          <packageName>P.C</packageName>
        </manifest>
      </archive>
    </configuration>

In its place I put:

    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
      <execution>
        <id>create-executable-jar</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>P.C</mainClass>
              <packageName>P.C</packageName>
            </manifest>
          </archive>
        </configuration>
      </execution>
    </executions>
一身仙ぐ女味 2024-10-25 23:50:58

maven exec 插件可能会解决您的问题。您可以使用它来运行 C.jar,它将管理类路径(并确保包含 S.jar)。

将与此类似的内容添加到您的 P pom.xml 中:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.1</version>
        <executions>
          <execution>
            ...
            <goals>
              <goal>java</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <mainClass>P.C</mainClass>
        </configuration>
      </plugin>
    </plugins>
  </build>
   ...
</project>

然后您应该能够像这样运行该程序:

mvn exec:java -Dexec.mainClass="P.C"

The maven exec plugin might solve your problem. You can use it to run the C.jar and it will manage the classpath (and ensure that S.jar is included).

Add something similar to this to your P pom.xml:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.1</version>
        <executions>
          <execution>
            ...
            <goals>
              <goal>java</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <mainClass>P.C</mainClass>
        </configuration>
      </plugin>
    </plugins>
  </build>
   ...
</project>

Then you should be able to run the program like this:

mvn exec:java -Dexec.mainClass="P.C"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文