一个基于Spring实现的热更新插件开发框架

news2024/11/12 19:41:54

前言

对于其他解释性语言来说,热更新根本不是什么事,但对于Java来说是多么的不容易,现在使用Java开发的热更新系统,基本使用JS编写脚本,然后用Java的JavaScript引擎来跑脚本。

spring-hot-plugin

现在有一款开源的Spring 热更新插件开发框架spring-hot-plugin,插件

  • 支持编写各类Controller控制器,跟在Spring Boot 中写接口一样
  • 支持热加载普通类、各类Spring Bean,在插件里面写各类@Service、@Component
  • 支持热加载定时任务,在插件里面编写@Scheduled定时任务
  • 支持插件中使用第三方依赖,在插件中使用JNI加载dll,或者使用第三方jar依赖
  • 支持Mybatis、MybatisPlus,在插件中编写@Mapper,控制数据库
  • 提供主程序监听插件启动卸载事件,用于在主程序中跟随插件生命周期控制相关任务

下面演示一下支持的各个特性

Controller控制器

@Slf4j
@RestController
public class IndexController {

    @Resource
    private TestService testService;

    @GetMapping({"/hello"})
    public String hello() {
        return "Hello itsaysay!";
    }
	
    @GetMapping({"/hello/name"})
    public Person helloName() {
        Person person = new Person();
        person.setName("Human");
        String json = JSON.toJSONString(person);
        log.info(json);
        return person;
    }
}    

各类@Service、@Component

@Service
public class TestServiceImpl implements TestService {

    @Resource
    private TestMapper testMapper;
    @Resource
    private TestMapper2 testMapper2;


    @Override
    public User getUser(Integer id) {
        return testMapper.selectById(id);
    }

    @Override
    public User getUserXml(Integer id) {
        return testMapper.selectByIdXml(id);
    }
}

@Scheduled定时任务

@Slf4j
@Component
public class TaskDemo {

    @Scheduled(cron = "0/1 * * * * ?")
    public void task() {
        log.info("task starting");
    }
}

定时任务运行
在这里插入图片描述

使用JNI加载dll

    @GetMapping("/hik/sdk/init")
    public Boolean hikSDKInit() {
        //海康的SDK dll依赖了其他的dll,需要指定目录,放插件包没用
        //只有一个dll的sdk,不需要,可以放在插件包内
        //这是java native的限制
        HCNetSDK hCNetSDK = (HCNetSDK) Native.loadLibrary("HCNetSDK.dll", HCNetSDK.class);
        if (hCNetSDK == null) {
            return false;
        }
        return true;
    }

使用第三方Jar包

pom文件中增加:

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.39</version>
        </dependency>

在Controller 中使用第三方依赖包中的类

    @GetMapping({"/hello/name"})
    public Person helloName() {
        Person person = new Person();
        person.setName("Human");
        String json = JSON.toJSONString(person);
        log.info(json);
        return person;
    }

fastJson 加载后使用

在这里插入图片描述

编写@Mapper

这里我引入MP来使用数据库

@Mapper
public interface TestMapper extends BaseMapper<User> {

    User selectByIdXml(@Param("id") Integer id);
}

编写xml,xml要放在跟Mapper类一起
在这里插入图片描述

如果放到resources中,路径要跟Mapper类一样
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="csdn.itsaysay.demo.plugin.mapper.TestMapper">

    <select id="selectByIdXml" resultType="csdn.itsaysay.demo.plugin.bean.User">
        select * from usertb where id = #{id}
    </select>
</mapper>

在Controller 中增加接口

    @GetMapping("/mp/getUser/{id}")
    public User getUser(@PathVariable("id") Integer id) {
        return testService.getUser(id);
    }

    @GetMapping("/mp/getUserXml/{id}")
    public User getUserXml(@PathVariable("id") Integer id) {
        return testService.getUserXml(id);
    }

编写Service

@Service
public class TestServiceImpl implements TestService {

    @Resource
    private TestMapper testMapper;
    @Resource
    private TestMapper2 testMapper2;


    @Override
    public User getUser(Integer id) {
        return testMapper.selectById(id);
    }

    @Override
    public User getUserXml(Integer id) {
        return testMapper.selectByIdXml(id);
    }
}

MP调用:

在这里插入图片描述

调用XML中的 id

在这里插入图片描述

插件事件监听

在主程序中编写如下代码:


/**
 * 插件事件监听
 * @author jujun.chen
 */
@Slf4j
@Component
public class PluginListener implements vip.aliali.spring.plugin.listener.PluginListener {

    @Override
    public void startSuccess(PluginInfo pluginInfo) {
        log.info("{}--->启动成功", pluginInfo.getId());
    }

    @Override
    public void startFailure(PluginInfo pluginInfo, Throwable throwable) {
        log.info("{}--->启动失败", pluginInfo.getId());
    }

    @Override
    public void stopSuccess(PluginInfo pluginInfo) {
        log.info("{}--->停止成功", pluginInfo.getId());
    }

    @Override
    public void stopFailure(PluginInfo pluginInfo, Throwable throwable) {
        log.info("{}--->停止失败", pluginInfo.getId());
    }
}

通过调用安装、卸载插件接口,控制台打印相应日志

在这里插入图片描述

项目免不掉一些Bug,需要不断迭代更新

项目开源地址:https://github.com/jujunchen/spring-hot-plugin

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

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

相关文章

PDB自启动设置

1、自启动说明 方案一&#xff1a;oracle12.1只能使用触发器 方案二&#xff1a;oracle12.2可用ALTER pluggable DATABASE ALL save state; 高版本建议优先使用第二种模式 2、触发器模式 CREATE TRIGGER open_all_pdbs AFTER STARTUP ON DATABASE BEGIN EXECUTE IMMEDIA…

通过C# 裁剪PDF页面

在处理PDF文档时&#xff0c;有时需要精确地裁剪页面以适应特定需求&#xff0c;比如去除广告、背景信息或者仅仅是为了简化文档内容。 本文将指导如何使用免费.NET控件通过C#实现裁剪PDF页面。 免费库 Free Spire.PDF for .NET 支持在 .NET (C#, VB.NET, ASP.NET, .NET Core)…

JAVA优化物流生态聚合快递与云洋系统小程序源码

优化物流生态&#xff0c;聚合快递与云洋系统小程序 &#x1f69a; 开篇&#xff1a;物流新生态&#xff0c;从这里启航 在这个快节奏的时代&#xff0c;物流不仅是商品传递的桥梁&#xff0c;更是连接消费者与商家的关键纽带。你是否厌倦了繁琐的物流查询、不稳定的配送时效&…

[Python学习日记-16] 细讲数据类型——元组

[Python学习日记-16] 细讲数据类型——元组 简介 元组的创建和查看 元组的切片 元组的循环 元组的嵌套 简介 有些时候我们的列表数据不想被人修改时怎么办&#xff1f;就可以用元组存放。元组&#xff08;tuple&#xff09;其实是列表的兄弟类型&#xff0c;他们非常的相似…

springboot项目中 前端浏览器访问时遇到跨域请求问题CORS怎么解决?has been blocked by CORS policy

文章目录 现象解决方案1. **全局配置 CORS**2. **使用 CrossOrigin 注解**3. **配置 Spring Security**4. **自定义 CORS 过滤器** Spring Security 6.x 及其后续版本解决方案1. 使用 SecurityFilterChain 配置 CORS2. 重要配置说明3. 在生产环境中的最佳实践 现象 前端浏览器…

【题解】CF2008G

题意翻译 原题链接CF2008G 思路 由于操作次数不限&#xff0c;观察到所有操作都是可逆的&#xff0c;所以可以随便搞。然后观察mex函数&#xff0c;发现让所有数在不重复的情况下尽可能地小是最优的&#xff08;重复就浪费了&#xff09;。      先不考虑重复和 0 0 0&a…

Ali_Yun Port

Ali_Yun Port 云服务器端口

【信创】加装硬盘后如何迁移微信数据到新磁盘 _ 统信 _ 麒麟 _ 方德

原文链接&#xff1a;【信创】Linux加装硬盘后如何迁移微信数据到新磁盘 | 统信 | 麒麟 | 方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在Linux系统中加装新硬盘后&#xff0c;如何将微信等数据迁移到新磁盘的文章。在使用过程中&#xff0c;随着数据量的…

拱式桥安全结构健康监测解决方案

拱式桥作为一种常见的桥梁结构&#xff0c;其拱形设计不仅美观&#xff0c;还具有较高的承载能力。然而&#xff0c;随着使用年限的增加和环境因素的影响&#xff0c;拱式桥的结构健康和稳定需要持续监测和评估。自动化监测技术的应用&#xff0c;可以提升拱式桥的监测效率和准…

快速使用react 全局状态管理工具--redux

redux Redux 是 JavaScript 应用中管理应用状态的工具&#xff0c;特别适用于复杂的、需要共享状态的中大型应用。Redux 的核心思想是将应用的所有状态存储在一个单一的、不可变的状态树&#xff08;state tree&#xff09;中&#xff0c;状态只能通过触发特定的 action 来更新…

代码随想录训练营 Day58打卡 图论part08 拓扑排序 dijkstra(朴素版)

代码随想录训练营 Day58打卡 图论part08 一、拓扑排序 例题&#xff1a;卡码117. 软件构建 题目描述 某个大型软件项目的构建系统拥有 N 个文件&#xff0c;文件编号从 0 到 N - 1&#xff0c;在这些文件中&#xff0c;某些文件依赖于其他文件的内容&#xff0c;这意味着如果…

用Python实现时间序列模型实战——Day 18: 时间序列中的季节性与周期性预测

一、学习内容 1. 季节性调整与周期性预测 季节性调整 是在时间序列分析中常用的技术&#xff0c;旨在去除数据中因季节性波动导致的周期性变化&#xff0c;使数据更易于解释和预测。通常&#xff0c;我们可以使用季节性分解方法来分离时间序列中的趋势、季节性和随机成分。 …

JAVA实现压缩包解压兼容Windows系统和MacOs

目标&#xff1a;JAVA实现压缩包解压获取图片素材 问题&#xff1a;Windows系统和MacOs压缩出来的zip内容有区别 MacOs会多出来 以及本身一个文件夹 而windows则不会。为了解决这个问题。兼容mac的压缩包增加一层过滤 要知道 ZipInputStream 可以读取 ZIP 文件中的条目&…

KTV 营业明细+员工提成—SAAS本地化及未来之窗行业应用跨平台架构

一、ktv 绩效必要性 1. 激励员工积极性&#xff1a;提成制度能够直接将员工的努力和收入挂钩&#xff0c;促使员工更加积极主动地工作&#xff0c;以获取更高的收入。 2. 提高工作效率和业绩&#xff1a;为了获得更多提成&#xff0c;员工会努力提高工作效率&#xff0c;增加业…

别中招!从“超低利率“到“包过承诺“,揭秘贷款几大陷阱!

今天咱们聊聊贷款时得防的那些坑&#xff0c;免得一不小心就被套路了。你以为找了个靠谱帮手&#xff0c;结果却是步步陷阱&#xff0c;咱们一起来揭秘这些招数&#xff0c;也给大伙儿提个醒。 第一招&#xff0c;低利率诱惑。正常普通信用贷款服务费是2-15%个点内&#xff0c;…

第十七节:学习Hutool上传文件(自学Spring boot 3.x的第四天)

这节记录下如何使用Hutool库上传本地的文件到服务器端&#xff08;因为是练习&#xff0c;所以是本地端&#xff09;。 第一步&#xff1a;引入Hutool库最新版本&#xff0c;通过maven方式。&#xff08;最新版本需去maven仓库查询&#xff09; 第二步&#xff1a;编写一个post…

Django路由访问及查询数据

1、在应用模块下&#xff0c;创建urls文件&#xff0c;用来存放访问路由 2、在项目总访问url里面注册路由 3、在view文件里&#xff0c;定义方法参数 from django.core import serializers from django.db import connection from django.http import HttpResponse, JsonRespo…

【佳学基因检测】在织梦网站中, 创建或修改目录:/var/www/html/cp 失败! DedeTag Engine Create File False

【佳学基因检测】在织梦网站中, 创建或修改目录&#xff1a;/var/www/html/cp 失败&#xff01; DedeTag Engine Create File False 在使用 DedeCMS&#xff08;一个常用的内容管理系统&#xff09;时&#xff0c;如果遇到“创建或修改目录&#xff1a;/var/www/html/cp 失败&…

背靠大众,「半价Model 3」卖爆,小鹏走出低谷

‍作者 |老缅 编辑 |德新 各路消息都在显示&#xff0c;小鹏MONA M03爆单了。 总裁王凤英在庆功宴上喝下了人生第一杯酒。 小鹏MONA产品线负责人透露&#xff0c;上市后的两天内&#xff0c;MONA全国的试驾车累计开了超过10万公里。 在上市后的48小时内&#xff0c;M03获得…

华为OD机试 - 周末爬山 - 广度优先搜索BFS(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…