2023年6月30日发(作者:)
实现⼀个规则引擎的可视化具体⽅案在介绍这个⽅案之前,得先简单了解⼀下什么是规则引擎什么是规则引擎?简单的说,规则引擎所负责的事情就是:判定某个数据或者对象是否满⾜某个条件,然后根据判定结果,执⾏不同的动作。例如:对于刚刚在⽹站上完成购物的⼀个⽤户(对象),如果她是 "⼥性⽤户 并且 (连续登录天数⼤于10天 或者 订单⾦额⼤于200元 )" (条件) , 那么系统就⾃动给该⽤户发放⼀张优惠券(动作)。在上⾯的场景中,规则引擎最重要的⼀个优势就是实现“条件“表达式的配置化。如果条件表达式不能配置,那么就需要程序员在代码⾥⾯写死各种if... ,如果条件组合特别复杂的话,代码就会很难维护;同时,如果不能配置化,那么每次条件的细微变更,就需要修改代码,然后通过运维⾛发布流程,⽆法快速响应业务的需求。在groovy脚本的⽅案中,上⾯的场景可以这么实现:1)定义⼀个groovy脚本:[code]def validateCondition(args){return args.⽤户性别 == "⼥性" && (args.连续登录天数>10 || args.订单⾦额 > 200);}2)通过Java提供的 ScriptEngineManager 对象去执⾏ groovy 3.0.7 /* * * @params condition 从数据库中读出来的条件表达式 */private Boolean validateCondition(String condition){ //实际使⽤上,ScriptEngineManager可以定义为单例 ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = ineByName(scriptLang); Map args = new HashMap<>(); ("⽤户性别", "⼥性"); ("连续登录天数", 11); ("订单⾦额", 220); (script); return ((Invocable) engine).invokeFunction("validateCondition", args);}在上⾯的groovy脚本中,经常需要变动的部分就是 ”args.⽤户性别 == "⼥性" && (args.连续登录天数>10 || args.订单⾦额 >200)“ 这个表达式,⼀个最简单的⽅案,就是在后台界⾯提供⼀个⽂本框,在⽂本框中录⼊整个groovy脚本,然后保存到数据库。但是这种⽅案有个缺点:表达式的定义有⼀定门槛。对于程序员来说,这⾃然是很简单的事,但是对于没接触过编程的业务⼈员,就有⼀定的门槛了,很容易录⼊错误的表达式。这就引出了本⽂的另⼀个话题,如何实现bool表达式的可视化编辑?如何实现bool表达式的可视化编辑?⼀种⽅案就是对于⼀个指定的表达式,前端⼈员进⾏语法解析,然后渲染成界⾯,业务⼈员编辑之后,再将界⾯元素结构转换成表达式。然⽽,直接解析语法有两个确定:1)需要考虑的边界条件⽐较多,⼀不⼩⼼就解析出错。2)⽽且也限定了后端可以选⽤的脚本语⾔。例如,在上⾯的⽅案中选⽤的是groovy,它使⽤的"与"运算符是 && , 假如某天有⼀种性能更好的脚本语⾔,它的"与"运算符定位为 and ,那么就会需要修改很多表达式解析的地⽅。另⼀种⽅案,是定义⼀个数据结构来描述表达式的结构(说了这么多,终于来到重点了): { "all": [ { "any": [ { "gl": ["连续登录天数", 10] }, { "gl": ["订单⾦额", 200] } ]}, { "eq": ["⽤户性别", "⼥性"] } ]}然后,使⽤递归的⽅式解析该结构,对于前端开发,可以在递归解析的过程中渲染成对应的界⾯元素;对于后端⼈员,可以⽣成对应的bool表达式,有了bool表达式,就可以使⽤预定的脚本模板,⽣成最终的规则。// 模板的例⼦def validateCondition(args){return $s;}/** * 动态bool表达式解析器 */public class RuleParser { private static final Map operatorMap = new HashMap<>(); private static final ObjectMapper objectMapper = new ObjectMapper(); static { ("all", "&&"); ("any", "||"); ("ge", ">="); ("gt", ">"); ("eq", "=="); ("ne", "!="); ("le", "<="); ("lt", "<"); } /** * 解析规则字符串,转换成表达式形式 * ⽰例: * 输⼊: * { "any": [ * { "all": [ * { "ge": ["A", 10] }, * { "eq": ["B", 20] } * ]}, * { "lt": ["C", 30] }, * { "ne": ["D", 50] } * ]} * * 输出: * ( A >= 10 && B == 20 ) || ( C < 30 ) || ( D != 50 ) * @param rule 规则的json字符串形式 * @return 返回 bool 表达式 * @throws IOException 解析json字符串异常 */ public static String parse(String rule) throws IOException { JsonNode jsonNode = ee(rule); return parse(jsonNode); } /** * 解析规则节点,转换成表达式形式 * @param node Jackson Node * @return 返回bool表达式 */ private static String parse(JsonNode node) { // TODO: ⽀持变量的 ”arg.“ 前缀定义 if (ct()) { Iterator<> it = (); if(t()){ entry = (); List arrayList = new ArrayList<>(); for (JsonNode jsonNode : ue()) { (parse(jsonNode)); } return "(" + (" " + (()) + " ", arrayList) + ")"; } else { // 兼容空节点:例如 {"all": [{}, "eq":{"A","1"}]} return " 1==1"; } } else if (eNode()) { return (); } return ""; }以上就是本⽂要阐述的全部内容,对于这个话题,如果你有这⽅⾯的经验或者更好的⽅案,也请多多指教,谢谢!到此这篇关于如何实现⼀个规则引擎的可视化的⽂章就介绍到这了,希望对你有帮助,更多相关规则引擎可视化内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章,希望⼤家以后多多⽀持!
发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1688107515a82585.html
评论列表(0条)