参考SpringBoot的启动原理,解析和执行Jar包中的方法

JVMTI 实现 springboot jar包的加密(防止反编译) 421342 阅读详情

解析和执行Jar包中的方法

1. 使用spring-boot 的打包插件

打包插件配置:pom.xml

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.1.3.RELEASE</version>
                <configuration>
                    <layout>NONE</layout>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

layout 配置为 NONE 表示打包的结果包含所有依赖,并且不会包含spring-boot-loader。

spring-boot 打包插件的详细,请参考官方文档。

如 springbootjar ,使用 mvn clean package 打包后,jar 包的结构如下:

在这里插入图片描述

2. 核心代码

工程依赖于 spring-boot-loader ,相关 pom 配置为:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-loader</artifactId>
            <version>2.1.3.RELEASE</version>
            <scope>provided</scope>
        </dependency>

新建一个类 MyLauncher ,继承于 JarLauncher,然后对外暴露一个方法,提供 ClassLoader,这个类加载器,就可以加载使用 spring-boot-maven-plugin 打的 jar 包中的方法了。

具体代码如下:

package com.ysx.execute.utils;

import org.springframework.boot.loader.JarLauncher;
import org.springframework.boot.loader.archive.Archive;
import org.springframework.boot.loader.jar.JarFile;

/**
 * @author youngbear
 * @email youngbear@aliyun.com
 * @date 2019-04-01 07:45
 * @blog https://blog.youkuaiyun.com/next_second
 * @github https://github.com/YoungBear
 * @description
 */
public class MyLauncher extends JarLauncher {
    public MyLauncher(Archive archive) {
        super(archive);
    }

    /**
     * 获取 ClassLoader
     *
     * @return
     * @throws Exception
     */
    public ClassLoader getClassLoader() throws Exception {
        JarFile.registerUrlProtocolHandler();
        ClassLoader classLoader = createClassLoader(getClassPathArchives());
        return classLoader;
    }
}

具体执行方法的代码如下:

package com.ysx.execute.service.impl;

import com.google.gson.Gson;
import com.ysx.execute.entity.RequestExecuteEntity;
import com.ysx.execute.service.IExecuteService;
import com.ysx.execute.utils.MyLauncher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.loader.archive.JarFileArchive;
import org.springframework.stereotype.Service;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

/**
 * @author youngbear
 * @email youngbear@aliyun.com
 * @date 2019-04-01 20:42
 * @blog https://blog.youkuaiyun.com/next_second
 * @github https://github.com/YoungBear
 * @description
 */
@Service
public class ExecuteServiceImpl implements IExecuteService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExecuteServiceImpl.class);
    private static final Gson GSON = new Gson();

    @Override
    public String executeSpringBootJar(RequestExecuteEntity requestExecuteEntity) throws Exception {
        String jarPath = requestExecuteEntity.getJarPath();
        String className = requestExecuteEntity.getClassName();
        String methodName = requestExecuteEntity.getMethodName();
        List<String> paramClassNameList = requestExecuteEntity.getParamClassNameList();
        List<String> paramJsonList = requestExecuteEntity.getParamJsonList();

        // 使用本地jar文件,创建一个 JarFileArchive
        JarFileArchive jarFileArchive = new JarFileArchive(new File(jarPath));
        // 根据 JarFileArchive 创建一个 MyLauncher 对象,用于获取 类加载器
        MyLauncher myLauncher = new MyLauncher(jarFileArchive);
        ClassLoader classLoader = myLauncher.getClassLoader();

        // 使用类加载器,获取相关 Class<?> 对象,最后使用反射调用方法
        Class<?> aClass = classLoader.loadClass(className);
        List<Class<?>> paramClassList = new ArrayList<>();
        for (String paramClassName : paramClassNameList) {
            paramClassList.add(classLoader.loadClass(paramClassName));
        }
        Class<?>[] paramClassArray = paramClassList.toArray(new Class<?>[0]);

        List<Object> paramObjectList = new ArrayList<>();
        for (int i = 0; i < paramJsonList.size(); i++) {
            paramObjectList.add(GSON.fromJson(paramJsonList.get(i), paramClassList.get(i)));
        }

        Object[] paramObjectArray = paramObjectList.toArray(new Object[0]);

        Method method = aClass.getDeclaredMethod(methodName, paramClassArray);

        Object obj = aClass.newInstance();
        Object result = method.invoke(obj, paramObjectArray);
        LOGGER.info("result: {}", GSON.toJson(result));

        // 执行完成后,关闭 ClassLoader
        if (classLoader instanceof URLClassLoader) {
            ((URLClassLoader) classLoader).close();
        }

        return GSON.toJson(result);
    }
}

3. 请求示例

本地使用 SpringBoot 启动 execute 工程后(mvn spring-boot:run),可以访问SwaggerUI文档地址:http://localhost:8080/swagger-ui.html

http 请求入参:

{
  "className": "com.ysx.springbootjar.Hello",
  "jarPath": "/Users/youngbear/Desktop/springbootjar-1.0-SNAPSHOT.jar",
  "methodName": "method1",
  "paramClassNameList": [
    "com.ysx.springbootjar.param.InputParam"
  ],
  "paramJsonList": [
    "{\"in1\":\"in1ysx\",\"in2\":2}"
  ]
}

执行结果如下图:

在这里插入图片描述

项目GitHub地址

参考

1. springboot应用启动原理(二) 扩展URLClassLoader实现嵌套jar加载

2. spring boot应用启动原理分析

3. spring boot应用启动原理分析

springboot项目开发实战 文章目录springboot项目开发实战之后端流程详解一、创建简单的springboot之web项目1、简单springboot框架环境搭建2、相关jar包的导入3、配置文件yaml的设置4、框架结构的梳理如过滤器和拦截器5、代码结构的书写1)controller层书写 springboot项目开发实战之后端流程详解 一、创建简单的springboot之web项目 1、简单springboot框架环境搭建 step1: step2: step3: step4: step5: 2、相关jar包的导入 阅读详情

相关推荐

springboot+java类热加载

springboot 、java类热加载、jarinjar、动态编译、自动引用依赖

springboot 动态加载jar包,插件式加载运行

springboot 动态加载jar包,插件式加载运行

hybaym的专栏 5120

spring-boot-loader-tools-2.1.3.RELEASE.jar

java运行依赖jar包

Spring boot的ClasssLoader加载和卸载jar/class

一.前言 在开发过程中,有时候需要动态加载各种jar/class到程序中,然而又只使用一次,或者加载的jar/class中有改动需要持续升级。程序一直在运行,每次加载进去的jar/class如果过多,对系统会造成很大的压力,而且已经加载进去的jar/class不能覆盖,从而造成得不到想要的结果。此时就需要考虑对加载进去的jar/class进行卸载。 二.思路 我们知道,当一个java类...

丶自定义 5417

gm/Id 设计方法

本文介绍gm/Id方法的具体实现。

maxwell2ic的博客 4万+

XianYuAutoDeliveryX:基于闲鱼API与大模型的智能自动发货系统实践

本文详细介绍了如何利用XianYuAutoDeliveryX系统,结合闲鱼API与大语言模型,构建一个智能自动发货解决方案。该系统能实现买家付款后秒级自动发货,并通过对接ChatGPT等大模型智能回复买家咨询,有效解放卖家时间,提升虚拟商品店铺的运营效率和客户体验。

bush的博客 1016

springboot调用子项目(以jar方式)

1.首先将子项目打包成jar包 使用maven install命令将子项目打包 选中子项目右击选择run as—》maven insatll 这里简单说下为什么不用maven package打包 它们的区别:package 只是打包到target下,install是打包安装到我的本地maven仓库 2.在父项目的pom.xml添加子项目的依赖 &amp;lt;dependency&amp;gt; ...

weixin_44092924的博客 666

AIDD-人工智能药物设计-构建基于机器学习方法的在线预测平台高准确预测药物诱导骨毒性

在此基础上,提取多种药物分子特征,包括分子指纹(如MACCS、Morgan、RDKit、TopologicalTorsion、AtomPairs与Descriptors)及分子图谱,通过Transformer编码器与神经网络进行机器学习模型训练。最后,将训练好的模型部署为在线Web服务器(BoneToxPD),供用户快速预测药物的骨毒性。本研究不仅在骨毒性预测的准确性方面取得了突破,还在模型解释性方面提供了新的视角,通过注意力机制精准识别出影响骨毒性的关键化学基团,推动药物研发领域更安全、更高效的发展。

itwangyang520的博客 1081

SpringBoot基于jar包启动核心原理及流程详解

如今,Spring Boot几乎已成为Java企业级开发的标准框架,它为开发人员提供了极其方便的项目框架搭建、软件集成功能,极大地提升了开发人员的工作效率,减少了企业的运营成本。而Spr...

华章IT官方博客 2359

esp32 python开发环境搭建_eclipse esp32开发环境搭建

安装方法基本是按照官网提供的方法来操作https://github.com/espressif/idf-eclipse-plugin#GettingStarted但是官网的方法安装之后还是不能编译成功的,第一次编译会出现一下问题问题1:Building in: E:\eclipse-workspace\helloworlk\buildcmake -G Ninja -DCMAKE_TOOLCHAIN...

weixin_39978276的博客 1263

ROST_CM6软件之词频分析、社会网络和语义网络分析、情感分析

简介 ROST CM 6是武汉大学沈阳教授研发编码的国内目前唯一的以辅助人文社会科学研究的大型免费社会计算平台。该软件可以实现微博分析、聊天分析、全网分析、网站分析、浏览分析、分词、词频统计、英文词频统计、流量分析、聚类分析等一系列文本分析。 社会网络和语义网络分析(S) 数据 注意,保存时编码要为ANSI 所以这里需要转换一下 准备自定义表与停词表 例如 同时,点击快速分析后,将会弹出网络图 对网络图进行设置 对布局进行设置 对节点、边进行设置 最终效果图 修改 情感分析

积一时之步,臻千里之遥程 9万+

java加载jar包原理_可执行Jar包运行原理

spring boot有一个很方便的功能就是可以将应用打成可执行的jar。那么大家有没想过这个jar是怎么运行起来的呢?本篇博客就来介绍下spring boot可执行jar包的运行原理。1. 打可执行jar包将spring boot应用打成可执行jar包很容易,只需要在pom中加上一个spring boot提供的插件,然后在执行mvn package即可。org.springframework.b...

weixin_31913479的博客 1071

莫兰指数stata命令_一文读懂16个sp系列stata空间计量命令及应用

spcompress:Compress Stata-format shapefile压缩数据成stata格式的shapefile2、Looking at data/观测数据2、Looking at data/观测数据grmap:Graph choropleth maps绘制等值区域图spdistance:Calculator for distance between places计算区域之间距离3...

weixin_39719989的博客 822

idea怎么查看jar打包的路径_SpringBoot,IDEA下打包成可执行JAR,启动原理

前言:项目开发完成,总是需要打包部署的,IDEA直接运行打包失败了(不是你想要的样子),经过尝试,pom.xml中需要做出配置。配置内容(pom.xml): src/main/java **/*.xml true syste...

weixin_39525118的博客 2154

Unity事件总线第一篇:为什么你的游戏需要一个事件总线?

本文探讨了游戏开发中常见的跨模块调用导致代码强耦合的问题。通过一个攻击按钮触发角色攻击、怪物掉血和血条更新的案例,分析了直接调用方式带来的维护困难、扩展性差和模块重用性低等弊端。文章提出使用事件总线(Event Bus)作为解决方案,通过发布-订阅模式实现模块解耦。重构后的代码中,各模块只需与事件总线交互,彼此不再直接依赖。这种设计使得新增功能(如音效)无需修改现有代码,大大提高了系统的可维护性和扩展性,同时增强了模块的重用性,完美体现了开闭原则。

qq_46348216的博客 1298

基于STM32+Qt上位机设计的智慧停车场管理系统(207)

本项目设计了一套基于STM32+Qt上位机的智慧停车场管理系统。该系统融合了先进的嵌入式技术、图像识别技术、数据库技术和移动互联网技术,通过STM32硬件端实时采集车库现场信息,包括车牌识别、车位占用状态监测等,并将数据上传至Qt上位机进行处理与展示。利用MySQL数据库存储车辆出入库记录及车位使用情况,确保数据的安全性和可追溯性;通过Android手机APP为用户提供查询、支付等功能,实现远程交互与便捷服务。

3942

java 运行jar的原理_可执行Jar包运行原理

Spring Boot有一个很方便的功能就是可以将应用打成可执行的Jar。那么大家有没想过这个Jar是怎么运行起来的呢?本篇博客就来介绍下Spring Boot可执行Jar包的运行原理。将Spring Boot应用打成可执行Jar包很容易,只需要在pom中加上一个Spring Boot提供的插件,然后在执行mvn package即可。 org.springframework.bootspring-...

weixin_39966465的博客 890

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

SpringBoot 的jar包为什么可以直接运行?

“文末送书《SpringBoot技术内幕:架构设计与实现原理》”得益于SpringBoot的封装,我们可以只通过jar -jar一行命令便启动一个web项目。再也不用操心搭建tomcat...

程序员闪充宝 2676

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

androidstudio将项目打包成jar包_SpringBoot基于jar包启动核心原理及流程详解

如今,Spring Boot几乎已成为Java企业级开发的标准框架,它为开发人员提供了极其方便的项目框架搭建、软件集成功能,极大地提升了开发人员的工作效率,减少了企业的运营成本。而Spring Boot又极其简单易用,一个新手按照官方文档的指导在十几分钟内就能创建一个可运行的Spring Boot项目。本文带你了解SpringBoot基于jar包启动核心原理及流程。得益于SpringBo...

weixin_31652625的博客 366

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

SpringBoot学习系列-jar包启动原理

打包生成两个jar包 ssmdemo-plus.jar引入了相关第三方依赖。 ssmdemo-plus.jar.original仅包含应用编译后的本地资源 jar包的目录结构 |—— BOOT-INF |—— classes 存放的是应用编译后的class文件 |—— lib 存放的是应用依赖的第三方jar包文件 |——META-INF 存放应用打包信息maven坐...

zhanboring的博客 78

java -jar 工作原理_Spring Boot 可执行 Jar 包运行原理

Spring Boot 有一个很方便的功能就是可以将应用打成可执行的 Jar。那么大家有没想过这个 Jar 是怎么运行起来的呢?本篇博客就来介绍下 Spring Boot 可执行 Jar 包的运行原理。打可执行 Jar 包将 Spring Boot 应用打成可执行 Ja r包很容易,只需要在 pom 中加上一个 Spring Boot 提供的插件,然后在执行mvn package即可。org.sp...

weixin_28950015的博客 240

Spring Boot项目制作Jar包和Jar包结构的分析

1简介 在出差的过程中,在项目执行的初期,由于需要给客户提供一个可执行的程序,由于当时时间的缘故,采用了提供jar包的形式,因为jar包只要通过 java -jar ***.jar 就可以作为一个独立的程序,可以让其他的程序进行调用服务。现在简单的介绍这个jar包的制作过程和jar包中的结构。 2Jar包制作 可参考博客 Springboot项目(包含第三方jar包)打成jar包方法, 2.1项...

不当初 6316

Thinking In Spring Boot 之 Spring Boot 如何启动—JAR 文件详解(一)

Spring Boot 大家应该都知道如何启动。但是为什么通过main方法就能启动呢?请听我细细道来。 一般启动spring Boot 应用的方式有两种: 开发环境 @SpringBootApplication public class FirstAppByGuiApplication { public static void main(String[] args) { Spr...

分享 AI 编程实战、踩坑经验与技术感悟 | 一个工程师的成长笔记 用代码讲故事,用实战验证理论,用图文让技术更易懂 博客即知识库,分享即成长 🌱 1038

当执行 java -jar springBootDemo.jar 后发生了什么 —— 2.从JarLauncher到应用启动类

前言 上一篇文章分析了Jar包里面包含什么,并且说到MANIFES.MF里面的其中一个配置为Main-Class: org.springframework.boot.loader.JarLauncher,但是由于源代码在GitHub上,而国内网速很慢,下载好之后继续看看JarLauncher做了什么。 其中很多细节都讲的比较粗糙,也是第一次遇到这些知识点,有时间以后补充。主要是梳理启动的流程。 分...

Tomonkey的专栏 649

11.jar包和war包的区别

通常是开发时要引用通用类,打成jar包便于存放管理。当你使用某些功能时就需要这些jar包的支持,需要导入jar包。

独孤东方朔的博客 1832
上一篇: Java 常用 Json 解析框架
下一篇: 常用数学公共函数
杨小熊的笔记
博客等级 码龄15年 125粉丝 156原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值