前提
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工程
2、编辑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>test-mvn-package</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>
</dependencies>
</project>
3、编辑主类MyMain.java
public class MyMain {
public static void main(String[] args) {
System.out.println("===========程 序 启 动===========");
// 当前时间字符串,格式:yyyy-MM-dd HH:mm:ss
// DateUtil 第三方jar包中的类
String now = DateUtil.now();
System.out.println("当前时间:" + now);
System.out.println("===========程 序 关 闭===========");
}
}
4、测试,运行主方法,效果如下:
5、直接mvn package,打包后,运行jar包
运行方法一:java -jar test-mvn-package-1.0-SNAPSHOT.jar
运行方法二(指定主类):java -cp test-mvn-package-1.0-SNAPSHOT.jar com.test.api.MyMain
项目打包
使用Maven有以下几种方法可以生成能直接运行的jar包,可以根据需要选择一种合适的方法。
方法一:使用maven-jar-plugin和maven-dependency-plugin插件打包
<build>
<plugins>
<!-- 使用maven-jar-plugin和maven-dependency-plugin插件打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.test.api.MyMain</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</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目录
反编译jar包,MANIFEST.MF文件内容如下:
4、使用命令:java -jar test-mvn-package-1.0-SNAPSHOT.jar,可以直接运行
方法二:使用maven-assembly-plugin插件打包
1、在pom.xml中配置:
<build>
<plugins>
<!-- 使用maven-assembly-plugin插件打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.test.api.MyHttpRequest</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>
</plugins>
</build>
2、使用maven命令:mvn clean package 打包
3、target目录内容如下,多了test-mvn-package-1.0-SNAPSHOT-jar-with-dependencies.jar包
反编译jar包,test-mvn-package-1.0-SNAPSHOT-jar-with-dependencies.jar内容如下:
可以看到其中把第三方包的内容放到新的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-shade-plugin插件打包
1、在pom.xml中配置:
<build>
<plugins>
<!-- 使用maven-shade-plugin插件打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.test.api.MyMain</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
2、使用maven命令:mvn clean package 打包
3、target目录内容如下,多了original-test-mvn-package-1.0-SNAPSHOT.jar包
反编译jar包,test-mvn-package-1.0-SNAPSHOT.jar内容如下:
可以看到其中把第三方包的内容放到新的jar包中了
不过,如果项目中用到hutool-all第三方包,用这种方式打出来的包运行时可能会出错,但实验中没有出现这种情况。项目中最好使用maven依赖源包
4、使用命令:java -jar test-mvn-package-1.0-SNAPSHOT.jar