前提

  Maven可以使用mvn package指令对项目进行打包,如果使用Java -jar xxx.jar执行运行jar文件,会出现"no main manifest attribute, in xxx.jar"(没有设置Main-Class)、ClassNotFoundException(找不到依赖包)等错误。

  要想jar包能直接通过java -jar xxx.jar运行,需要满足:

  1、在jar包中的META-INF/MANIFEST.MF中指定Main-Class,这样才能确定程序的入口在哪里;

  2、要能加载到依赖包。

搭建示例项目

  1、新建Maven工程

  

maven java -jar maven java jar包_Maven

  2、编辑pom.xml文件

1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>org.example</groupId>
 8     <artifactId>test-mvn-package</artifactId>
 9     <version>1.0-SNAPSHOT</version>
10 
11     <dependencies>
12         <dependency>
13             <groupId>cn.hutool</groupId>
14             <artifactId>hutool-all</artifactId>
15             <version>5.3.7</version>
16         </dependency>
17     </dependencies>
18 </project>

  3、编辑主类MyMain.java

1 public class MyMain {
 2 
 3     public static void main(String[] args) {
 4         System.out.println("===========程 序 启 动===========");
 5 
 6         // 当前时间字符串,格式:yyyy-MM-dd HH:mm:ss
 7         // DateUtil 第三方jar包中的类
 8         String now = DateUtil.now();
 9         System.out.println("当前时间:" + now);
10 
11         System.out.println("===========程 序 关 闭===========");
12     }
13 }

  4、测试,运行主方法,效果如下:

    

maven java -jar maven java jar包_Java_02

  5、直接mvn package,打包后,运行jar包

    运行方法一:java -jar test-mvn-package-1.0-SNAPSHOT.jar

    

maven java -jar maven java jar包_Java_03

    运行方法二(指定主类):java -cp test-mvn-package-1.0-SNAPSHOT.jar com.test.api.MyMain

    

maven java -jar maven java jar包_maven java -jar_04

    均无法直接运行

项目打包

  使用Maven有以下几种方法可以生成能直接运行的jar包,可以根据需要选择一种合适的方法。

方法一:使用maven-jar-plugin和maven-dependency-plugin插件打包

  1、在pom.xml中配置:

1 <build>
 2     <plugins>
 3 
 4         <!-- 使用maven-jar-plugin和maven-dependency-plugin插件打包 -->
 5         <plugin>
 6             <groupId>org.apache.maven.plugins</groupId>
 7             <artifactId>maven-jar-plugin</artifactId>
 8             <version>3.1.0</version>
 9             <configuration>
10                 <archive>
11                     <manifest>
12                         <addClasspath>true</addClasspath>
13                         <classpathPrefix>lib/</classpathPrefix>
14                         <mainClass>com.test.api.MyMain</mainClass>
15                     </manifest>
16                 </archive>
17             </configuration>
18         </plugin>
19         <plugin>
20             <groupId>org.apache.maven.plugins</groupId>
21             <artifactId>maven-dependency-plugin</artifactId>
22             <version>3.1.1</version>
23             <executions>
24                 <execution>
25                     <id>copy-dependencies</id>
26                     <phase>package</phase>
27                     <goals>
28                         <goal>copy-dependencies</goal>
29                     </goals>
30                     <configuration>
31                         <outputDirectory>${project.build.directory}/lib</outputDirectory>
32                     </configuration>
33                 </execution>
34             </executions>
35         </plugin>
36 
37     </plugins>
38 </build>

    说明:

    maven-jar-plugin用于生成META-INF/MANIFEST.MF文件的部分内容,com.xx.Main指定MANIFEST.MF中的Main-Class,true会在MANIFEST.MF加上Class-Path项并配置依赖包,lib/指定依赖包所在目录。

    只是生成MANIFEST.MF文件还不够,maven-dependency-plugin插件用于将依赖包拷贝到${project.build.directory}/lib指定的位置,即lib目录下。

  2、使用maven命令:mvn clean package 打包

  3、target目录内容如下,多了lib目录

    

maven java -jar maven java jar包_Java_05

    反编译jar包,MANIFEST.MF文件内容如下:

    

maven java -jar maven java jar包_jar_06

  4、使用命令:java -jar test-mvn-package-1.0-SNAPSHOT.jar,可以直接运行

    

maven java -jar maven java jar包_Java_07

方法二:使用maven-assembly-plugin插件打包

  1、在pom.xml中配置:

1 <build>
 2     <plugins>
 3 
 4         <!-- 使用maven-assembly-plugin插件打包 -->
 5         <plugin>
 6             <groupId>org.apache.maven.plugins</groupId>
 7             <artifactId>maven-assembly-plugin</artifactId>
 8             <version>3.2.0</version>
 9             <configuration>
10                 <archive>
11                     <manifest>
12                         <mainClass>com.test.api.MyHttpRequest</mainClass>
13                     </manifest>
14                 </archive>
15                 <descriptorRefs>
16                     <descriptorRef>jar-with-dependencies</descriptorRef>
17                 </descriptorRefs>
18             </configuration>
19             <executions>
20                 <execution>
21                     <id>make-assembly</id>
22                     <phase>package</phase>
23                     <goals>
24                         <goal>single</goal>
25                     </goals>
26                 </execution>
27             </executions>
28         </plugin>
29 
30     </plugins>
31 </build>

  2、使用maven命令:mvn clean package 打包

  3、target目录内容如下,多了test-mvn-package-1.0-SNAPSHOT-jar-with-dependencies.jar包

    

maven java -jar maven java jar包_maven java -jar_08

    反编译jar包,test-mvn-package-1.0-SNAPSHOT-jar-with-dependencies.jar内容如下:

    

maven java -jar maven java jar包_maven java -jar_09

    可以看到其中把第三方包的内容放到新的jar包中了

    不过,如果项目中用到hutool-all第三方包,用这种方式打出来的包运行时可能会出错,但实验中没有出现这种情况。项目中最好使用maven依赖源包

  4、使用命令:java -jar test-mvn-package-1.0-SNAPSHOT.jar,无法运行

  5、使用命令:java -jar test-mvn-package-1.0-SNAPSHOT-jar-with-dependencies.jar,可以直接运行

    

maven java -jar maven java jar包_Maven_10

方法三:使用maven-shade-plugin插件打包

  1、在pom.xml中配置:

1 <build>
 2     <plugins>
 3 
 4         <!-- 使用maven-shade-plugin插件打包 -->
 5         <plugin>
 6             <groupId>org.apache.maven.plugins</groupId>
 7             <artifactId>maven-shade-plugin</artifactId>
 8             <version>3.2.3</version>
 9             <configuration>
10                 <createDependencyReducedPom>false</createDependencyReducedPom>
11             </configuration>
12             <executions>
13                 <execution>
14                     <phase>package</phase>
15                     <goals>
16                         <goal>shade</goal>
17                     </goals>
18                     <configuration>
19                         <transformers>
20                             <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
21                                 <mainClass>com.test.api.MyMain</mainClass>
22                             </transformer>
23                         </transformers>
24                     </configuration>
25                 </execution>
26             </executions>
27             </plugin>
28 
29     </plugins>
30 </build>

  2、使用maven命令:mvn clean package 打包 

  3、target目录内容如下,多了original-test-mvn-package-1.0-SNAPSHOT.jar包

    

maven java -jar maven java jar包_Java_11

    反编译jar包,test-mvn-package-1.0-SNAPSHOT.jar内容如下:

    

maven java -jar maven java jar包_maven java -jar_12

    可以看到其中把第三方包的内容放到新的jar包中了

    不过,如果项目中用到hutool-all第三方包,用这种方式打出来的包运行时可能会出错,但实验中没有出现这种情况。项目中最好使用maven依赖源包

  4、使用命令:java -jar test-mvn-package-1.0-SNAPSHOT.jar

    

maven java -jar maven java jar包_Java_13