Maven打包所有依賴到一個可執(zhí)行jar中遇到的問題
需求
普通的Maven Java項目(非Springboot項目),需要打包成一個jar包(包含所有的第三方依賴jar包),能夠放在服務器上單獨運行。
遇到的問題
找不到主類
大家都知道,如果使用常見的maven-jar-plugin
打包,只能將自己項目里的源碼編譯打包,不會包含第三方的jar包。
如果該項目沒有第三方依賴包,則可以通過maven-jar-plugin
打包,直接執(zhí)行打好的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文件的主頁。 此文件包含有關(guān)JAR內(nèi)容的元數(shù)據(jù)。
JAR包中的/META-INF/MANIFEST.MF元數(shù)據(jù)文件必須包含Main-Class(主類)信息。(工程里的src/META-INF/MANIFEST.MF)
項目所有的依賴都必須在Classpath中,其可以通過 MANIFEST.MF 指定或者隱式設(shè)置。
打包時沒有包含第三方依賴
如果該項目有第三方依賴包,通過上面的方式打包,是不會包含第三方依賴的,直接運行生成的jar包會出錯(相關(guān)依賴不存在)。
想要打包時包含第三方依賴,又可以分兩種情況:
情況1
打包成可執(zhí)行jar文件,但是將所有依賴(包括外部依賴)單獨打包到另外一個指定文件夾下,通過指定Class-Path的方式關(guān)聯(lián)。
- 打包依賴到指定文件夾
<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>
關(guān)于Maven dependency plugin可以參考我的另外一篇博客,有詳細介紹:
- 指定啟動入口,并關(guān)聯(lián)依賴
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <!-- 是否綁定依賴,將外部jar包依賴加入到classPath中 --> <addClasspath>true</addClasspath> <!-- 依賴前綴,與之前設(shè)置的文件夾路徑要匹配 --> <classpathPrefix>lib/</classpathPrefix> <!-- 主函數(shù)的入口 --> <mainClass>com.xxx.AppMain</mainClass> </manifest> </archive> </configuration> </plugin>
配置好后,可以通過下面的命令編譯打包:mvn clean pacakge -DskipTests=true
注意,復雜情況下,classpath需要在運行時指定,如 java -cp …
情況2
將整個工程打成一個可執(zhí)行jar包,包含所有的依賴。
需要通過maven-assembly-plugin
插件來打包,可以實現(xiàn)該需求。
<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
執(zhí)行成功后會在target文件夾下多出一個以-jar-with-dependencies結(jié)尾的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 路徑里,執(zhí)行下面的命令
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結(jié)尾的jar包. 這個jar包就包含了項目所依賴的所有jar文件,不再是class;
項目里多個主類,如何動態(tài)指定
可以通過自定義property屬性,在執(zhí)行maven命令時,動態(tài)指定來實現(xiàn),配置如下:
例如,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命令時,動態(tài)指定:
mvn -Dmain.class=com.xxx.AppMain2 assembly:assembly
總結(jié)
到此這篇關(guān)于Maven打包所有依賴到一個可執(zhí)行jar中遇到的問題的文章就介紹到這了,更多相關(guān)Maven打包依賴到j(luò)ar內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何基于LoadingCache實現(xiàn)Java本地緩存
這篇文章主要介紹了如何基于LoadingCache實現(xiàn)Java本地緩存,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-12-12Spring?Security權(quán)限管理小結(jié)
SpringSecurity是一個權(quán)限管理框架,核心是認證和授權(quán),前面已經(jīng)系統(tǒng)的給大家介紹過了認證的實現(xiàn)和源碼分析,本文重點來介紹下權(quán)限管理,需要的朋友可以參考下2022-08-08Java加載properties文件實現(xiàn)方式詳解
這篇文章主要介紹了Java加載properties文件實現(xiàn)方式詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-07-07JavaWeb Spring注解Annotation深入學習
這篇文章主要為大家詳細介紹了JavaWeb Spring注解Annotation,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09