1. 简介
SpringBoot项目部署虽然简单,但是经常因为修改了少量代码而需要重新打包上传服务器重新部署,而公网服务器的网速受限,可能整个项目的代码文件仅仅只有1-2MB甚至更少,但是需要上传几十MB甚至更大的jar包而受限整体的部署速度。
项目基本稳定后,lib引入的jar很少再有更新了,假如可以将项目所需的lib放到外部路径,仅仅打包代码文件,可将包大小缩小到几十倍甚至几百倍。
2. 正常打包
- 创建项目
- 修改pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.c3stones</groupId>
<artifactId>spring-boot-reduce</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-reduce</name>
<description>Spring Boot Reduce Weight</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 编写启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 启动类
*
* @author CL
*
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 编写示例接口
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 示例Controller
*
* @author CL
*
*/
@RestController
public class DemoController {
/**
* 示例接口
*
* @return
*/
@RequestMapping(value = "/get")
public String get() {
return "demo";
}
}
- 项目打包
#进入项目根路径
mvn clean install
- 进入Maven仓库,查看信息
可以看到,整个包大小为15.9MB。使用解压工具打开:
可以看到,lib占用15.85MB。 - 启动项目,并请求示例接口
java -jar spring-boot-reduce-0.0.1-SNAPSHOT.jar
curl http://127.0.0.1:8080/get
3. 瘦身部署
- 从之前的包中拷贝jar
解压之前打的包,根据路径:spring-boot-reduce-0.0.1-SNAPSHOT.jarBOOT-INF拷贝lib文件夹。 - 修改pom文件(build节点)
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.c3stones</groupId>
<artifactId>spring-boot-reduce</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-reduce</name>
<description>Spring Boot Reduce Weight</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layout>ZIP</layout>
<includes>
<include>
<groupId>nothing</groupId>
<artifactId>nothing</artifactId>
</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</project>
layout必须为ZIP。includes中配置需要包含的jar,nothing表示不包含任何jar,因此将全部jar包放到外部路径。
- 进入项目根路径,再次打包
mvn clean install
- 进入Maven仓库,查看信息
可以看到,整个包大小为92.3KB。使用解压工具打开:
可以看到,已经没有lib文件夹了。 - 启动项目,并请求示例接口
将之前拷贝的lib文件夹和下工程包放到统一文件夹。
java -Dloader.path=lib -jar spring-boot-reduce-0.0.1-SNAPSHOT.jar
curl http://127.0.0.1:8080/get
loader.path配置外部包的路径,可配置相对路径或绝对路径。
项目可以正常启动,成功瘦身。
4. 原理分析
首先查看正常打包文件夹META-INF下的MANIFEST.MF文件:
Manifest-Version: 1.0
Implementation-Title: spring-boot-reduce
Implementation-Version: 0.0.1-SNAPSHOT
Built-By: Administrator
Implementation-Vendor-Id: com.c3stones
Spring-Boot-Version: 2.1.4.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.c3stones.Application
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_102
Implementation-URL: https://projects.spring.io/spring-boot/#/spring-bo
ot-starter-parent/spring-boot-reduce
再查看瘦身打包后文件夹META-INF下的MANIFEST.MF文件:
Manifest-Version: 1.0
Implementation-Title: spring-boot-reduce
Implementation-Version: 0.0.1-SNAPSHOT
Built-By: Administrator
Implementation-Vendor-Id: com.c3stones
Spring-Boot-Version: 2.1.4.RELEASE
Main-Class: org.springframework.boot.loader.PropertiesLauncher
Start-Class: com.c3stones.Application
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_102
Implementation-URL: https://projects.spring.io/spring-boot/#/spring-bo
ot-starter-parent/spring-boot-reduce
注意两个文件中Main-Class
的值。
在瘦身打包配置中,layout属性值必须为ZIP,特此说明layout属性值:
- JAR,即通常的可执行jar
Main-Class: org.springframework.boot.loader.JarLauncher - WAR,即通常的可执行war,需要的servlet容器依赖
Main-Class: org.springframework.boot.loader.warLauncher - ZIP,即DIR,类似于JAR
Main-Class: org.springframework.boot.loader.PropertiesLauncher
通过查看Spring Boot官网总结,org.springframework.boot.loader.Launcher
是作为一个可执行的jar的主入口点一个特殊的启动类。它是Main-Class的实际值,用于设置适当URLClassLoader的main()方法并最终调用程序方法。它有三个子类,即JarLauncher
,WarLauncher
和PropertiesLauncher
。
子类目的是从包引入的jar包或war包中加载资源。其中JarLauncher
和WarLauncher
加载资源的路径是固定的,即为BOOT-INF/lib和WEB-INF/lib。如果需要加载自定义位置的资源包,则需要使用PropertiesLauncher
,它默认的加载位置是BOOT-INF/lib,但可以使用loader.path来指定外部资源包的路径。PropertiesLauncher
具有可以通过外部属性(系统属性、环境变量、启动清单(MANIFEST.MF文件)、loader.properties)启用的一些特殊功能,具体请查阅SpringBoot官网:Launching Executable Jars