SpringBoot 项目瘦身maven/gradle详解
howeres 人气:0maven thin jar 步骤
spring-boot-maven-plugin configuration layout ZIP includes include non-exists maven-dependency-plugin excutions excution goal copy-dependencies configuration outputDirectory
<build> <finalName>thin-jar</finalName> <!--java -jar -Dloader.path=./lib thin-jar.jar--> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring.boot.version}</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> <configuration> <!-- fork=true 新开 Jvm 运行插件 --> <fork>true</fork> <addResources>true</addResources> <jvmArguments>-Dfile.encoding=UTF-8</jvmArguments> <layout>ZIP</layout> <includes> <include> <groupId>non-exists</groupId> <artifactId>non-exists</artifactId> </include> </includes> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy-dependencies</id> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/lib</outputDirectory> <!--是否排除传递性--> <excludeTransitive>false</excludeTransitive> <!--是否去掉jar包版本信息--> <stripVersion>false</stripVersion> <!--包含范围--> <includeScope>runtime</includeScope> </configuration> </execution> </executions> </plugin> </plugins> </build>
<fork>false</fork>
表示 Maven 使用自身的 JVM 虚拟机运行插件, 而 <fork>true</fork>
则告知 Maven 启动一个新的 JVM 虚拟机进程运行插件. 使用 spring-boot-devtools 模块时需要特定 JVM 配置来运行, 所以需要创建新的 JVM 虚拟机进程来运行. 所以通常使用 spring-boot-devtools 热部署时, 需要在 spring-boot-maven-plugin 插件上会加上 fork=true
<layout>ZIP</layout>
MANIFEST.MF 文件中 Main-Class 是 PropertiesLauncher, 就是 spring-boot-maven-plugin 插件配置 <layout>ZIP</layout>
的结果
- layout:
- 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
- 此外
<classifier>suffix</classifier>
project-1.1.1-suffix 与 mvn package 所打成的 jar 进行区分 - mvn package 打包时使用 maven-jar-plugin 插件执行 package 命令, 生成的 jar 不包含依赖, 不可以执行但可以作为依赖引用
- 使用 spring-boot-maven-plugin 插件打包将 mvn package 生成的软件包重命名为了 *.original
Gradle thin jar
task clearJar(type: Delete) { delete "$buildDir/libs/lib" } // 将依赖包复制到lib目录 task copyJar(type: Copy, dependsOn: 'clearJar') { into "$buildDir/libs/lib" from configurations.runtime // from configurations.compileClasspath } bootJar { // mainClassName = '' // 例外所有的jar excludes = ["*.jar"] // lib目录的清除和复制任务 dependsOn clearJar dependsOn copyJar // 指定依赖包的路径, 无需 java.ext.dir 或 loader.path 参数 manifest { attributes "Manifest-Version": 1.0, 'Class-Path': configurations.compileClasspath.files.collect { "lib/$it.name" }.join(' ') } }
需要把 dependencies 放到了 bootJar{} 之前
调用 bootJar 打包
运行的时候也不需要指定 -Djava.ext.dirs=./lib 或 -Dloader.path=./lib 了, 将 lib 目录放在 jar 包同级目录下, 直接 -jar运行就可以了
# java -Djava.ext.dirs=./lib -jar bootrun.jar java -jar bootrun.jar
loader.path
loader.path 是 Spring 提供的配置参数
可以使用 --classpath / -cp 指定类加载的路径,但 classpath 的生效是有条件的
# 运行 class 生效 java -cp .;lib/x.jar Test # 运行 jar 失效 java -cp lib/x.jar -jar app.jar
使用 java -jar boot.jar
时 (此时 -cp 无效), 可以使用 loader.path
指定类加载路径加载其他 jar, loader.path
实现了 classpath
的功能
但 loader.path 生效是有条件的
当 MANIFEST.MF 的 Main-Class 为:
- PropertiesLauncher (额外配置) 生效
- JarLauncher (默认配置) 失效 (启动会快一些)
为了使用 loader.path,需要把 jar 包的 Main-Class 配置为 PropertiesLauncher,在 build.gradle 中如下配置,可参考 Using the PropertiesLauncher
bootJar { manifest { attributes 'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher' } }
So by adding all the needed classpaths to the loader.path variable, spring will be able to boostrap the application. (details)
加载全部内容