Maven打包所有依赖到一个可执行jar中遇到的问题
需求
普通的Maven Java项目(非Springboot项目),需要打包成一个jar包(包含所有的第三方依赖jar包),能够放在服务器上单独运行。
遇到的问题
找不到主类
大家都知道,如果使用常见的maven-jar-plugin打包,只能将自己项目里的源码编译打包,不会包含第三方的jar包。
如果该项目没有第三方依赖包,则可以通过maven-jar-plugin打包,直接执行打好的jar包(java -jar xxx.jar),可能会遇到找不到主类的情况,可以通过下面的方式解决:指定主类
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.xxx.AppMain</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
注意:
META-INF文件夹是MANIFEST.MF文件的主页。 此文件包含有关JAR内容的元数据。
JAR包中的/META-INF/MANIFEST.MF元数据文件必须包含Main-Class(主类)信息。(工程里的src/META-INF/MANIFEST.MF)
项目所有的依赖都必须在Classpath中,其可以通过 MANIFEST.MF 指定或者隐式设置。
打包时没有包含第三方依赖
如果该项目有第三方依赖包,通过上面的方式打包,是不会包含第三方依赖的,直接运行生成的jar包会出错(相关依赖不存在)。
想要打包时包含第三方依赖,又可以分两种情况:
情况1
打包成可执行jar文件,但是将所有依赖(包括外部依赖)单独打包到另外一个指定文件夹下,通过指定Class-Path的方式关联。
- 打包依赖到指定文件夹
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</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>
关于Maven dependency plugin可以参考我的另外一篇博客,有详细介绍:
- 指定启动入口,并关联依赖
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<!-- 是否绑定依赖,将外部jar包依赖加入到classPath中 -->
<addClasspath>true</addClasspath>
<!-- 依赖前缀,与之前设置的文件夹路径要匹配 -->
<classpathPrefix>lib/</classpathPrefix>
<!-- 主函数的入口 -->
<mainClass>com.xxx.AppMain</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
配置好后,可以通过下面的命令编译打包:mvn clean pacakge -DskipTests=true
注意,复杂情况下,classpath需要在运行时指定,如 java -cp …
情况2
将整个工程打成一个可执行jar包,包含所有的依赖。
需要通过maven-assembly-plugin插件来打包,可以实现该需求。
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.xxx.AppMain</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
配置好后,可以通过下面的命令编译打包:mvn assembly:assembly执行成功后会在target文件夹下多出一个以-jar-with-dependencies结尾的jar包. 这个jar包就包含了项目所依赖的所有jar的class。
扩展问题
不希望依赖的jar包变成class
可以通过修改插件的配置做到
- 在本地maven仓库里找到maven-assembly-plugin
cd ~/.m2/repository/org/apache/maven/plugins/maven-assembly-plugin/
- 进入打包时运行使用的版本里,如2.2-beta-5;
- 解压maven-assembly-plugin-2.2-beta-5.jar;
- 进入解压好的文件夹找到assemblies\jar-with-dependencies.xml,
把里面的UNPACK改成FALSE,保存即可; - 还原解压后的文件为jar包
例如,在~/.m2/repository/org/apache/maven/plugins/maven-assembly-plugin/2.2-beta-5 路径里,执行下面的命令
jar cvfm maven-assembly-plugin-2.2-beta-5.jar maven-assembly-plugin-2.2-beta-5/META-INF/MANIFEST.MF -C maven-assembly-plugin-2.2-beta-5 .
- 再次使用
mvn assembly:assembly打包,编译好的以-jar-with-dependencies结尾的jar包. 这个jar包就包含了项目所依赖的所有jar文件,不再是class;
项目里多个主类,如何动态指定
可以通过自定义property属性,在执行maven命令时,动态指定来实现,配置如下:
例如,main.class 则为自定义的;
<properties>
<main.class>com.xxx.AppMain</main.class>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
运行maven命令时,动态指定:
mvn -Dmain.class=com.xxx.AppMain2 assembly:assembly
总结
到此这篇关于Maven打包所有依赖到一个可执行jar中遇到的问题的文章就介绍到这了,更多相关Maven打包依赖到jar内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Java文件字符输入流FileReader读取txt文件乱码的解决
这篇文章主要介绍了Java文件字符输入流FileReader读取txt文件乱码的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-09-09
SpringBoot中Token登录授权、续期和主动终止的方案流程分析
SpringBoot项目中,基于Token的登录授权方案主要有两种:利用Session/Cookie和JWT,Cookie/Session方案有状态,不适合分布式架构,而JWT虽无状态,但存在过期时间不可强制失效、一次性等缺点,本文介绍SpringBoot中Token登录授权、续期和主动终止的方案,感兴趣的朋友一起看看吧2024-09-09
Java+WebSocket实现简单实时双人协同pk答题系统
在实时互动应用中,实现流畅的多人协同对战功能是一大挑战,WebSocket技术,以其全双工通信能力,提供了解决方案,本文我们就来使用WebSocket实现简单实时双人协同pk答题系统吧2025-06-06
Java中BigDecimal的舍入模式解析(RoundingMode)
这篇文章主要介绍了Java中BigDecimal的舍入模式解析(RoundingMode),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-06-06


最新评论