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

背景和需求:

上半年在我们的钱包app里做了一个类似余额宝的功能,下半年开始要推广了,和大部分公司的推广手段一样,邀请新用户开户成功之后给推广者发奖金;举个例子,余额宝的年化收益是 1.7% p.a,邀请一个新用户年化利息就加 1%,邀请2个加 2%......当然有最大限制。。用户今天余额是10块钱,今天推广了5个人,那么用户明天的余额就是(实际比这个复杂点):

本金:10

昨天利息:A = 10 * 1.7% /  365

昨天奖金:B = 10 * 5% / 365

昨天总收入:A + B

需求分析:

1、我这边需要根据 邀请人数计算用户每天能拿到的推广奖金;

2、(扩展)且需要支持以后的其他项目,比如说以后做借呗,需要为借呗计算每一期的信息数据;或者更换了一个新的推广活动,有了新的计算规则。。。总之一句话,就是可以计算 everything

方案一:

由于我们这个计算奖金功能是在A服务里完成的;那么可以在A服务里新建接口,按照类型type去判断是什么场景,然后A服务的同学去编码写每种场景的实现。

但是这样的话,会带来很多问题:

1、A服务的同学只熟悉A服务,对于其他的服务B(借呗业务)不了解,不方便A服务的同学编码;

2、如果是接入方B(借呗业务同学)去A服务里编码自己的业务的话,由于每个服务的工程与项目写法不同,也会给B服务的同学带来编码效率问题

3、所有的业务实现都写在A服务里,每次改动计算规则,哪怕没有A服务的改动,那么A服务也需要重新code、test、deploy...

由此来看,方案一不可取

方案二:

因为是要计算everything,那么我们需要抽象出一个计算接口 calculateService,该接口不依赖任何业务,隔离所有场景,只做计算。

1、我们对外暴露calculateService接口,calculate方法,入参和出参都是map

2、接入方如果想用A服务的calculate接口,需要做以下准备:

(1)接入方需要自行实现 calculateParse 接口,完成自己具体的业务逻辑的编码

(2)需要把具体的业务逻辑的编码,放进A服务的calculate_rule表中;也就是要按照A服务的要求,提供dml文件给A服务的同学

3、A服务的同学需要做的是:

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

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

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

这么做的话,会有以下优点:

(1)A服务只负责提供计算功能,完全隔离业务;

(2)具体的业务,由对应的业务同学进行编码,编码完成之后,提供dml给A同学导入DB中

(3)当某些计算规则需要 增加、修改、删除时,也是通过 sql 文件进行处理

(4)sql文件执行完成,不需要重启服务器,只需要推一下开关即可

(5)减少编码带来的bug,节约coding、testing的时间,提供迭代效率

 

选型

做这个需求的时候,调研了groovy、spring expression language、velocity 三种动态引擎,发现后两种比较适合做一些规则配置,而我这个需求设计到完整的业务逻辑,所以我选择了groovy。

spring expression language

https://www.baeldung.com/spring-expression-language

像我们公司的鉴权,就是用该语言做的;

举个简单的例子,拿用户付款的场景来说,前提是需要用户已存在并且状态是可用的;

一般公司里都是让用户服务暴露 queryUser接口,其他接入方调接口进行判断;

但是如果服务较多有几十个或者上百个,每个服务做鉴权都是重复的逻辑和代码,那这显然是不好的;

而且这还只是最简单的鉴权,还有很多鉴权场景需要判断接口的返回码 or 是否是中国人等多种鉴权的组合和嵌套;

这种情况如果写在代码里的话,后期不好维护和扩展,每次都要改代码,增加bug几率。

如果使用 spring EL 表达式的话,只需要在表里这么配置就OK了。

用户存在且状态可用:UserStatusFactor.exists == true && UserStatusFactor.userStatus  == ENABLE,其中 UserStatusFactor 是我们程序里的类,他有 exists 和 userStatus两个字段,查询相关的表给这两个字段赋值,然后利用spring expression去匹配我们DB里配置的规则即可。

判断接口的返回码 or 是否是中国人:ThirdPartyFactor.reasonCode == 102 or ExternalPerson.nationality == chinese

然后会有很多已经存在的规则之间可以相互组合,相互搭配,扩展性很好,给某些场景增加或修改鉴权规则时,只需要修改sql,不需要改变代码。除非是那种之前一直没有过的鉴权规则,需要开发一套,然后再给以后的复用。

velocity

是一种基于Java的模板引擎,其使用场景和思路和spring EL类似,用法就直接看教程了http://velocity.apache.org/

groovy

https://www.bootwiki.com/groovy/index.html

是一个基于Java 虚拟机的敏捷动态语言

无缝集成 所有已经存在的 Java 对象和类库

直接编译成 Java 字节码,这样可以在任何使用 Java 的地方使用 Groovy 。

在开发 Web,GUI,数据库或控制台程序时 通过减少框架性代码 大大提高了开发者的效率。

 

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

maple 枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值