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

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

前言


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


1671200314521.jpg


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


1671200322433.jpg


这样做最大的一个好处就是如果发现某个依赖出现问题,那么我只需要在libs替换其中某个依赖,影响范围可以减小很多。

那大家是不是很好奇是怎么做到的呢?


打包方式详解


主要是通过两个maven插件打出这样的结构的包。

  1. spring-boot-maven-plugin

该插件是spring boot官方提供的一个打包插件,主要用来打出fat jar,并且提供了支持java -jar xxx.jar方式启动。 官网地址:docs.spring.io/spring-boot…

我们需要用这个插件,因为只有它可以打出支持启动的jar,但是打出的包中又不能有依赖,该怎么做呢?如下图:


1671200331730.jpg


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

maven-assembly-plugin插件可以灵活定制打包内容,官网地址:maven.apache.org/plugins/mav…

我们现在就是想办法利用该插件抽出我们用到的依赖包,该怎么做呢?

1671200341420.jpg

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

1671200348372.jpg

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

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

网络异常,图片无法展示
|

解压该安装包:

1671200355719.jpg

打开libs目录:

1671200360737.jpg


启动方式解析


现在我们已经按照自己想要的结构打出包了,那如何在启动的时候加载libs目录中的依赖呢?

前面提到了springboot插件打出的包是启动的入口,实际上在这个包里面springboot会自动打入一个引导类org.springframework.boot.loader.Launcher,它是 Spring Boot 可执行 jar 的主要入口点,它是 Spring Boot jar 文件中的实际 Main-Class,用于设置适当的 URLClassLoader 并最终调用 Spring Boot项目中定义的 main()方法。

Launcher有三个子类(JarLauncherWarLauncherPropertiesLauncher),如果我们打包插件的layout配置的是ZIP的方式,它会使用PropertiesLauncher

PropertiesLauncher机制说明:

默认情况下,PropertiesLauncherBOOT-INF/lib/ 中加载,我们可以通过设置loader.properties 中的loader.pathLOADER_PATH 环境变量来增加其它的加载位置。

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

所以,打包成功后,我们可以通过 java -jar -Dloader.path=xx1,xx2,public <jarName>.jar 命令来启动程序,这样对应目录下的依赖均会被加载。


总结


这种打包启动方式虽然不常见,但是还是有一定的价值的,特别是在项目组件模块比较多的时候,出现紧急缺陷,可以按需替换包,将影响范围控制到最小。

目录
相关文章
|
Rust 安全 前端开发
你应该知晓的Rust Web 框架(一)
你应该知晓的Rust Web 框架
1379 1
|
3月前
|
人工智能 开发框架 监控
AI智能体的开发流程
开发成熟AI智能体是系统工程,需融合自主规划、记忆管理与工具调用。本文详解企业级五阶段标准流程:需求定义、架构设计(LLM/记忆/规划/工具)、核心开发(框架/Prompt/函数调用)、评测优化(黄金数据集/轨迹分析/安全护栏)及LLMOps部署运维。(239字)
YOLOv11改进策略【模型轻量化】| 替换骨干网络为 GhostNet V3 2024华为的重参数轻量化模型
YOLOv11改进策略【模型轻量化】| 替换骨干网络为 GhostNet V3 2024华为的重参数轻量化模型
1003 18
YOLOv11改进策略【模型轻量化】| 替换骨干网络为 GhostNet V3 2024华为的重参数轻量化模型
|
JSON 前端开发 数据格式
鸿蒙5开发宝藏案例分享---体验流畅的首页信息流
本攻略分享了一个鸿蒙新闻类首页的完整开发方案,涵盖流畅动效、懒加载及性能优化。核心功能包括:1) 51ms响应的Tab切换动效,使用`onAnimationStart`实现;2) 底部Lottie动画,帧率稳定60FPS;3) 下拉刷新与上拉加载,响应时间仅150ms;4) 懒加载Feed流,支持万级数据不卡顿;5) 地址选择页,结合位置服务与城市索引提升用户体验。整体方案注重性能优化与交互细节,适合开发者快速上手并提升应用品质。
|
存储 Java 定位技术
获取ip所在城市
本文介绍了如何在SpringBoot应用中通过IP地址快速获取用户的国家、省份和城市信息。首先,通过引入GeoLite2 City数据库并整合相关依赖,接着下载并配置GeoLite2 City数据库文件。然后,创建地址获取工具类和Controller接口,最后进行测试以确保功能正常。此方法简单高效,适用于多种应用场景。
|
Python
Python量化炒股的数据信息获取— 获取上市公司股东和股本信息
Python量化炒股的数据信息获取— 获取上市公司股东和股本信息
1549 1
|
Kubernetes 监控 调度
Kubernetes(K8s)与虚拟GPU(vGPU)协同:实现GPU资源的高效管理与利用
本文探讨了如何使用Kubernetes和虚拟GPU(vGPU)实现异构GPU的协同调度。Kubernetes是一个容器编排平台,通过设备插件、资源规格、调度器扩展和节点标签实现GPU资源管理。vGPU技术允许物理GPU资源在多个虚拟机或容器中共享。文章详细介绍了vGPU的部署配置步骤,并提出了GPU资源调度、负载均衡和监控调优的方法。强调虚拟GPU的性能取决于硬件和驱动支持,合理配置能提供高性能计算环境。参考文献包括Kubernetes和NVIDIA官方文档及相关研究论文。
|
缓存 算法 Java
提升性能与可读性的艺术
【10月更文挑战第22天】提升性能与可读性的艺术
|
前端开发 JavaScript
实用的JavaScript小技巧
这些JavaScript小技巧可以帮助你更加高效地编写代码,提高代码质量和可读性。
211 1
|
算法
【二分查找】数的范围/数的三次方根
【二分查找】数的范围/数的三次方根
339 0
【二分查找】数的范围/数的三次方根