如何从包中生成JAR文件?

huangapple go评论74阅读模式
英文:

How to generate jar file from package?

问题

我有以下项目,我正在尝试从中生成jar文件。

如何从包中生成JAR文件?

我尝试了许多方法,但无法正确生成jar文件,我认为问题在于文件夹的结构,我还必须包含.xlsx文件,因为它是我程序的一部分。
当我尝试进行"clean and build"时,它会生成.jar文件,但是当我尝试运行它时,我会收到一个错误消息。
我还尝试过在Manifest.txt中手动指定主类并进行编译。

错误:找不到或加载主类NewJFrame
原因:java.lang.ClassNotFoundException: NewJFrame

我应该遵循哪些正确的步骤?
我提到"NewJFrame"是包含主类的类。

Pom的结构如下:

Pom 结构

英文:

I have the following project, I am trying to generate jar file from it.

如何从包中生成JAR文件?

I tried a ton of methods and I cannot properly generate the jar file, I think the problem is the folders structure, I also have to include the .xlsx as it it part of my program.
When I try to clean and build it generates the .jar file but when i try to run it I get an error
I also tried to manually specify the main class in the Manifest.txt and compile it.

Error: Could not find or load main class NewJFrame
Caused by: java.lang.ClassNotFoundException: NewJFrame

What are the correct steps I should follow?
I mention that the "NewJFrame" is the class that has the main inside

The pom structure is :

Pom Structure

答案1

得分: 0

将以下内容添加到您的pom文件中。这样您将会得到一个包含所有所需依赖和其他内容的单独的far(可执行)JAR文件。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.1.1</version>

    <configuration>
        <archive>
            <manifest>
                <mainClass>fully.qualified.MainClass</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>

    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>

</plugin>

不需要翻译的代码部分已被保留。

英文:

Add this into your pom file. And you will have a single far jar which contains all the dependencies you need and everything.

&lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-assembly-plugin&lt;/artifactId&gt;
            &lt;version&gt;3.1.1&lt;/version&gt;

            &lt;configuration&gt;
                &lt;archive&gt;
                  &lt;manifest&gt;
                     &lt;mainClass&gt;fully.qualified.MainClass&lt;/mainClass&gt;
                  &lt;/manifest&gt;
                &lt;/archive&gt;
                &lt;descriptorRefs&gt;
                    &lt;descriptorRef&gt;jar-with-dependencies&lt;/descriptorRef&gt;
                &lt;/descriptorRefs&gt;
            &lt;/configuration&gt;

            &lt;executions&gt;
                &lt;execution&gt;
                    &lt;id&gt;make-assembly&lt;/id&gt;
                    &lt;phase&gt;package&lt;/phase&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;single&lt;/goal&gt;
                    &lt;/goals&gt;
                &lt;/execution&gt;
            &lt;/executions&gt;

        &lt;/plugin&gt;

答案2

得分: 0

很遗憾,事情并不像听起来那么简单... 要运行一个Jar文件,您需要以下内容:

  • 您要运行的Jar文件。在您的情况下,这是从IDE命令生成的Jar文件。
  • 一个类路径,包括所有的依赖项。通常,这些依赖项由您的IDE管理,这也是您可以使用IDE运行应用程序的原因。但是当您生成一个Jar文件,例如使用Maven,您就不再由IDE为您管理依赖项了。

假设您有一个基本的Maven应用程序,没有依赖项,您可以按照以下步骤进行操作:

package com.stackoverflow.test;
public class Main {

    public static void main(String[] args) {
        System.out.println("Hello World !");
    }
}

然后,要生成Jar文件,运行man package。要运行它,执行以下操作(不需要清单文件):

java -cp target/myApp.jar com.stackoverflow.test.Main

这里,您可以看到-cp选项,它指示JVM加载一个Jar文件,在我们的例子中位于target目录下,名为myApp.jar,并在类com.stackoverflow.test.Main中执行主方法。

很简单,对吧?

但是,当您开始使用依赖项时,情况就会变得更加复杂。在我接下来的示例中,我将假设我有一个与著名库有关的依赖项。我将相应地更新我的POM文件:

<?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>launchJar</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
    </dependencies>

</project>

然后,我将在我的代码中使用这个API:

package com.stackoverflow.test;

import org.apache.commons.lang3.StringUtils;

public class Main {

    public static void main(String[] args) {
        System.out.println(StringUtils.upperCase("Hello World !"));
    }
}

一旦我生成了Jar文件(使用mvn package),并执行与之前相同的命令,我就会遇到错误:

java -cp target/myApp.jar com.stackoverflow.test.Main

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils at com.stackoverflow.test.Main.main(Main.java:8)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang3.StringUtils
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 1 more

唯一使其工作的方法是将新的依赖项添加到类路径中,以便运行应用程序。在我的示例中,使用Maven,commons-lang3 依赖项位于:~/.m2/repository/org/apache/commons/commons-lang3/3.9/commons-lang3-3.9.jar

为了使我的应用程序运行,我执行:

java -cp ~/.m2/repository/org/apache/commons/commons-lang3/3.9/commons-lang3-3.9.jar:target/myApp.jar com.stackoverflow.test.Main

注意:

  • 要运行应用程序,类路径的顺序很重要(在我的Jar文件之前是 commons-lang)。
  • 在Unix/Linux上,分隔不同的Jar文件的字符是:。在Windows上,请使用;

但是,如果我有很多依赖项,我需要手动提供它们吗?幸运的是,不需要 如何从包中生成JAR文件?

使用Maven,您可以使用一个新的插件,创建所谓的“fat jar”或“带有依赖关系的jar”。要这样做,只需更新您的POM以添加一个新的插件:

...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.1.1</version>

            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>

            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>

        </plugin>
    </plugins>
</build>
...

然后,使用mvn package您会得到一个新的Jar文件,名为:myApp-with-dependencies.jar
要运行它,执行:

java -cp target/myApp-jar-with-dependencies.jar com.stackoverflow.test.Main

您还可以自定义此插件,以自动添加一个MainClass,并创建一个“可运行的Jar”。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.1.1</version>

    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
            <manifest>
                <mainClass>com.stackoverflow.test.Main</mainClass>
            </manifest>
        </archive>
    </configuration>

    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>

</plugin>

然后,只需运行:


<details>
<summary>英文:</summary>

Unfortunately, it is not as easy as it sounds... To run a Jar, you need to have:
 
 - The jar you want to run. In your case, this is the Jar generated from your IDE command
 - A classpath, with all the dependencies. Usually, those dependencies are managed by your IDE, which is the reason why you can run your app with the IDE. But when you generate a JAR, with Maven for instance, then you no longer have your IDE managing the dependencies for you.

So let&#39;s say you have a basic application with Maven, with NO dependencies, you could do the following:

package com.stackoverflow.test;
public class Main {

public static void main(String[] args) {
    System.out.println(&quot;Hello World !&quot;);
}

}

Then, to generate the JAR, you run `man package`. To run it, do the following (no need for manifest file):

java -cp target/myApp.jar com.stackoverflow.test.Main


Here, you can see the &quot;-cp&quot; option, which instructs the JVM to load a JAR, in our case, located in target and named myApp.jar, and execute the main method inside the class `com.stackoverflow.test.Main`.

Easy right ?

But then, things get more complicated when you start having dependencies. In my following example, I&#39;ll assume I have a dependency with a famous library. I&#39;ll update my POM accordingly:

<?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&quot;>
<modelVersion>4.0.0</modelVersion>

&lt;groupId&gt;org.example&lt;/groupId&gt;
&lt;artifactId&gt;launchJar&lt;/artifactId&gt;
&lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;

&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.apache.commons&lt;/groupId&gt;
        &lt;artifactId&gt;commons-lang3&lt;/artifactId&gt;
        &lt;version&gt;3.9&lt;/version&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;

</project>

And then, I&#39;ll use this API in my code:

package com.stackoverflow.test;

import org.apache.commons.lang3.StringUtils;

public class Main {

public static void main(String[] args) {
    System.out.println(StringUtils.upperCase(&quot;Hello World !&quot;));
}

}

Once I generated the Jar (`mvn package`) and execute the same command as before, I have your error:

java -cp target/myApp.jar com.stackoverflow.test.Main


&gt; Exception in thread &quot;main&quot; java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils at com.stackoverflow.test.Main.main(Main.java:8)&lt;br/&gt;
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang3.StringUtils&lt;br/&gt;
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)&lt;br/&gt;
        at java.lang.ClassLoader.loadClass(ClassLoader.java:418)&lt;br/&gt;
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)&lt;br/&gt;
        at java.lang.ClassLoader.loadClass(ClassLoader.java:351)&lt;br/&gt;
        ... 1 more&lt;br/&gt;

The only way to get it to work is by adding my new dependencies to the classpath, in order to run the application. With maven, in my example, the `commons-lang3` dependencies is located in: `~/.m2/repository/org/apache/commons/commons-lang3/3.9/commons-lang3-3.9.jar`.

In order for my application to run, I execute:

java -cp ~/.m2/repository/org/apache/commons/commons-lang3/3.9/commons-lang3-3.9.jar:target/myApp.jar com.stackoverflow.test.Main

Note: 
 - To run the application, the classpath order is important (commons-lang before my Jar)
 - On Unix/Linux, to separate different JARs, the character is `: `. On windows, use `;`

But then, what happens if I have lots of dependencies, will I need to provide them manually ? Fortunately, no :D

With Maven, you can use a new plugin, which creates a so-called &quot;fat jar&quot;, or &quot;jar with dependencies&quot;. To do so, just update your POM to add a new plugin:

...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>

            &lt;configuration&gt;
                &lt;descriptorRefs&gt;
                    &lt;descriptorRef&gt;jar-with-dependencies&lt;/descriptorRef&gt;
                &lt;/descriptorRefs&gt;
            &lt;/configuration&gt;

            &lt;executions&gt;
                &lt;execution&gt;
                    &lt;id&gt;make-assembly&lt;/id&gt;
                    &lt;phase&gt;package&lt;/phase&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;single&lt;/goal&gt;
                    &lt;/goals&gt;
                &lt;/execution&gt;
            &lt;/executions&gt;

        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;

...


Then, with `man package` you have a new JAR created, called: myApp-with-dependencies.jar.
To run it, execute:

java -cp target/myApp-jar-with-dependencies.jar com.stackoverflow.test.Main


You could also customize this plugin to automatically add a MainClass and have a &quot;runnable Jar&quot;.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>

            &lt;configuration&gt;
                &lt;descriptorRefs&gt;
                    &lt;descriptorRef&gt;jar-with-dependencies&lt;/descriptorRef&gt;
                &lt;/descriptorRefs&gt;
                &lt;archive&gt;
                    &lt;manifest&gt;
                        &lt;mainClass&gt;com.stackoverflow.test.Main&lt;/mainClass&gt;
                    &lt;/manifest&gt;
                &lt;/archive&gt;
            &lt;/configuration&gt;

            &lt;executions&gt;
                &lt;execution&gt;
                    &lt;id&gt;make-assembly&lt;/id&gt;
                    &lt;phase&gt;package&lt;/phase&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;single&lt;/goal&gt;
                    &lt;/goals&gt;
                &lt;/execution&gt;
            &lt;/executions&gt;

        &lt;/plugin&gt;

And then, just run:

java -jar target/myApp-jar-with-dependencies.jar


</details>



huangapple
  • 本文由 发表于 2020年7月27日 18:52:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/63113793.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定