文章目錄

  • 1. 一般常見的打包方式如下(全量包FatJar)
  • 2. 增量包(ThinJar)


1. 一般常見的打包方式如下(全量包FatJar)

  • FatJar打包時,所有依賴的jar包會一併打包,並且打包好的jar可以直接使用java -jar執行,一般來説整個可執行jar包大約會有幾十上百兆不等。
<build>
    <plugins>
        <!-- 默認的打包插件,用來打普通的project JAR包 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                        <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
                    </manifest>
                </archive>
            </configuration>
            <executions>
                <execution>
                    <id>default-jar</id>
                    <phase>package</phase>
                    <configuration>
                        <excludes>
                            <exclude>config/**</exclude>
                            <exclude>*.yml</exclude>
                            <exclude>logback-spring.xml</exclude>
                            <exclude>banner.txt</exclude>
                        </excludes>
                        <classifier>assembly</classifier>
                    </configuration>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
                <execution>
                    <id>full-jar</id>
                    <phase>package</phase>
                    <configuration>
                        <classifier>full</classifier>
                    </configuration>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <!-- 將Spring Boot應用打包為可執行的jar或war文件 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>default</id>
                    <phase>package</phase>
                    <configuration>
                        <classifier>assembly</classifier>
                    </configuration>
                    <goals>
                        <goal>build-info</goal>
                        <goal>repackage</goal>
                    </goals>
                </execution>
                <execution>
                    <id>full-jar</id>
                    <phase>package</phase>
                    <configuration>
                        <classifier>full</classifier>
                    </configuration>
                    <goals>
                        <goal>build-info</goal>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <!-- 支持自定義的打包結構,也可以定製依賴項等,該項目的對應配置文件在src/assembly下 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
        </plugin>
    </plugins>
</build>

2. 增量包(ThinJar)

  • 相比於FatJar,ThinJar會將依賴的jar包拷貝到業務jar包外部,這樣業務jar包的大小會非常小,並且支持jar包或文件級別的升級
<profiles>
  <profile>
	  <!--標識符,用於給這個 Maven Profile 命名-->
	  <id>fat-jar</id>
	  <properties>
		  <packaging.type>jar</packaging.type>
	  </properties>
	  <activation>
		  <!--Profile 在沒有指定其它激活條件時,會自動激活,
		  Maven 會在構建時默認使用這個 Profile。
		  通常這種情況適用於應用程序的常規構建配置-->
		  <activeByDefault>true</activeByDefault>
	  </activation>

	  <build>
		  <plugins>
			  <!--這段配置主要是通過 maven-jar-plugin 插件生成 JAR 文件時的細節控制。
			  它定義了兩個執行目標:default-jar 和 full-jar,分別生成不同類型的 JAR 文件:
			 1、default-jar 生成一個名為 myproject-assembly.jar 的 JAR 文件,並排除了特定文件(如 config/**、.yml 文件等)。
			 通常用於構建一個輕量級的 JAR 文件,不包含不必要的配置文件(如 .yml 文件等)
			 2、full-jar 生成一個名為 myproject-full.jar 的完整 JAR 文件,包含所有依賴和文件
			 用於構建一個完整的 JAR 文件,通常包含所有的依賴和資源文件,適用於需要完整打包的場景
			  -->
			  <plugin>
				  <!--Maven 用來創建 JAR 文件的官方插件-->
				  <groupId>org.apache.maven.plugins</groupId>
				  <artifactId>maven-jar-plugin</artifactId>
				  <configuration>
					  <!--配置 JAR 文件的歸檔行為,主要是關於 MANIFEST.MF 文件的配置-->
					  <archive>
						  <!--用於配置 JAR 文件的 MANIFEST.MF 文件,這個文件存儲了 JAR 的元數據-->
						  <manifest>
							  <!--設置為 true 後,會自動將 JAR 的實現版本和實現標題等信息添加到 MANIFEST.MF 中-->
							  <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
							  <!--設置為 true 後,會將 JAR 的規範版本和規範標題等信息添加到 MANIFEST.MF 中-->
							  <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
						  </manifest>
					  </archive>
				  </configuration>
				  <!--執行配置-->
				  <executions>
					  <execution>
						  <!--執行步驟的唯一標識符-->
						  <id>default-jar</id>
						  <!--指定插件執行的生命週期階段,這裏是在 package 階段執行-->
						  <phase>package</phase>
						  <!--配置該執行的參數-->
						  <configuration>
							  <!--配置哪些文件或目錄不應該被包含在 JAR 文件中。這裏排除了 config/** 目錄、
							  所有 .yml 文件、logback-spring.xml 和 banner.txt 文件-->
							  <excludes>
								  <exclude>config/**</exclude>
								  <exclude>*.yml</exclude>
								  <exclude>logback-spring.xml</exclude>
								  <exclude>banner.txt</exclude>
							  </excludes>
							  <!--設置為 assembly,這意味着生成的 JAR 文件將被標記為
							   -assembly.jar。例如,構建過程中可能會生成一個名為 myproject-assembly.jar 的文件。-->
							  <classifier>assembly</classifier>
						  </configuration>
						  <!--指定該執行的目標,這裏是 jar,表示生成 JAR 文件-->
						  <goals>
							  <goal>jar</goal>
						  </goals>
					  </execution>
					  <!--full-jar 執行配置-->
					  <execution>
						  <id>full-jar</id>
						  <phase>package</phase>
						  <!--設置為 full,這意味着生成的 JAR 文件將被標記為 -full.jar。
						  例如,構建過程中可能會生成一個名為 myproject-full.jar 的文件。-->
						  <configuration>
							  <classifier>full</classifier>
						  </configuration>
						  <!--目標仍然是 jar,表示該執行也會生成一個 JAR 文件-->
						  <goals>
							  <goal>jar</goal>
						  </goals>
					  </execution>
				  </executions>
			  </plugin>
			  <plugin>
				  <!--通過 default 和 full-jar 兩個執行目標,生成了兩種分類符不同的 JAR 文件(-assembly.jar 和 -full.jar)-->
				  <!--Spring Boot 提供的官方 Maven 插件,用於支持 Spring Boot 應用程序的構建、打包和相關任務-->
				  <groupId>org.springframework.boot</groupId>
				  <artifactId>spring-boot-maven-plugin</artifactId>
				  <executions>
					  <!--定義了兩個執行目標,分別是 default 和 full-jar,均在 Maven 構建生命週期的 package 階段執行-->
					  <execution>
						  <!--標識此執行目標-->
						  <id>default</id>
						  <!--在打包階段運行該目標-->
						  <phase>package</phase>
						  <configuration>
							  <!--指定生成的 JAR 文件的分類符,這裏為 assembly,因此生成的文件名形如 project-assembly.jar-->
							  <classifier>assembly</classifier>
						  </configuration>
						  <goals>
							  <!--生成構建信息文件(如 build-info.properties),包括版本、構建時間等-->
							  <goal>build-info</goal>
							  <!--將項目重新打包為可執行的 JAR 文件(fat JAR),包含所有依賴和資源-->
							  <goal>repackage</goal>
						  </goals>
					  </execution>
					  <execution>
						  <!--標識此執行目標-->
						  <id>full-jar</id>
						  <!--在打包階段運行該目標-->
						  <phase>package</phase>
						  <configuration>
							  <!--設置分類符為 full,生成的文件名形如 project-full.jar-->
							  <classifier>full</classifier>
						  </configuration>
						  <goals>
							  <!--生成構建信息文件-->
							  <goal>build-info</goal>
							  <!--將項目重新打包為完整的可執行 JAR 文件-->
							  <goal>repackage</goal>
						  </goals>
					  </execution>
				  </executions>
			  </plugin>
			  <plugin>
				  <!--Maven 官方插件-->
				  <groupId>org.apache.maven.plugins</groupId>
				  <!--用於生成複雜的分發包,比如將 JAR 文件、配置文件、文檔等資源打包成 ZIP 或 TAR 文件-->
				  <artifactId>maven-assembly-plugin</artifactId>
			  </plugin>
		  </plugins>
	  </build>
  </profile>

  <profile>
	  <id>thin-jar</id>
	  <properties>
		  <packaging.type>jar</packaging.type>
	  </properties>
	  <build>
		  <plugins>
			  <plugin>
				  <groupId>org.apache.maven.plugins</groupId>
				  <artifactId>maven-jar-plugin</artifactId>
				  <version>3.1.2</version>
				  <configuration>
					  <archive>
						  <manifest>
							  <!--會將實現和規範版本的信息添加到 MANIFEST.MF 文件中-->
							  <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
							  <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
						  </manifest>
					  </archive>
					  <excludes>
						  <!--排除了 config/**(配置目錄)、.yml 文件、logback-spring.xml 和 banner.txt 文件-->
						  <exclude>config/**</exclude>
						  <exclude>*.yml</exclude>
						  <exclude>logback-spring.xml</exclude>
						  <exclude>banner.txt</exclude>
					  </excludes>
					  <!--設置為 bootapp,生成的 JAR 文件名會以 -bootapp.jar 結尾-->
					  <classifier>bootapp</classifier>
				  </configuration>

			  </plugin>

			  <plugin>
				  <!--將運行時類路徑信息寫入瘦 JAR 的 MANIFEST.MF 文件,屬性名為 Xdr-Thin-Classpath-->
				  <groupId>org.apache.maven.plugins</groupId>
				  <artifactId>maven-antrun-plugin</artifactId>
				  <version>3.0.0</version>
				  <executions>
					  <execution>
						  <id>write-classpath</id>
						  <phase>package</phase>
						  <configuration>
							  <target>
								  <!--引用 Maven 的運行時類路徑-->
								  <property name="runtime_classpath" refid="maven.runtime.classpath"/>
								  <!--目標文件為 -bootapp.jar-->
								  <jar destfile="${project.build.directory}/${project.artifactId}-${project.version}-bootapp.jar" update="true">
									  <manifest>
										  <attribute name="Xdr-Thin-Classpath" value="${runtime_classpath}"/>
									  </manifest>
								  </jar>
							  </target>
						  </configuration>
						  <goals>
							  <goal>run</goal>
						  </goals>
					  </execution>
				  </executions>
			  </plugin>
			  <plugin>
				  <groupId>org.springframework.boot</groupId>
				  <artifactId>spring-boot-maven-plugin</artifactId>
				  <configuration>
					  <!--指定無效的依賴項來避免打包實際的依賴文件-->
					  <includes>
						  <include>
							  <groupId>not.exists.groupId</groupId>
							  <artifactId>not.exists.artifactId</artifactId>
						  </include>
					  </includes>
				  </configuration>
				  <executions>
					  <execution>
						  <id>default</id>
						  <phase>package</phase>
						  <configuration>
							  <classifier>bootapp</classifier>
						  </configuration>
						  <goals>
							  <goal>build-info</goal>
							  <goal>repackage</goal>
						  </goals>
					  </execution>
				  </executions>
				  <dependencies>
					<!--引入自定義的打包格式-->
					<!--擴展spring boot maven plugin,重新制定可執行jar包的Launcher類-->
					<dependency>
						<groupId>com.xdr630</groupId>
						<artifactId>xdr-boot-thin-layout</artifactId>
						<version>0.0.1-SNAPSHOT</version>
					</dependency>
				  </dependencies>
			  </plugin>
			  <plugin>
				  <groupId>org.apache.maven.plugins</groupId>
				  <artifactId>maven-assembly-plugin</artifactId>
				  <version>3.1.1</version>
				  <executions>
					  <execution>
						  <phase>package</phase>
						  <goals>
							  <goal>single</goal>
						  </goals>
					  </execution>
				  </executions>
				  <configuration>
					  <descriptors>
						  <descriptor>src/assembly/assembly_thin.xml</descriptor>
					  </descriptors>
					  <outputDirectory>target</outputDirectory>
				  </configuration>
			  </plugin>
		  </plugins>
	  </build>
  </profile>

  <profile>
	  <id>war</id>
	  <properties>
		  <packaging.type>war</packaging.type>
	  </properties>

	  <dependencies>
		  <dependency>
			  <groupId>org.springframework.boot</groupId>
			  <artifactId>spring-boot-starter-tomcat</artifactId>
			  <scope>provided</scope>
		  </dependency>
	  </dependencies>

	  <build>
		  <finalName>myproject</finalName>

		  <plugins>
			  <plugin>
				  <groupId>org.apache.maven.plugins</groupId>
				  <artifactId>maven-war-plugin</artifactId>
				  <version>3.1.0</version>
				  <configuration>
					  <failOnMissingWebXml>false</failOnMissingWebXml>
					  <archive>
						  <manifestEntries>
							  <Dependencies>jdk.unsupported</Dependencies>
						  </manifestEntries>
					  </archive>
				  </configuration>
			  </plugin>

			  <plugin>
				  <groupId>org.springframework.boot</groupId>
				  <artifactId>spring-boot-maven-plugin</artifactId>
				  <executions>
					  <execution>
						  <id>default</id>
						  <phase>package</phase>
						  <goals>
							  <goal>build-info</goal>
							  <goal>repackage</goal>
						  </goals>
					  </execution>
				  </executions>
			  </plugin>
		  </plugins>
	  </build>
  </profile>
</profiles>

<distributionManagement>
  <repository>
	  <id>maven-release</id>
	  <name>Nexus Release Repository</name>
	  <url>http://xxx:8081/repository/maven-releases/</url>
  </repository>

  <snapshotRepository>
	  <id>maven-snapshots</id>
	  <name>Nexus Release Repository</name>
	  <url>http://xxx:8081/repository/maven-snapshots/</url>
  </snapshotRepository>
</distributionManagement>
  • 注意:這裏一定要指定maven-assembly-plugin插件的版本為3.1.1+,否則會出現依賴包打包不正確的bug
<?xml version='1.0' encoding='UTF-8'?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">

    <!-- 打包完成後文件名以“-bin”結尾 -->
    <id>bin</id>
    <formats>
        <!-- 壓縮格式為tar.gz -->
        <format>tar.gz</format>
    </formats>
    <includeBaseDirectory>true</includeBaseDirectory>
    <!-- 文件拷貝 -->
    <fileSets>
        <!-- bin目錄: 拷貝運維腳本(Windows) -->
        <fileSet>
            <directory>${project.basedir}/src/bin</directory>
            <outputDirectory>bin</outputDirectory>
            <includes>
                <include>*_thin.bat</include>
                <include>shutdown.bat</include>
            </includes>
            <lineEnding>dos</lineEnding>
        </fileSet>
        <!-- bin目錄: 拷貝運維腳本(Linux)-->
        <fileSet>
            <directory>${project.basedir}/src/bin</directory>
            <outputDirectory>bin</outputDirectory>
            <includes>
                <include>*_thin.sh</include>
                <include>shutdown.sh</include>
            </includes>
            <lineEnding>unix</lineEnding>
            <fileMode>0755</fileMode>
        </fileSet>
        <!-- conf目錄: 從編譯目錄拷貝配置文件 -->
        <fileSet>
            <directory>${project.build.directory}/classes</directory>
            <outputDirectory>conf</outputDirectory>
            <includes>
                <!-- 若有漏掉的配置文件,可以在這裏添加規則 -->
                <include>config/**</include>
                <include>*.yml</include>
                <include>logback-spring.xml</include>
                <include>banner.txt</include>
            </includes>
        </fileSet>
        <!-- lib/bootapp目錄: 保存業務jar包,加載jar包時首先從bootapp目錄加載 -->
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>lib/bootapp</outputDirectory>
            <includes>
                <include>*-bootapp.jar</include>
            </includes>
        </fileSet>
    </fileSets>

    <!-- 依賴包拷貝 -->
    <dependencySets>
        <!-- lib/xdr目錄: 拷貝xdr相關的包 -->
        <dependencySet>
            <useProjectArtifact>false</useProjectArtifact>
            <outputDirectory>lib/xdr</outputDirectory>
            <outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension}</outputFileNameMapping>
            <includes>
                <!-- groupId:artifactId,支持通配符 -->
              	<include>com.xdr630*:*</include>
            </includes>
        </dependencySet>
        <!-- lib/spring目錄: 拷貝spring相關的包 -->
        <dependencySet>
            <useProjectArtifact>false</useProjectArtifact>
            <outputDirectory>lib/spring</outputDirectory>
            <outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension}</outputFileNameMapping>
            <includes>
                <include>org.springframework*:*</include>
            </includes>
        </dependencySet>
        <!-- lib/others目錄: 拷貝無法歸類的包相關的包 -->
        <dependencySet>
            <useProjectArtifact>false</useProjectArtifact>
            <outputDirectory>lib/others</outputDirectory>
            <outputFileNameMapping>${artifact.artifactId}-${artifact.baseVersion}.${artifact.extension}</outputFileNameMapping>
            <excludes>
                <exclude>org.springframework*:*</exclude>
                <exclude>com.xdr630*:*</exclude>
            </excludes>
        </dependencySet>
        <!-- 如果還有自定義的分包規則,可以在這裏添加 -->
    </dependencySets>
</assembly>