【Drools】动态规则引擎使用和配置(SpringBoot集成Drools)
前提:自己有一个springBoot的项目.没有的话自己创建即可。
直接上手:
pom.xml添加如下jar包:
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.52.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.52.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>7.52.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>$7.52.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.52.0.Final</version>
</dependency>
为方便测试,可以多添加springboot test依赖(因为下面的例子会用到):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
随便找个地方创建Test测试类
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.api.KieBase;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieSession;
import org.kie.internal.utils.KieHelper;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.HashMap;
import java.util.Map;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DroolsApplicationHelloWordTests {
@Test
public void test() {
EntityInfoVo actualInfoVo = new EntityInfoVo(210137L, false, "规则", "描述");
final KieBase kieBase = getKieSession("rule1", "(a>30||<10)");
KieSession ksession = kieBase.newKieSession();
ksession.setGlobal("ruleResult", actualInfoVo);
Map<String, Object> map = new HashMap<>();
map.put("a", 50);
ksession.insert(map);
ksession.fireAllRules();
//移除session状态
ksession.destroy();
ksession.dispose();
System.out.println("是否命中:"+actualInfoVo.getHit());
}
/**
* @param ruleName 规则名称
* @param rule 规则信息, 如 a>0||b<30
* @return
*/
private KieBase getKieSession(String ruleName, String rule) {
String myRule = "import java.util.Map;\n" +
"global com.example.droolsdemo.entity.EntityInfoVo ruleResult;\n" +
"rule \"%s\"\n" +
" dialect \"mvel\"\n" +
" no-loop false \n" +
" when\n" +
" $fact:Map(%s)\n" +
" then\n" +
"\t ruleResult.setHit(Boolean.TRUE);\n" +
"end";
//生成完整的规则字符串
final String ruleStr = String.format(myRule, ruleName, rule);
KieHelper helper = new KieHelper();
helper.addContent(ruleStr, ResourceType.DRL);
return helper.build();
}
}
实体类:
public class EntityInfoVo implements Serializable {
private Long crowdCode;
/**
* 是否命中
* true:命中
* false:不命中
*/
private Boolean hit;
/**
* 值说明
*/
private String valueDes;
/**
* 规则说明
*/
private String ruleDes;
public Long getCrowdCode() {
return crowdCode;
}
public void setCrowdCode(Long crowdCode) {
this.crowdCode = crowdCode;
}
public Boolean getHit() {
return hit;
}
public void setHit(Boolean hit) {
this.hit = hit;
}
public String getValueDes() {
return valueDes;
}
public void setValueDes(String valueDes) {
this.valueDes = valueDes;
}
public String getRuleDes() {
return ruleDes;
}
public void setRuleDes(String ruleDes) {
this.ruleDes = ruleDes;
}
public EntityInfoVo(Long crowdCode, Boolean hit, String valueDes, String ruleDes) {
this.crowdCode = crowdCode;
this.hit = hit;
this.valueDes = valueDes;
this.ruleDes = ruleDes;
}
public EntityInfoVo() {
}
}
getKieSession方法说明:
1- global com.example.droolsdemo.entity.EntityInfoVo ruleResult;
设置的全局对象,可用于规则走完when后,对该对象进行设置相应的赋值。(比如你要将结果带到外面的代码…可以看:ruleResult.setHit(Boolean.TRUE) 这行代码)
2- dialect :方言,可选 mvel,java 默认java
3- no-loop:是否循环判断,一般情况下都设置为false,因为如果是true 就会对你insert进来的对象进行循环遍历判断,处理不好会造成死循环.
4- 动态规则的重点: helper.addContent(ruleStr, ResourceType.DRL);
test方法说明:
1-
EntityInfoVo actualInfoVo = new EntityInfoVo(210137L, false, "规则", "描述");
ksession.setGlobal("ruleResult", actualInfoVo);
这两个设置规则全局对象。
2-
Map<String, Object> map = new HashMap<>();
map.put("a", 50);
ksession.insert(map);
这几行是将要判断的对象放进去,用于规则判断
3-
执行结果:
注意点:
A- (a>30||<10) 这个规则,表示你要insert的对象,要有a,b两个字段,如果没有就会报错,因为源码里面会去找你insert进去的对象的字段,跟规则的字段对比。当然前面a>30返回true了,后面的b就不需要了,如果改成:a>30&&b<10 这个方法就会报错,修改如下:
Map<String, Object> map = new HashMap<>();
map.put("a", 50);
map.put("b", 50);
ksession.insert(map);
进一步优化
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.api.KieBase;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieSession;
import org.kie.internal.utils.KieHelper;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DroolsApplicationHelloWordTests {
private static Map<String, KieBase> kieCache = new ConcurrentHashMap<>();
@Test
public void test() {
EntityInfoVo actualInfoVo = new EntityInfoVo(210137L, false, "规则", "描述");
final KieBase kieBase = getKieSession("rule1", "(a>30||<10)");
KieSession ksession = kieBase.newKieSession();
ksession.setGlobal("ruleResult", actualInfoVo);
Map<String, Object> map = new HashMap<>();
map.put("a", 50);
ksession.insert(map);
ksession.fireAllRules();
//移除session状态
ksession.destroy();
ksession.dispose();
System.out.println("是否命中:"+actualInfoVo.getHit());
}
/**
* @param ruleName 规则名称
* @param rule 规则信息, 如 a>0||b<30
* @return
*/
private KieBase getKieSession(String ruleName, String rule) {
if (kieCache.get(ruleName) != null) {
return kieCache.get(ruleName);
}
String myRule = "import java.util.Map;\n" +
"global com.example.droolsdemo.entity.EntityInfoVo ruleResult;\n" +
"rule \"%s\"\n" +
" dialect \"mvel\"\n" +
" no-loop false \n" +
" when\n" +
" $fact:Map(%s)\n" +
" then\n" +
"\t ruleResult.setHit(Boolean.TRUE);\n" +
"end";
//生成完整的规则字符串
final String ruleStr = String.format(myRule, ruleName, rule);
KieHelper helper = new KieHelper();
helper.addContent(ruleStr, ResourceType.DRL);
final KieBase build = helper.build();
kieCache.put(ruleName, build);
return build;
}
}
//或者使用无状态的session 这样不需要维护会话的状态
//StatelessKieSession statelessKieSession = kieBase.newStatelessKieSession();
statelessKieSession.execute(object);//类似于ksession.insert(map);
进入源码可以看到:
public void execute(Object object) {
StatefulKnowledgeSession ksession = this.newWorkingMemory();
try {
ksession.insert(object);
ksession.fireAllRules();
} finally {
this.dispose(ksession);
}
}
源码内部帮我们实现了dispose方法
完整代码:
demo
参考文献:
1-官方文档
2 中文文档(忘了在哪下载的了)
链接:https://pan.baidu.com/s/11Ex8a5aOc0HDsi2L73UQcQ
提取码:rhao
上一篇: 软件更新调用专用贴子..
下一篇: 【专题】动态DP