文章目录
- Fat Jar
- 瘦身
- pom修改
- copy lib
- 启动 -Dloader.path
- 验证
- 源码分析
- 前置阅读
- spring-boot-loader 依赖
- 类继承关系
- PropertiesLauncher属性配置
- 附 pom.xml
Fat Jar
【pom.xml】
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.16</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.artisan</groupId>
<artifactId>thinBootJar</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>thinBootJar</name>
<description>thinBootJar</description>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder-jammy-base:latest</builder>
</image>
</configuration>
</plugin>
</plugins>
</build>
</project>
打包后观察目录
重点关注下Main-Class
瘦身
pom修改
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 用来配置可执行jar包中Main-Class的类型,这里一定要设置为 ZIP,使打的jar包中的Main-Class为PropertiesLauncher
-->
<layout>ZIP</layout>
<includes>
<!-- 不打依赖包 -->
<include>
<!-- nothing 代表不存在的依赖包,意思就是什么依赖包都不引入-->
<groupId>nothing</groupId>
<artifactId>nothing</artifactId>
</include>
<!-- <include>-->
<!-- common是引入的公共服务模块 -->
<!-- <groupId>com.xxx.xx.rpc</groupId>-->
<!-- <artifactId>common</artifactId>-->
<!-- </include>-->
</includes>
</configuration>
</plugin>
</plugins>
</build>
JAR,即通常的可执行jar
Main-Class: org.springframework.boot.loader.JarLauncher
WAR,即通常的可执行war,需要的servlet容器依赖位于WEB-INF/lib-provided
Main-Class: org.springframework.boot.loader.warLauncher
ZIP,即DIR,类似于JAR
Main-Class: org.springframework.boot.loader.PropertiesLauncher
MODULE,将所有的依赖库打包(scope为provided的除外),但是不打包Spring Boot的任何Launcher
NONE,将所有的依赖库打包,但是不打包Spring Boot的任何Launcher
打包后观察下 jar包 的大小 和 里面的内容
重点关注下Main-Class
copy lib
<!-- 将依赖的jar包copy到lib目录下 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!-- 指定依赖的路径 -->
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
打包后观察下
启动 -Dloader.path
为了让名字好看一点
java -Dloader.path=./lib -jar artisan-test-thin-boot-jar.jar
验证
通过启动参数loader.path
配置外置依赖包的加载路径。 项目成功启动,说明我们配置的外包依赖包加载生效了
源码分析
前置阅读
SpringBoot - 探究Spring Boot应用是如何通过java -jar 启动的
SpringBoot(二) 启动分析JarLauncher
spring-boot-loader 依赖
为了方便查看源码,我们引入如下依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-loader -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
</dependency>
类继承关系
org.springframework.boot.loader.Launcher
类是特殊的引导程序类,用作可执行jar的主要入口点。它是jar文件中的实际Main-Class,用于设置适当的URLClassLoader并最终调用main()方法
-
有三个启动器子类(
JarLauncher
,WarLauncher
和PropertiesLauncher
)。它们的目的是从目录中的嵌套jar文件或war文件(而不是在类路径中显式的文件)加载资源(.class文件等)。 -
对于
JarLauncher
和WarLauncher
,嵌套路径是固定的。JarLauncher
位于BOOT-INF / lib /
中,而WarLauncher
位于WEB-INF / lib /
和WEB-INF / lib-provided /
中。如果需要,可以在这些位置添加额外的罐子。 -
默认情况下,
PropertiesLauncher
在应用程序存档中的BOOT-INF / lib /
中查找。可以通过在loader.properties
(这是目录,归档文件或归档文件中的目录的逗号分隔列表)中设置一个称为LOADER_PATH
或loader.path
的环境变量来添加其他位置
概括一下: 启动器Launcher是为了项目启动加载依赖资源的,共有3个启动器 JarLauncher,WarLauncher和PropertiesLauncher ,
- JarLauncher和WarLauncher加载资源的路径是固定的,
- PropertiesLauncher可以通过环境变量loader.path来指定加载资源的位置
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
PropertiesLauncher属性配置
- loader.path: 用于定义lib包加载路径。
- loader.home: 解析loader.path中相对路径的基础路径,通常是类路径位置。
- loader.args: 设置main方法的默认参数,以空格分隔。
- loader.main: 指定要启动的主类的名称,例如com.xxx.Application。
- loader.config.name: 指定属性文件的路径,例如classpath:loader.properties。
- loader.system: 一个布尔值标志,指示是否将所有属性添加到系统属性,默认为false。
附 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.16</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.artisan</groupId>
<artifactId>thinBootJar</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>thinBootJar</name>
<description>thinBootJar</description>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>artisan-test-thin-boot-jar</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 用来配置可执行jar包中Main-Class的类型,这里一定要设置为 ZIP,使打的jar包中的Main-Class为PropertiesLauncher
-->
<layout>ZIP</layout>
<includes>
<!-- 不打依赖包 -->
<include>
<!-- nothing 代表不存在的依赖包,意思就是什么依赖包都不引入-->
<groupId>nothing</groupId>
<artifactId>nothing</artifactId>
</include>
<!-- <include>-->
<!-- common是引入的公共服务模块 -->
<!-- <groupId>com.xxx.xx.rpc</groupId>-->
<!-- <artifactId>common</artifactId>-->
<!-- </include>-->
</includes>
</configuration>
</plugin>
<!-- 将依赖的jar包copy到lib目录下 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!-- 指定依赖的路径 -->
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>