公司的这种打包启动方式,我简直惊呆了

简介: 大家都知道,SpringBoot应用最终会打出一个Fat Jar, 里面包含了用到的全部依赖,启动也非常简单,java -jar xxx.jar即可。

前言

如果本文对你有帮助的话,球球帮忙投个票吧,投票通道 感激不尽呀~~

大家都知道,SpringBoot应用最终会打出一个Fat Jar, 里面包含了用到的全部依赖,启动也非常简单,java -jar xxx.jar即可。

但是我们公司打出的最终包,将依赖包挪到了外部,然后启动的时候通过loader.path指定依赖包的位置,如java -Dloader.path=libs -jar xxxx的方式启动,也能够启动成功。

这样做最大的一个好处就是如果发现某个依赖出现问题,那么我只需要在libs替换其中某个依赖,影响范围可以减小很多。
那大家是不是很好奇是怎么做到的呢?
打包方式详解
主要是通过两个maven插件打出这样的结构的包。

spring-boot-maven-plugin

该插件是spring boot官方提供的一个打包插件,主要用来打出fat jar,并且提供了支持java -jar xxx.jar方式启动。 官网地址:docs.spring.io/spring-boot…。
我们需要用这个插件,因为只有它可以打出支持启动的jar,但是打出的包中又不能有依赖,该怎么做呢?如下图:

layout: 布局方式,这里要选择ZIP,后面说明原因。
includes: 选择包含哪些依赖,这里写了一个不存在的jar,那么也间接实现了不打入其他的依赖。这种方式比较ugly,但是目前没有找到更加合适的方案。

maven-assembly-plugin

maven-assembly-plugin插件可以灵活定制打包内容,官网地址:maven.apache.org/plugins/mav…。
我们现在就是想办法利用该插件抽出我们用到的依赖包,该怎么做呢?

我们现在看下assembly.xml中的关键配置:

可以根据include、exclude属性通过正则灵活的抽取相关依赖到指定的目录下

最终执行mvn clean package在target目录下得到最终的安装包:

解压该安装包:

打开libs目录:

启动方式解析
现在我们已经按照自己想要的结构打出包了,那如何在启动的时候加载libs目录中的依赖呢?
前面提到了springboot插件打出的包是启动的入口,实际上在这个包里面springboot会自动打入一个引导类org.springframework.boot.loader.Launcher,它是 Spring Boot 可执行 jar 的主要入口点,它是 Spring Boot jar 文件中的实际 Main-Class,用于设置适当的 URLClassLoader 并最终调用 Spring Boot项目中定义的 main()方法。
Launcher有三个子类(JarLauncher、WarLauncher 和 PropertiesLauncher),如果我们打包插件的layout配置的是ZIP的方式,它会使用PropertiesLauncher。
PropertiesLauncher机制说明:
默认情况下,PropertiesLauncher 在 BOOT-INF/lib/ 中加载,我们可以通过设置loader.properties 中的loader.path 或 LOADER_PATH 环境变量来增加其它的加载位置。

loader.path:配置逗号分隔的 Classpath 类路径,例如 lib,${HOME}/app/lib,前面的路径优先,类似于 javac 命令中的 -classpath。
loader.home:用于解析 loader.path 配置的相对路径,默认是${user.dir}。

所以,打包成功后,我们可以通过 java -jar -Dloader.path=xx1,xx2,public .jar 命令来启动程序,这样对应目录下的依赖均会被加载。
总结
这种打包启动方式虽然不常见,但是还是有一定的价值的,特别是在项目组件模块比较多的时候,出现紧急缺陷,可以按需替换包,将影响范围控制到最小。

相关文章
|
关系型数据库 测试技术 数据库
PostgreSQL数据库压力测试工具pgbench简单应用
PG数据库提供了一款轻量级的压力测试工具叫pgbench,其实就是一个编译好后的扩展性的可执行文件。
3499 0
|
6月前
|
开发工具 开发者
鸿蒙开发:如何无线调试应用
以上呢,就是鸿蒙开发中,如何使用无线来调试应用,相对来说还是比较的简单,需要注意的事项只有一个,那就是,两台设备,一个是PC电脑,一个是真机设备,都需要在同一网络下,才能运行起来应用。
295 1
|
9月前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
404 23
|
Java ice
【Java开发指南 | 第二十八篇】Java封装
【Java开发指南 | 第二十八篇】Java封装
222 0
|
算法 安全 数据安全/隐私保护
链接加密的方法有哪些?
【10月更文挑战第6天】链接加密的方法有哪些?
1306 10
|
存储 数据安全/隐私保护
贴片卡与插拔卡的优缺点
在讨论贴片卡(通常指的是嵌入在设备内部的存储卡,如SIM卡、eMMC等)与插拔卡(如SD卡、microSD卡等,用户可以轻松插入和拔出的存储卡)的优缺点时,我们可以从多个方面进行比较:
|
消息中间件 存储 监控
RabbitMQ 死信队列
RabbitMQ的死信队列(DLQ)是存储无法正常消费消息的特殊队列,常见于消息被拒绝、过期或队列满时。DLQ用于异常处理、任务调度和监控,通过绑定到普通队列自动路由死信消息。通过监听死信队列,可以对异常消息进行补偿和进一步处理,提升系统稳定性和可维护性。
424 1
|
XML Android开发 UED
Android动画之共享元素动画简单实践
本文介绍Android共享元素动画, 实现两Activity间平滑过渡特定UI元素。通过设置`transitionName`属性和使用`ActivityOptions.makeSceneTransitionAnimation`启动目标Activity实现动画效果。可自定义过渡动画提升体验。
358 0
|
移动开发 JavaScript 前端开发
app四种开发模式的优缺点
app四种开发模式的优缺点
679 1