springboot + groovy 进行动态编程 (二)_groovy 动态加载 mapper-程序员宅基地

技术标签: groovy  

springboot + groovy 进行动态编程 (一)

 本篇文章是编码,上篇文章我们说到 A服务的同学需要做的是:

(1)在项目启动的时候,完成对calculate_rule表的读取,并构造 groovy 对应的xml格式

(2)把构造好的xml,交给spring容器去管理,这样A服务里就可以拿到calculateParse接口的具体实现

(3)当calculate_rule表中的计算代码有改动时,不需要重启A服务,只需要通过一个开关就可以refresh内存里的计算规则即可

那下面我们把他一一实现:

一、A服务里建表

CREATE TABLE `calculate_rule` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `interface_id` varchar(128) NOT NULL COMMENT 'interface_id',
  `bean_name` varchar(64) NOT NULL COMMENT 'bean_name',
  `calculate_rule` text NOT NULL COMMENT 'calculate_rule',
  `calculate_type` varchar(64) NOT NULL COMMENT 'reward',
  `status` varchar(16) NOT NULL DEFAULT 'ENABLE' COMMENT 'ENABLE/DISENABLE',
  `extend_info` varchar(4096) DEFAULT NULL,
  `created_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
  `modified_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='calculate rule';

二、A服务里项目启动时,读取该表,并组装成groovy对应xml的格式,交给spring容器管理

1、实现InitializingBean接口,重写afterPropertiesSet方法

2、查询 calculate_rule 表,拿到 interface_id、bean_name、calculate_rule 数据,并做对象转换

3、 把转换之后的数据放进本地缓存里,方便我们后续使用;并构造groovy格式的xml,加载bean到spring容器

 4、加载bean到spring容器

 5、新增接口calculateParse,接入方如果想接入的话,必须要实现这个接口,实现自己的业务逻辑

6、 对外暴露 calculate接口,接入方需要调该接口,我这里就以 controller 为例了

7、groovy解析引擎

8、DML

INSERT INTO `calculate_rule`(`id`, `interface_id`, `bean_name`, `calculate_rule`, `calculate_type`, `status`, `extend_info`, `created_time`, `modified_time`) VALUES (1, 'B.integration.A.calculate.reward', 'rewardCalculateParser', 'package com.example.demo.groovy.calculate.impl;\n\nimport com.example.demo.entity.request.CalculateRequest;\nimport com.example.demo.entity.response.CalculateResponse;\nimport com.example.demo.groovy.calculate.CalculateParser;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.math.BigDecimal;\nimport java.math.RoundingMode;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 计算推广奖金\n */\npublic class RewardCalculateParser implements CalculateParser {\n\n    @Override\n    public CalculateResponse parse(CalculateRequest request) {\n\n        Map<String, Object> extendInfo = request.getExtendInfo();\n\n        String interfaceId = request.getInterfaceId();\n\n        BigDecimal totalAmount = BigDecimal.ZERO;\n        if (StringUtils.isNotBlank((String) extendInfo.get(\"totalAmount\"))) {\n            totalAmount = new BigDecimal((String) extendInfo.get(\"totalAmount\"));\n        }\n\n        int refererNumber = 0;\n        if (StringUtils.isNotBlank((String) extendInfo.get(\"refererNumber\"))) {\n            refererNumber = Integer.parseInt((String) extendInfo.get(\"refererNumber\"));\n        }\n\n\n        System.out.println(\"进入奖金计算逻辑,总金额为:\" + totalAmount + \",邀请人数为:\" + refererNumber);\n        \n        BigDecimal reward = totalAmount.multiply(new BigDecimal(String.valueOf(refererNumber)))\n                .divide(new BigDecimal(\"100\")).divide(new BigDecimal(\"365\"),4, RoundingMode.HALF_DOWN);\n        CalculateResponse response = new CalculateResponse();\n\n        response.setInterfaceId(interfaceId);\n        Map<String, Object> map = new HashMap<>();\n        map.put(\"reward\", reward);\n\n        response.setExtendInfo(map);\n\n        System.out.println(\"退出奖金计算逻辑,总奖金为:\" + reward);\n        return response;\n    }\n}', 'reward', 'ENABLE', NULL, '2020-07-06 09:27:58.279144', '2020-07-06 13:23:51.311882');

 9、到此为止,主要思路就是这样,启动项目,访问 http://localhost:8888/calculate 测试结果为:

10、为了防止我们以后修改了计算的业务逻辑之后需要重启服务,我们新增一个接口去refresh内存里的计算规则

11、测试refresh,启动工程,访问 http://localhost:8888/calculate 接口,看到计算结果为:

这个时候改变DB里的脚本,把奖金改为 9999,然后访问 http://localhost:8888/refresh 接口刷新;

再次访问 http://localhost:8888/calculate 接口,看到计算结果为:

可以发现我们想要修改计算规则的话,直接把修改之后的脚本放进DB里,然后执行refresh接口即可生效;

实际项目中会可能会有自动化或者平台化的产品来实现refresh功能,但是思路都是一样的。 

12、至此我们的代码完成了,完整代码在gitlab里  https://gitee.com/gane_maple/groovy

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_33101675/article/details/107156878

智能推荐

探索未来云原生 debugging 工具:InCloud-程序员宅基地

文章浏览阅读263次,点赞5次,收藏10次。探索未来云原生 debugging 工具:InCloud项目地址:https://gitcode.com/inbug-team/InCloud项目简介InCloud 是由 InBug Team 开发的一款创新的云原生调试工具。它旨在解决现代分布式系统中复杂的问题,尤其是针对 Kubernetes 环境下的服务定位与故障排查问题。通过提供可视化、动态追踪和实时数据分析的能力,InCloud ...

Vue3通透教程【十八】TS为组件的props标注类型_defineprops ts-程序员宅基地

文章浏览阅读4.1w次,点赞79次,收藏50次。通过TS语法来编写组件的props方法_defineprops ts

Gralloc 总结-程序员宅基地

文章浏览阅读3.9k次。从字面就可以看出来Gralloc接口是为了显示内存分配与释放 – Graphics Allocation。它的主要目的有三个:Ø 为应用分配显示用内存;Ø 可以把显示内存在不同进程间进行映射;Ø 同步通过加载gralloc抽象层(gralloc.xxx.so),可以打开fb设备(/dev/fb0)和gpu设备(/dev/graphic/),fb设备用于操作fram_gralloc

RobotFramework自动化测试各类库关键字整理_robot framework 中的关键字库有哪些类型-程序员宅基地

文章浏览阅读4.1k次,点赞3次,收藏62次。1、browserManagementopen browser:打开浏览器close browser:关闭浏览器go to:跳转到某个URLgo back:相当于浏览器的回退select window:选择窗口close window:关闭窗口wait until keywords succeeds:与选择窗口配合使用,确保能够选中窗口select window main:回到主窗..._robot framework 中的关键字库有哪些类型

LeetCode_每日一题今日份_312.戳气球(没懂)-程序员宅基地

文章浏览阅读137次。题解Javaclass Solution { public int[][] rec; public int[] val; public int maxCoins(int[] nums) { int n = nums.length; val = new int[n + 2]; for (int i = 1; i <= n; i++) { val[i] = nums[i - 1]; }.

初识activiti-程序员宅基地

文章浏览阅读60次。Activity工作流学习要点1. 1个插件在Eclipse中安装Activity插件,让你可以在Eclipse中绘制Activity工作流图2. 1个引擎ProcessEngine对象,Activity工作流引擎。这是Activiti工作的核心。负责生成流程运行时的各种实例及数据、监控和管理流程的运行。所有的操作都是从获取引擎开始的,所以一般会把引擎作为全局变量Proc..._activiti proc_def_id_ 由组成

随便推点

Pytorch学习:torchvison.transforms常用包(ToTensor、Resize、Compose和RandomCrop)_totensor在哪个包里面-程序员宅基地

文章浏览阅读543次。给定平均值: (mean[1],…,mean[n]) 和标准值: (std[1],…,std[n]) 对于 n 通道,该变换将归一化输入 torch.*Tensor 的每个通道,即, output[channel] = (input[channel] - mean[channel]) / std[channel]如果图像是torch tensor,则预计具有[…,H,W]形状,其中…表示任意数量的前导维度,但如果使用非恒定填充,则预计输入最多具有2个前导维度。,H,W]形状,其中…表示任意数量的前导维度。_totensor在哪个包里面

qgis二次开发环境搭建(超级详细)_qt+qgis库开发教程-程序员宅基地

文章浏览阅读6.5w次,点赞24次,收藏234次。 最近有一个项目要求基于qgis+QT进行二次开发开发,要使用到qgis平台。陆陆 续续花了差不多两个多星期,在把开发环境搭建起来。 首先就面临2种选择,一种 到qgis官网下载源码,进行编译,此 情况我走了一般编译成功,但是很麻烦,还有很多问题没有解决。 另外,直接在线下载, 官方网站 编译好的二次开发SDK包。本篇 文章采用的是第2种方法,简单快捷,但..._qt+qgis库开发教程

impala时间函数最全版(强烈建议收藏)_impala 时间函数-程序员宅基地

文章浏览阅读9.2k次,点赞8次,收藏101次。impala时间函数最全版(强烈建议收藏)本文基于impala3.2版本,所有的内置时间函数;文章目录impala时间函数最全版(强烈建议收藏)一、补充概念说明1、date类型和timestamp类型区别2、时区二、获取当前时间戳函数三、时间计算函数四、获取时间指定单位函数五、时间比较函数六、时间格式转换函数一、补充概念说明1、date类型和timestamp类型区别对于一个完整的时间格式来说:2021-02-02 09:59:42.46,前半部分属于date,后半部分属于time;date类型的_impala 时间函数

cURL 超时设置:CURLOPT_CONNECTTIMEOUT 和 CURLOPT_TIMEOUT 的区别-程序员宅基地

文章浏览阅读7.9k次,点赞2次,收藏4次。PHP cURL 的超时设置有两个 CURLOPT_CONNECTTIMEOUT 和 CURLOPT_TIMEOUT,他们的区别是:CURLOPT_CONNECTTIMEOUT用来告诉 PHP 在成功连接服务器前等待多久(连接成功之后就会开始缓冲输出),这个参数是为了应对目标服务器的过载,下线,或者崩溃等可能状况。CURLOPT_TIMEOUT用来告诉成功 PHP 从服务器接收缓冲完成前需要等待多长时间,如果目标是个巨大的文件,生成内容速度过慢或者链路速度过慢,这个参数就会很有用。使用 cURL..

gitlab迁移项目到新组(group)中_git 换group-程序员宅基地

文章浏览阅读2.3w次,点赞4次,收藏10次。1在新group中 new project_git 换group

VMware中如何实现Linux系统与宿主机文件共享_vmwarelinux与宿主机共享内存-程序员宅基地

文章浏览阅读820次。参考:http://hi.baidu.com/fly_2009hui/blog/item/a62b484f0f4ac63baec3ab73.html使用hgfs实现vmare文件传输一法使用vmware(vmware workstation 5)下shared folders功能实现vmware中host与ghost间文件传输,无需任何网络相关设置,不使用任何网络协议,host和gho_vmwarelinux与宿主机共享内存

推荐文章

热门文章

相关标签