Ryan Wang's Blog

Spring Boot另类的打包方式

2018.09.25

这一篇是我很久之前发在头条上的,今天转过来。

Spring Boot在近来是非常受开发者欢迎的,简化了配置方式,不需要再配置繁琐的xml,内嵌web容器等等。相对于SSM,本人更喜欢使用Spring Boot开发Web项目。

总所周知,Spring Boot提供了两种打包方式,即Jar和War。前者内置了web容器,使用一条命令就可以运行,后者需要单独安装Tomcat容器。对比下来,我更喜欢打包成Jar,不想单独安装一个Tomcat,费时费力...

那么问题就来了,一个打包成Jar包之后,体积大的不忍直视。因为里面不仅包含了资源文件,还有很多依赖Jar包,导致体积一般都在40M以上。

所以在这里教大家一种打包方式,这种方式会把依赖Jar包,resources目录,运行Jar包分开。所以,第一次部署需要把这三部分都上传上去,但是以后的更新迭代就只需要上传覆盖resources目录(如果有修改的话),运行Jar包就可以了。

打包好的项目结构如下图: file

好了,开始正题,这种打包方式运用到了Maven的一个打包插件maven-assembly-plugin,没了解过的同学可以去百度了解一下。

修改pom.xml

首先我们需要修改pom.xml里面默认的代码块,如下

<build>
	<finalName>halo</finalName>
	<resources>
		<resource>
			<directory>src/main/java</directory>
			<filtering>false</filtering>
			<excludes>
				<exclude>**/*.java</exclude>
			</excludes>
		</resource>
	</resources>
	<plugins>
		<!-- 跳过单元测试,不然打包的时候会因为加载不了application.yaml报错 -->
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-surefire-plugin</artifactId>
			<configuration>
				<skip>true</skip>
			</configuration>
		</plugin>

		<plugin>
			<artifactId>maven-compiler-plugin</artifactId>
			<configuration>
				<source>1.8</source>
				<target>1.8</target>
				<encoding>UTF-8</encoding>
			</configuration>
		</plugin>

		<plugin>
			<artifactId>maven-assembly-plugin</artifactId>
			<configuration>
				<appendAssemblyId>false</appendAssemblyId>
				<descriptors>
					<descriptor>assembly.xml</descriptor>
				</descriptors>
				<outputDirectory>${project.build.directory}/dist/</outputDirectory>
			</configuration>
			<executions>
				<execution>
					<id>make-assembly</id>
					<phase>package</phase>
					<goals>
						<goal>single</goal>
					</goals>
				</execution>
			</executions>
		</plugin>

		<!-- 打包成jar文件,并指定lib文件夹以及resources资源文件夹 -->
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-jar-plugin</artifactId>
			<version>3.1.0</version>
			<configuration>
				<archive>
					<manifest>
						<mainClass>cc.ryanc.halo.Application</mainClass>
						<classpathPrefix>lib/</classpathPrefix>
						<addClasspath>true</addClasspath>
					</manifest>
					<manifestEntries>
						<Class-Path>resources/</Class-Path>
					</manifestEntries>
				</archive>
			</configuration>
		</plugin>
	</plugins>
</build>

创建assembly.xml

在项目根目录创建assembly.xml文件

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">

    <id>distribution</id>
    <formats>
        <format>dir</format>
    </formats>

    <includeBaseDirectory>false</includeBaseDirectory>

    <fileSets>
        <fileSet>
            <directory>src/main/resources/</directory>
            <outputDirectory>/resources</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>bin/</directory>
            <outputDirectory>/</outputDirectory>
        </fileSet>
    </fileSets>

    <dependencySets>
        <dependencySet>
            <outputDirectory>/lib</outputDirectory>
            <scope>runtime</scope>
            <excludes>
                <exclude>${project.groupId}:${project.artifactId}</exclude>
            </excludes>
        </dependencySet>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>${project.groupId}:${project.artifactId}</include>
            </includes>
        </dependencySet>
    </dependencySets>
</assembly>

好了,接下来在控制台执行mvn clean package,等待打包完成之后,就可以在target/dist里面看到打包好的项目了,只需要执行根目录的Jar就行了(java -jar 包名)。如果需要部署在服务端,建议使用shell脚本运行项目,不然退出控制台之后,应用就会被kill掉。