前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个基于Spring实现的热更新插件开发框架

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

作者头像
阿提说说
发布2024-09-11 15:19:47
860
发布2024-09-11 15:19:47
举报
文章被收录于专栏:Java技术进阶

前言

对于其他解释性语言来说,热更新根本不是什么事,但对于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控制器

代码语言:javascript
复制
@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

代码语言:javascript
复制
@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定时任务

代码语言:javascript
复制
@Slf4j
@Component
public class TaskDemo {

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

定时任务运行

使用JNI加载dll

代码语言:javascript
复制
    @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文件中增加:

代码语言:javascript
复制
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.39</version>
        </dependency>

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

代码语言:javascript
复制
    @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来使用数据库

代码语言:javascript
复制
@Mapper
public interface TestMapper extends BaseMapper<User> {

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

编写xml,xml要放在跟Mapper类一起

如果放到resources中,路径要跟Mapper类一样

代码语言:javascript
复制
<?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 中增加接口

代码语言:javascript
复制
    @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

代码语言:javascript
复制
@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

插件事件监听

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

代码语言:javascript
复制
/**
 * 插件事件监听
 * @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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-09-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • spring-hot-plugin
    • Controller控制器
      • 各类@Service、@Component
        • @Scheduled定时任务
          • 使用JNI加载dll
            • 使用第三方Jar包
              • 编写@Mapper
                • 插件事件监听
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档