一、需求
打一個zip包,包含如下:
bin為程序腳本,啟動和停止
lib為依賴包
根目錄下為配置文件和項目jar包
二、知識儲備
2.1、插件了解
plugin | function |
---|---|
maven-jar-plugin | maven 默認打包插件,用來創建 project jar,負責將應用程序打包成可執行的jar文件 可在此處設置主類,manifest,排除對應的配置文件等 |
maven-shade-plugin | 用來打可執行包,executable(fat) jar |
maven-assembly-plugin | 支持定制化打包方式,負責將整個項目按照自定義的目錄結構打成最終的壓縮包,方便實際部署 可在此處設置打包拷貝路徑,配置,以及打包好的jar文件等 |
三、配置
1、pom配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.6</version> <configuration> <archive> <manifest> <mainClass>com.jd.bt.ZuulApplication</mainClass> <!-- to create a class path to your dependecies you have to fill true in this field --> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> </manifest> <manifestEntries> <Class-Path>./</Class-Path> </manifestEntries> </archive> <excludes> <!--注意從編譯結果目錄開始算目錄結構--> <exclude>/*.yml</exclude> <exclude>/*.properties</exclude> <exclude>/*.xml</exclude> </excludes> </configuration> </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <!-- not append assembly id in release file name --> <appendAssemblyId>false</appendAssemblyId> <descriptors> <descriptor>src/main/assembly/depolyment.xml</descriptor> </descriptors> </configuration> <executions> <execution> <id>dist</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin>
對於maven-jar-plugin配置
其中manifest的部分是核心,在可執行的jar文件中,打包后會在jar文件內的META-INF文件夾下,生成一個MANIFEST.MF文件,里面記錄了可執行文件的一些相關配置,比如像上面一段代碼中所配置的內容,這里面就配置了可執行jar文件未來讀取classpath的相對目錄位置在什么地方,以及引入的jar文件都有哪些,上面的配置就是classpath目錄是./
mainClass配置表示,哪個class作為程序的入口來執行
addClasspath配置表示,是否將依賴的classpath一起打包
classpathPrefix配置表示,依賴的classpath的前綴,也就是打包后生成的MANIFEST.MF文件里,引入的jar文件都會加上前綴,lib/,比如fastjson-1.2.7.jar,在mainfest文件里就會是lib/fastjson-1.2.7.jar
excludes配置表示,排除哪些文件夾不被打包進去
注意:其實maven-jar-plugin主要就是配置了MANIFEST.MF這個文件而已,就是讓可執行文件知道自己怎么執行,加載哪些文件執行的描述,剩下的工作交由maven-assembly-plugin來處理
對於maven-assembly-plugin配置
地址:http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html#class_unpackOptions
http://liugang594.iteye.com/blog/2093607
https://blog.csdn.net/u011955252/article/details/78927175
最終壓縮的文件格式,為zip,fileSets中配置了需要將那些文件打包到最終壓縮包中,
如配置文件包括了啟動腳本bin文件夾,里面放着shell的啟動腳本,相關的配置文件src/main/resources,里面放着整個程序提取的properties等相關的配置文件
最終可運行的jar文件,使用了${project.build.directory}變量,也就是通過maven-jar-plugin生成的那個jar文件
dependencySets里面配置了依賴庫最終輸出到lib文件夾下,與上面的maven-jar-plugin配置生成的manifest文件路徑相對應,這樣可運行jar就會按照manifest的路徑來找相應的文件進行加載
參看地址:https://blog.csdn.net/senpogml/article/details/52366518?locationNum=12
2、src/main/assembly/depolyment.xml配置
<?xml version="1.0" encoding="UTF-8"?> <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd"> <id>dist</id> <formats> <format>zip</format> </formats> <includeBaseDirectory>true</includeBaseDirectory> <fileSets> <fileSet> <directory>src/main/bin</directory> <outputDirectory>bin/</outputDirectory> </fileSet> <fileSet> <directory>src/main/resources</directory> <outputDirectory>/</outputDirectory> </fileSet> <fileSet> <directory>${project.build.directory}</directory> <outputDirectory>/</outputDirectory> <includes> <include>*.jar</include> </includes> </fileSet> </fileSets> <dependencySets> <dependencySet> <outputDirectory>lib</outputDirectory> <scope>runtime</scope> <excludes> <exclude>${groupId}:${artifactId}</exclude> </excludes> </dependencySet> </dependencySets> </assembly>
3、start.sh和stop.sh
start.sh
#!/bin/bash ARTIFACT_ID=jd-bt-microservice-gateway-zuul VERSION=0.0.1-SNAPSHOT main_jar=${ARTIFACT_ID}-${VERSION}.jar PIDS=`ps aux|grep ${main_jar} |grep -v "grep" |awk '{print $2}'` if [ ! -z "$PIDS" ]; then echo "${ARTIFACT_ID} already started!" echo "PID: $PIDS" exit 0; fi BIN_PATH="${JAVA_HOME}/bin" LOG_PATH="/Users/lihongxu/log/${ARTIFACT_ID}/" mkdir -p $LOG_PATH echo "ready start ${main_jar}"; nohup $BIN_PATH/java -server -Xms4096m -Xmx4096m -jar ../${main_jar} >$LOG_PATH/nohup.log 2>&1 & sleep 5 PIDS=`ps aux|grep ${main_jar} |grep -v "grep" |awk '{print $2}'` if [ ! -z "$PIDS" ]; then echo " ${ARTIFACT_ID} Started Successed,pid:${PIDS}" exit 0; else echo " ${ARTIFACT_ID} Started Failed" exit 1; fi
stop.sh
#!/bin/bash ARTIFACT_ID=jd-bt-microservice-gateway-zuul VERSION=0.0.1-SNAPSHOT main_jar=${ARTIFACT_ID}-${VERSION}.jar PIDS=`ps aux|grep ${main_jar} |grep -v "grep" |awk '{print $2}'` if [ ! -z "$PIDS" ]; then kill -9 "$PIDS" echo " ${ARTIFACT_ID} is stop !" echo " PID: $PIDS" exit 0; fi
四、java啟動
java -cp 和 -classpath 一樣,是指定類運行所依賴其他類的路徑,通常是類庫,jar包之類,需要全路徑到jar包,window上分號“;”,linux使用“:”
4.1、格式:
java -cp .;myClass.jar packname.mainclassname
表達式支持通配符,例如:
java -cp .;c:\classes01\myClass.jar;c:\classes02\*.jar packname.mainclassname
4.2、運行jar
java -jar myClass.jar
執行該命令時,會用到目錄META-INF\MANIFEST.MF文件,在該文件中,有一個叫Main-Class的參數,它說明了java -jar命令執行的類。
4.3、運行jar和cp
用maven導出的包中,如果沒有在pom文件中將依賴包打進去,是沒有依賴包。
1.打包時指定了主類,可以直接用java -jar xxx.jar。
2.打包是沒有指定主類,可以用java -cp xxx.jar 主類名稱(絕對路徑)。
3.要引用其他的jar包,可以用java -classpath $CLASSPATH:xxxx.jar 主類名稱(絕對路徑)。其中 -classpath 指定需要引入的類。
4.4、實例
下面基於pom和META-INF\MANIFEST.MF兩個文件的配置,進行了三種情況的測試:
pom.xml的build配置:

<build> <!--<finalName>test-1.0-SNAPSHOT</finalName>--> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <archive> <manifest> <mainClass>test.core.Core</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <!--下面是為了使用 mvn package命令,如果不加則使用mvn assembly--> <executions> <execution> <id>make-assemble</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
META-INF\MANIFEST.MF的內容:
Manifest-Version: 1.0
Main-Class: test.core.Core
1.pom中build指定mainClass 但是 META-INF\MANIFEST.MF文件中沒有指定Main-Class: test.core.Core
java -jar test-jar-with-dependencies.jar //執行成功
java -cp test-jar-with-dependencies.jar test.core.Core //執行失敗,提示jar中沒有主清單屬性
2.pom中build沒有指定mainClass 但是 META-INF\MANIFEST.MF文件中指定了Main-Class: test.core.Core
java -jar test-jar-with-dependencies.jar //執行失敗,提示jar中沒有主清單屬性
java -cp test-jar-with-dependencies.jar test.core.Core //執行成功
3.pom中build指定mainClass && META-INF\MANIFEST.MF文件中增加了Main-Class: test.core.Core
java -cp test-jar-with-dependencies.jar test.core.Core //執行成功
java -jar test-jar-with-dependencies.jar //執行成功