英文:
How to generate jar file from package?
问题
我有以下项目,我正在尝试从中生成jar文件。
我尝试了许多方法,但无法正确生成jar文件,我认为问题在于文件夹的结构,我还必须包含.xlsx文件,因为它是我程序的一部分。
当我尝试进行"clean and build"时,它会生成.jar文件,但是当我尝试运行它时,我会收到一个错误消息。
我还尝试过在Manifest.txt中手动指定主类并进行编译。
错误:找不到或加载主类NewJFrame
原因:java.lang.ClassNotFoundException: NewJFrame
我应该遵循哪些正确的步骤?
我提到"NewJFrame"是包含主类的类。
Pom的结构如下:
英文:
I have the following project, I am trying to generate jar file from it.
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 :
答案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.
<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>
答案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上,请使用;
。
但是,如果我有很多依赖项,我需要手动提供它们吗?幸运的是,不需要
使用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'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("Hello World !");
}
}
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 "-cp" 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'll assume I have a dependency with a famous library. I'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">
<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>
And then, I'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("Hello World !"));
}
}
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
> Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils at com.stackoverflow.test.Main.main(Main.java:8)<br/>
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang3.StringUtils<br/>
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)<br/>
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)<br/>
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)<br/>
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)<br/>
... 1 more<br/>
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 "fat jar", or "jar with dependencies". 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>
<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>
...
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 "runnable 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>
And then, just run:
java -jar target/myApp-jar-with-dependencies.jar
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论