介绍一款基于MVEL简单规则引擎
来源:互联网 发布:如何注册淘宝联盟账号 编辑:程序博客网 时间:2024/05/21 17:37
参考原文A Really Simple But Powerful Rule Engine
MVEL 介绍
最近正好有做规则引擎相关的需求,预研了一下,并找到一些可以满足我需求的技术。引入一个东西——MVEL,怎么定义MVEL表达式,参看MVEL Guide。
来一段代码看一下MVEL的功能,首先引入MVEL解析库:
compile 'org.mvel:mvel2:2.3.2.Final'
下图显示的是本文所用到的Java Bean类:
MVEL example:
@Test public void testMvel() { String rule1 = "(!(input.person.age < 26) && !(input.person.age > 59)) && input.account.ageInMonths > 24"; // compile表达式 异常表达式会报错 Serializable serializable = MVEL.compileExpression(rule1); TarifRequest request = new TarifRequest(); request.setPerson(new Person()); request.setAccount(new Account()); request.getPerson().setAge(30); request.getPerson().setName("jack"); request.getAccount().setAgeInMonths(25); Map<String, TarifRequest> vars = new HashMap<>(); vars.put("input", request); boolean res = (boolean) MVEL.executeExpression(serializable, vars); System.out.println(res); // true String rule2 = "input.person.name == 'tom'"; boolean res1 = (boolean) MVEL.executeExpression(MVEL.compileExpression(rule2), vars); System.out.println(res1); // false String rule3 = "['jack', 'tom', 'hanson'].contains(input.person.name)"; boolean res2 = (boolean) MVEL.executeExpression(MVEL.compileExpression(rule3), vars); System.out.println(res2); //true // MVEL.eval() 直接计算出表达式的值 System.out.println(MVEL.eval(rule2, vars)); //false }
基于MVEL的 简单规则引擎
github源码地址
引入依赖:
compile 'ch.maxant:rules:2.2.1'
1. 执行规则
这个规则引擎比较简单,我居然都能看懂里面的源码,看测试代码:
@Test public void testRules() throws Exception { Rule r1 = new Rule("one", "input.person.age < 26", "YT2011", 3, "ch.maxant.someapp.tarifs", null); Rule r2 = new Rule("two", "input.person.age > 59", "ST2011", 3, "ch.maxant.someapp.tarifs", null); Rule r3 = new Rule("three", "!#one && !#two", "DT2011", 3, "ch.maxant.someapp.tarifs", null); Rule r4 = new Rule("four", "#three && input.account.ageInMonths > 24", "LT2011", 4, "ch.maxant.someapp.tarifs", null); // 默认规则 Rule defaultRule = new Rule("five", "true", "default", -1, "ch.maxant.someapp.tarifs", null); List<Rule> rules = Arrays.asList(r1, r2, r3, r4, defaultRule); // 初始化并用MVEL解析器编译规则 Engine engine = new Engine(rules, true); TarifRequest request = new TarifRequest(); request.setPerson(new Person()); request.setAccount(new Account()); request.setDefaultRuleFlag(true); request.getPerson().setAge(30); request.getAccount().setAgeInMonths(5); // 获取优先级最高的匹配规则 String tarif = engine.getBestOutcome(request); System.out.println(tarif); }
执行大概流程图如下:
当没有规则匹配的时候,就返回默认规则的结果。
2. 使用SubRule编写更复杂的规则
@Test public void testSubRules() throws Exception { Rule rule1 = new SubRule("longdistance", "input.distance > 100", "ch.maxant.produkte", null); Rule rule2 = new SubRule("firstclass", "input.map[\"travelClass\"] == 1", "ch.maxant.produkte", null); Rule rule3 = new Rule("productA", "#longdistance && #firstclass", "productA", 3, "ch.maxant.produkte", null); List<Rule> rules = Arrays.asList(rule1, rule2, rule3); Engine e = new Engine(rules, true); TravelRequest request = new TravelRequest(150); request.put("travelClass", 1); List<Rule> rs = e.getMatchingRules(request); System.out.println(rs); }
规则引擎在解析的时候,SubRule的规则都将被丢弃,只执行rule3的规则,rule3被替换成了:
Rule rule3 = new Rule("productA", "(input.distance > 100) && (input.map["travelClass"] == 1)", "productA", 3, "ch.maxant.produkte", null);
3. 根据规则执行具体的操作
@Test public void testRulesAction() throws Exception { Rule r1 = new Rule("SendEmailToUser", "input.config.sendUserEmail == true", "SendEmailToUser", 1, "ch.maxant.someapp.config", null); Rule r2 = new Rule("SendEmailToModerator", "input.config.sendAdministratorEmail == true and input.user.numberOfPostings < 5", "SendEmailToModerator", 2, "ch.maxant.someapp.config", null); List<Rule> rules = Arrays.asList(r1, r2); final List<String> log = new ArrayList<>(); AbstractAction<ForumSetup, Void> a1 = new AbstractAction<ForumSetup, Void>("SendEmailToUser") { @Override public Void execute(ForumSetup input) { log.add("Sending email to user!"); return null; } }; AbstractAction<ForumSetup, Void> a2 = new AbstractAction<ForumSetup, Void>("SendEmailToModerator") { @Override public Void execute(ForumSetup input) { log.add("Sending email to moderator!"); return null; } }; Engine engine = new Engine(rules, true); ForumSetup setup = new ForumSetup(); Config config = new Config(); setup.setConfig(config); User user = new User(); setup.setUser(user); setup.getConfig().setSendUserEmail(true); setup.getConfig().setSendAdministratorEmail(true); setup.getUser().setNumberOfPostings(2); // executeBestAction() 执行优先级较高规则的action engine.executeAllActions(setup, Arrays.asList(a1, a2));
执行操作也挺简单的,rule的outcome和action的name是一一对应的关系,从匹配到的规则里获取outcome,然后通过outcome获取action,最后action执行具体的操作,这个逻辑没毛病,但感觉rule和action有辣么一点耦合关系,有值得改进的地方,等大伙看源码去深挖吧。
其他的规则引擎:
easy-rules
Rulette
阅读全文
1 0
- 介绍一款基于MVEL简单规则引擎
- 基于SPRING的应用增加简单规则引擎
- 规则引擎介绍
- Java规则引擎介绍
- 规则引擎简单应用
- 基于规则和规则引擎的系统
- 如何基于规则引擎打造规则库
- 介绍一款js模版引擎handlebars
- 规则引擎 (Rule Engine)介绍
- 规则引擎 (Rule Engine)介绍
- QLExpress 规则引擎使用介绍
- Drools规则引擎介绍一
- 为你的基于SPRING的应用增加简单规则引擎(转)
- 为你的基于SPRING的应用增加简单规则引擎
- 基于 Jboss Drools 规则引擎开发框架
- 基于Rete算法的JAVA规则引擎
- 基于Rete算法的JAVA规则引擎
- 基于规则引擎的经营决策管理
- CUDA 学习优化思路
- hihoCoder
- window 安装多个mysql实例
- 快讯 | Java 9 正式发布,新特性解读
- Unity_设计模式_有限状态机_010
- 介绍一款基于MVEL简单规则引擎
- 历届试题 PREV-34 矩阵翻硬币
- Meet Surprise ——最美的惊喜 只送给最美的你
- tools:context用法
- Letter Combinations of a Phone Number--LeetCode
- java 及 web中项目url处理
- LeetCode日常刷题(1)
- VMware vSphere Web Services SDK编程指南(十)- 10.6 配置 iSCSI 存储
- Linux下安装Mysql5.7.x数据库