Maven的打包插件
- maven-jar-plugin,默認的打包插件,用來打普通的project JAR包
- maven-shade-plugin,用來打可執行JAR包,也就是所謂的fat JAR包
- maven-assembly-plugin,支持自定義的打包結構,也可以定制依賴項等
maven-jar-plugin官方地址:https://maven.apache.org/plugins/maven-jar-plugin/
maven-dependency-plugin官方地址:https://maven.apache.org/plugins/maven-dependency-plugin/index.html
使用maven-jar-plugin和maven-dependency-plugin插件打包
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.6</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.xxg.Main</mainClass> </manifest> </archive> </configuration> </plugin> <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> </plugins> </build>
maven-jar-plugin用於生成META-INF/MANIFEST.MF文件的部分內容
- <mainClass>com.xxg.Main</mainClass>指定MANIFEST.MF中的Main-Class
- <addClasspath>true</addClasspath>會在MANIFEST.MF加上Class-Path項並配置依賴包
- <classpathPrefix>lib/</classpathPrefix>指定依賴包所在目錄
MANIFEST.MF文件片段
Class-Path: lib/commons-logging-1.2.jar lib/commons-io-2.4.jar Main-Class: com.xxg.Main
只是生成MANIFEST.MF文件還不夠,maven-dependency-plugin插件用於將依賴包拷貝到<outputDirectory>${project.build.directory}/lib</outputDirectory>指定的位置,即lib目錄下
指定了Main-Class,有了依賴包,那么就可以直接通過java -jar xxx.jar運行jar包
這種方式生成jar包有個缺點,就是生成的jar包太多不便於管理,下面兩種方式只生成一個jar文件,包含項目本身的代碼、資源以及所有的依賴包
maven-assembly-plugin 自定義打包插件
官方地址:https://maven.apache.org/plugins/maven-assembly-plugin/
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>${maven-assembly-plugin.version}<version> <executions> <execution> <id>make-assembly</id> <!-- 綁定到package生命周期 --> <phase>package</phase> <goals> <!-- 只運行一次 --> <goal>single</goal> </goals> </execution> </executions> <configuration> <descriptors> <!-- 配置描述符文件 --> <descriptor>src/main/assembly/assembly.xml</descriptor> </descriptors> <skipAssembly>${assemmbly.skip}</skipAssembly> <!-- 打包后不帶該后綴 --> <appendAssemblyId>false</appendAssemblyId> <!-- 也可以使用Maven預配置的描述符 <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> --> <!--歸檔--> <archive> <!--清單--> <manifest> <mainClass>cn.techny.start.Appliation</mainClass> </manifest> </archive> <!--打包時的名稱,如果沒有設置,打包后的包名是artifactId與version拼接的結果-->
<finalName>pdms</finalName> </configuration> </plugin> </plugins> </build>
若項目中用到spring Framework,用這種方式打出來的包運行時會出錯
要真正達到自定義打包的效果,就需要自己寫描述符文件,格式為XML
assembly官方地址:http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html
<assembly > <id>assembly</id> <!--支持 zip,tar,tar.gz,tar.bz2,jar,dir,war 等 --> <formats> <format>tar.gz</format> </formats> <!--在tar.gz壓縮包下是否生成和項目名相同的根目錄--> <includeBaseDirectory>true</includeBaseDirectory> <fileSets> <!--fileSet把某些目錄指定要打包的文件並指定輸出文件夾--> <fileSet> <directory>src/main/bin</directory> <includes> <include>*.sh</include> </includes> <outputDirectory>bin</outputDirectory> <!--fileMode是linux的rwx對應421--> <fileMode>0755</fileMode> </fileSet> <fileSet> <directory>src/main/conf</directory> <outputDirectory>conf</outputDirectory> </fileSet> <fileSet> <directory>src/main/sql</directory> <includes> <include>*.sql</include> </includes> <outputDirectory>sql</outputDirectory> </fileSet> <fileSet> <directory>target/classes/</directory> <includes> <include>*.properties</include> <include>*.xml</include> <include>*.txt</include> </includes> <outputDirectory>conf</outputDirectory> </fileSet> </fileSets> <files> <file> <source>target/${project.artifactId}-${project.version}.jar</source> <outputDirectory>.</outputDirectory> </file> </files> <dependencySets> <dependencySet> <!--是否把本項目添加到依賴文件夾下--> <useProjectArtifact>true</useProjectArtifact> <unpack>false</unpack> <!--打包時的scope,如果不配置默認就是runtime--> <scope>runtime</scope> <outputDirectory>lib</outputDirectory> <!--映射出來的文件--> <outputFilenameMapping></outputFilenameMapping> </dependencySet> </dependencySets> </assembly>
id與format
- formats是assembly插件支持的打包文件格式,有zip、tar、tar.gz、tar.bz2、jar、war
- 可以同時定義多個format
- id則是添加到打包文件名的標識符,用來做后綴
- 也就是說,如果按上面的配置,生成的文件就是a r t i f a c t I d − {artifactId}-artifactId−{version}-assembly.tar.gz
fileSets/fileSet
用來設置一組文件在打包時的屬性。
directory
源目錄的路徑
includes/excludes
設定包含或排除哪些文件,支持通配符
fileMode
指定該目錄下的文件屬性,采用Unix八進制描述法,默認值是0644
outputDirectory
生成目錄的路徑
files/file
與fileSets大致相同,不過是指定單個文件,並且還可以通過destName屬性來設置與源文件不同的名稱
dependencySets/dependencySet
用來設置工程依賴文件在打包時的屬性。也與fileSets大致相同,不過還有兩個特殊的配置:
- unpack:布爾值,false表示將依賴以原來的JAR形式打包,true則表示將依賴解成*.class文件的目錄結構打包。
- scope:表示符合哪個作用范圍的依賴會被打包進去。compile與provided都不用管,一般是寫runtime。
用maven-shade-plugin插件打包
maven-shade-plugin官方地址:https://maven.apache.org/plugins/maven-shade-plugin/index.html
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.xxg.Main</mainClass> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.handlers</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>META-INF/spring.schemas</resource> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build>
配置完成后,執行mvn package即可打包
如果項目中用到了Spring Framework,將依賴打到一個jar包中,運行時會出現讀取XML schema文件出錯
原因是Spring Framework的多個jar包中包含相同的文件spring.handlers和spring.schemas,如果生成一個jar包會互相覆蓋
為了避免互相影響,使用AppendingTransformer來對文件內容追加合並