Drools规则引擎,网上大把相关的文章介绍,但我感觉不够直白,理解有些困难,且知识点没有集中比较分散、有些还是早前版本的内容,对与新手来说上手可能比较慢,而且比较容易走弯路,故我在深入研究并实践于项目中后,在空闲时间花费精力整理了这篇文章,分享出来,便大家快速上手。
org.kie
kie-spring
7.55.0.Final
public Object checkRule(Object msg) {
List drlContentList=new ArrayList<>();
//当一个Fact对象为集合对象时的判断
//这个是当把某个集合(List)当成一个fact传入工作内存中后,规则有效
drlContentList.add("package zuowenjun.drools.rule.demo\n" +
"import cn.zuowenjun.model.Message;\n" +
"import java.util.List;\n" +
"rule \"test rule 0\"\n" +
"when \n" +
"$list:List(size>0) \n" +
"$msg:Message(createBy==\"zuowj\") from $list \n " +
"then\n" +
"System.out.println(\"hello zuowj! ---rule 0\");\n" +
"$msg.setReplyBy(\"rule 0\");\n" +
"end");
//普通Pattern 模式+字段约束
drlContentList.add("package zuowenjun.drools.rule.demo\n" +
"import cn.zuowenjun.model.Message;\n" +
"rule \"test rule 1\"\n" +
"when \n" +
"$msg:Message(createBy==\"zuowj\")\n " +
"then\n" +
"System.out.println(\"hello zuowj! ---rule 1\");\n" +
"$msg.setReplyBy(\"rule 1\");\n" +
"end");
//accumulate 内联方式(类似for循环处理)
drlContentList.add("package zuowenjun.drools.rule.demo\n" +
"import cn.zuowenjun.model.Message;\n" +
"rule \"test rule 2\"\n" +
"when \n" +
"exists(Message(createBy==\"zuowj\"))\n"+
"$res:String() from accumulate(Message(createBy==\"zuowj\",$cont:content),init(String allContent=\"\";),action(allContent +=$cont;),result(allContent))"+
"then\n" +
"System.out.println($res +\"---rule 2\");\n" +
"end");
//accumulate 普通函数方式
drlContentList.add("package zuowenjun.drools.rule.demo\n" +
"import cn.zuowenjun.model.Message;\n" +
"rule \"test rule 2-2\"\n" +
"when \n" + "accumulate(Message(createBy==\"zuowj\",$id:id);$countNum:count($id);$countNum>1) \n"+
"then\n" +
"System.out.println(\"count number:\"+ $countNum +\"---rule 2-2\");\n" +
"end");
//not,不满足时
drlContentList.add("package zuowenjun.drools.rule.demo\n" +
"import cn.zuowenjun.model.Message;\n" +
"rule \"test rule 3\"\n" +
"when not Message()\n" +
"then\n" +
"System.out.println(\"no message don't say hello! ---rule 3\");\n" +
"end");
//exists,匹配执行一次
drlContentList.add("package zuowenjun.drools.rule.demo\n" +
"import cn.zuowenjun.model.Message;\n" +
"rule \"test rule 4\"\n" +
"when exists(Message(createBy==\"zuowj\"))\n" +
"then\n" +
"System.out.println(\"exists Message(createBy==zuowj) fact! ---rule 4\");\n" +
"end");
//forall,工作内存中所有fact对象必需都满足时才匹配规则
drlContentList.add("package zuowenjun.drools.rule.demo\n" +
"import cn.zuowenjun.model.Message;\n" +
"rule \"test rule 5\"\n" +
"when forall(Message(createBy==\"zuowj\"))\n" +
"then\n" +
"System.out.println(\"for all Message(createBy==zuowj) fact! ---rule 5\");\n" +
"end");
//collect,将工作内存中所有fact对象添加到同一个集合中
drlContentList.add("package zuowenjun.drools.rule.demo\n" +
"import cn.zuowenjun.model.Message;\n" +
"rule \"test rule 6\"\n" +
"when Message() && $msgs:List(size>=9) from collect(Message(createBy==\"zuowj\"))\n" +
"then\n" +
"System.out.println(\"collect all Message fact(size=\" + $msgs.size() +\")! ---rule 6\");\n" +
"end");
KieHelper kieHelper=new KieHelper();
for(String drl:drlContentList){
kieHelper.addContent(drl,ResourceType.DRL);
}
KieBase kieBase = kieHelper.build();
StatelessKieSession kieSession = kieBase.newStatelessKieSession();
if (msg instanceof List){
kieSession.execute((List)msg);
} else{
kieSession.execute(msg);
}
return msg;
}
//单元测试
/**
* @author zuowenjun
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {DroolsDemoApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class RuleTests {
@Autowired
private RuleDemo ruleDemo;
@Test
public void testRule() {
List msgList=new ArrayList<>();
for(int i=1;i
思路:1.定义规则内容(即:规则执行单元),2.定义贯穿整个规则执行链条的上下文,内部就放fact、global等,具体实现参照如下示例代码【注意:如果仅是示例测试代码,并不规范,仅为演示提供思路】,整个规则执行采取:责任链的设计模式,即:每个规则只负责满足自己条件的执行逻辑,最后更新上下文中相关的内容。
//规则链上下文,里面就包含fact集合,全局对象及执行过的rule
public class RuleChainContext {
public List factList;
public static Map global;
public RuleUnit execedRule;
}
//规则执行单元抽象类(这里用抽象类而没有用接口,是因为我要限定组织逻辑,可以理解为模板用法)
public abstract class RuleUnit {
public RuleUnit nextExecedRule;
protected String name;
public abstract String getName();
public abstract boolean matchWhen(RuleChainContext context);
public abstract void doThen(RuleChainContext context);
public final void execute(RuleChainContext context) {
if (matchWhen(context)) {
doThen(context);
}
if (context.execedRule == null) {
context.execedRule = this;
}
context.execedRule.nextExecedRule = this;
}
}
通过单元测试模拟调用:
@Test
public void testDefRules() {
List ruleUnitList = new ArrayList<>();
ruleUnitList.add(new RuleUnit() {
@Override
public String getName() {
name= "rule-1";
return name;
}
@Override
public boolean matchWhen(RuleChainContext context) {
return context.factList.stream().anyMatch(f->f instanceof Integer && 1==(Integer)f);
}
@Override
public void doThen(RuleChainContext context) {
System.out.println("rule[include 1] do");
//TODO:context
}
});
ruleUnitList.add(new RuleUnit() {
@Override
public String getName() {
name= "rule-2";
return name;
}
@Override
public boolean matchWhen(RuleChainContext context) {
return context.factList.stream().anyMatch(f->f instanceof Integer && 2==(Integer)f);
}
@Override
public void doThen(RuleChainContext context) {
System.out.println("rule[include 2] do");
//TODO:context
}
});
RuleChainContext context=new RuleChainContext();
context.factList=new ArrayList<>();
context.factList.add(1);//加入1则触发规则1
context.factList.add(2);//加入2则触发规则2,若减少规则相应减少
for(RuleUnit ruleUnit:ruleUnitList){
ruleUnit.execute(context);
}
System.out.println("result context:\n" + JsonUtils.deserializer(context));
}
最终结果:
rule[include 1] do
rule[include 2] do
result context:
{"factList":[1,2],"execedRule":{"nextExecedRule":{"nextExecedRule":null,"name":"rule-2"},"name":"rule-1"}}
从输出的结果可以看出,还是可以达到规则引擎的简单效果的,当然如果想在生产环境实际应用自己实现的”类规则引擎”代码,实现规则与执行分开,也可将规则执行单元(RuleUnit)实现类单独放到一个JAR包,然后再借助于URLClassLoader实现动态加载并添加自定义的实现规则执行单元(RuleUnit)的类,最后执行即可。【.NET方面的同学实现亦同理】
注:文中相关名词解释来源于网上,并非原创,我这里仅为知识点总结!
可参考相关drools系列文章:
Original: https://www.cnblogs.com/zuowj/p/14949715.html
Author: 梦在旅途
Title: Drools规则引擎实践直白总结
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/592248/
转载文章受原作者版权保护。转载请注明原作者出处!