Spring Boot - 瘦身大作战:优雅应对Spring Boot Fat Jar

news2024/9/21 2:44:24

文章目录

  • 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()方法

  • 有三个启动器子类(JarLauncherWarLauncherPropertiesLauncher)。它们的目的是从目录中的嵌套jar文件或war文件(而不是在类路径中显式的文件)加载资源(.class文件等)。

  • 对于JarLauncherWarLauncher,嵌套路径是固定的。 JarLauncher位于BOOT-INF / lib /中,而WarLauncher位于WEB-INF / lib /WEB-INF / lib-provided /中。如果需要,可以在这些位置添加额外的罐子。

  • 默认情况下,PropertiesLauncher在应用程序存档中的BOOT-INF / lib /中查找。可以通过在loader.properties(这是目录,归档文件或归档文件中的目录的逗号分隔列表)中设置一个称为LOADER_PATHloader.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属性配置

在这里插入图片描述

在这里插入图片描述

  1. loader.path: 用于定义lib包加载路径。
  2. loader.home: 解析loader.path中相对路径的基础路径,通常是类路径位置。
  3. loader.args: 设置main方法的默认参数,以空格分隔。
  4. loader.main: 指定要启动的主类的名称,例如com.xxx.Application。
  5. loader.config.name: 指定属性文件的路径,例如classpath:loader.properties。
  6. 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>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1249896.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人机交互2——任务型多轮对话的控制和生成

1.自然语言理解模块 2.对话管理模块 3.自然语言生成模块

【数据结构 —— 堆的实现(顺序表)】

数据结构 —— 堆的实现&#xff08;顺序表&#xff09; 一.堆1.1堆的定义及结构1.1.1.堆的定义1.1.2.堆的性质1.1.3.堆的结构 二.堆的实现2.1.头文件的实现 —— &#xff08;Heap.h&#xff09;2.2.源文件的实现 —— &#xff08;Heap.c&#xff09;2.2.1.小堆的源文件2.2.2…

【汉诺塔 —— (经典分治递归)】

汉诺塔 —— &#xff08;经典分治递归&#xff09; 一.汉诺塔介绍二.分治算法解决汉诺塔问题三.汉诺塔问题的代码实现四.主函数测试展示 一.汉诺塔介绍 汉诺塔问题源自印度一个古老的传说&#xff0c;印度教的“创造之神”梵天创造世界时做了 3 根金刚石柱&#xff0c;其中的一…

量子计算 | 解密著名量子算法Shor算法和Grover算法

专栏集锦&#xff0c;大佬们可以收藏以备不时之需 Spring Cloud实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏&#xff1a;https:/…

Matplotlib自定义坐标刻度_Python数据分析与可视化

自定义坐标刻度 主次要刻度隐藏刻度与标签花哨的刻度格式格式生成器与定位器 虽然matplotlib默认的坐标轴定位器与格式生成器可以满足大部分需求&#xff0c;但是并非对每一幅图都合适。 主次要刻度 学习前最好有对matplotlib图形的对象层级较为了解&#xff0c;例如查看前面…

ZKP11.3 Correlation Intractability

ZKP学习笔记 ZK-Learning MOOC课程笔记 Lecture 11: From Practice to Theory (Guest Lecturer: Alex Lombardi) 11.3 What can we do without random oracle model Falsifiable Assumptions Prove security assuming that some concrete algorithmic task is infeasible: …

案例024:基于微信小程序的汽车保养系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

【华为网络-配置-021】- MSTP 多实例配置及安全保护等

要求&#xff1a; 1、vlan 10 从红色链路转发。 2、vlan 20 从黄色链路转发。 一、基础配置 [SW1]vlan batch 10 20 [SW1]interface GigabitEthernet 0/0/1 [SW1-GigabitEthernet0/0/1]port link-type trunk [SW1-GigabitEthernet0/0/1]port trunk allow-pass vlan all [SW…

【点云surface】 修剪B样条曲线拟合

1 介绍 Fitting trimmed B-splines&#xff08;修剪B样条曲线拟合&#xff09;是一种用于对给定的点云数据进行曲线拟合的算法。该算法使用B样条曲线模型来逼近给定的点云数据&#xff0c;并通过对模型进行修剪来提高拟合的精度和准确性。 B样条曲线是一种常用的曲线表示方法…

深度学习之基于Tensorflow银行卡号码识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介银行卡号码识别的步骤TensorFlow的优势 二、功能三、系统四. 总结 一项目简介 # 深度学习基于TensorFlow的银行卡号码识别介绍 深度学习在图像识别领域取得…

浏览器缓存、本地存储、Cookie、Session、Token

目录 前端通信&#xff08;渲染、http、缓存、异步、跨域&#xff09; HTTP与HTTPS&#xff0c;HTTP版本、状态码 请求头&#xff0c;响应头 缓存 强制缓存&#xff1a;Cache-Control:max-age&#xff08;HTTP1.1&#xff09;>Expires&#xff08;1.0&#xff09; js、…

python pdf转txt文本、pdf转json

文章目录 一、前言二、实现方法1. 目录结构2. 代码 一、前言 此方法只能转文本格式的pdf&#xff0c;如果是图片格式的pdf需要用到ocr包&#xff0c;以后如果有这方面需求再加这个方法 二、实现方法 1. 目录结构 2. 代码 pdf2txt.py 代码如下 #!/usr/bin/env python # -*- …

【LM、LLM】浅尝二叉树在前馈神经网络上的应用

前言 随着大模型的发展&#xff0c;模型参数量暴涨&#xff0c;以Transformer的为组成成分的隐藏神经元数量增长的越来越多。因此&#xff0c;降低前馈层的推理成本逐渐进入视野。前段时间看到本文介绍的相关工作还是MNIST数据集上的实验&#xff0c;现在这个工作推进到BERT上…

【Java程序员面试专栏 专业技能篇】Java SE核心面试指引(三):核心机制策略

关于Java SE部分的核心知识进行一网打尽,包括四部分:基础知识考察、面向对象思想、核心机制策略、Java新特性,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 本篇Blog为第三部分:核心机制策略,子节点表示追问或同级提问 异常处理 …

机器学习之自监督学习(四)MoCo系列翻译与总结(一)

Momentum Contrast for Unsupervised Visual Representation Learning Abstract 我们提出了“动量对比”&#xff08;Momentum Contrast&#xff0c;MoCo&#xff09;来进行无监督的视觉表示学习。从对比学习的角度来看&#xff0c;我们将其视为字典查找&#xff0c;通过构建…

Spring - Mybatis-设计模式总结

Mybatis-设计模式总结 1、Builder模式 2、工厂模式 3、单例模式 4、代理模式 5、组合模式 6、模板方法模式 7、适配器模式 8、装饰者模式 9、迭代器模式 虽然我们都知道有26个设计模式&#xff0c;但是大多停留在概念层面&#xff0c;真实开发中很少遇到&#xff0c;…

Day31| Leetcode 455. 分发饼干 Leetcode 376. 摆动序列 Leetcode 53. 最大子数组和

进入贪心了&#xff0c;我觉得本专题是最烧脑的专题 Leetcode 455. 分发饼干 题目链接 455 分发饼干 让大的饼干去满足需求量大的孩子即是本题的思路&#xff1a; class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {…

【差分放大电路分析】2021-12-31

缘由有哪位愿意帮助一下的-嵌入式-CSDN问答 截图&#xff0c;数值自己去计算。上2图是接电阻&#xff0c;下2图是接三极管。

JVM内存模型及调优

本文将为大家详细介绍JVM内存模型及如何对JVM内存进行调优。我们将分为以下几个部分进行讲解&#xff1a; JVM内存模型概述JVM内存区域及作用JVM内存调优方法实战案例与优化技巧 一、JVM内存模型概述 在深入了解JVM内存模型之前&#xff0c;我们需要先了解一下Java内存模型&am…

01、Tensorflow实现二元手写数字识别

01、Tensorflow实现二元手写数字识别&#xff08;二分类问题&#xff09; 开始学习机器学习啦&#xff0c;已经把吴恩达的课全部刷完了&#xff0c;现在开始熟悉一下复现代码。对这个手写数字实部比较感兴趣&#xff0c;作为入门的素材非常合适。 基于Tensorflow 2.10.0 1、…