浅浅学习Spring下Drools规则引擎使用
背景
近期偶然看到一个介绍了Drools规则引擎的视频。之前在上家公司也接触过一点点,场景主要是配合工作流引擎使用,用于在特定节点判断该由谁负责审批。
规则引擎在业务研发中使用频率还是比较高的,尤其是面对复杂、需灵活变更的场景更加适合。所以趁着还算热乎,赶紧再熟悉一小下。
Drools--java语言开发的开源业务规则引擎
DROOLS(JBOSS RULES )具有一个易于访问企业策略、易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快、效率高。业务分析师或审核人员可以利用它轻松查看业务规则,从而检验是否已编码的规则执行了所需的业务规则。(www.drools.org.cn/)
入门
步骤1: 引入依赖
<!-- Drools依赖 -->
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.61.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-spring</artifactId>
<version>7.61.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.61.0.Final</version>
</dependency>
步骤2:增加kieContainer配置
KieContainer是Drools规则引擎的容器,它用于加载和管理规则文件。
通过KieContainer,我们可以获取到规则文件中定义的规则和规则集,并创建相应的KieSession对象。
KieContainer通常在应用程序启动时创建,并在整个应用程序的生命周期中重复使用。
@Bean
public KieContainer kieContainer() {
KieServices kieServices = KieServices.get();
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
// 配置规则文件所在路径 /src/main/resources/myrules/rules.drl
kieFileSystem.write(ResourceFactory.newClassPathResource("myrules/rules.drl"));
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem).buildAll();
KieModule kieModule = kieBuilder.getKieModule();
return kieServices.newKieContainer(kieModule.getReleaseId());
}
步骤3: 编写规则文件drl
更加复杂的编写规则可参考: www.drools.org.cn/161.html 这里可以通过全局变量global的方式将SpringBean注入到规则文件中使用。
package myrules;
import com.rules.engine.DroolsTestService
import com..Person;
// 注入Spring管理的Bean
global com.rules.engine.DroolsTestService myService;
rule "Adult Rule"
when
// 将规则赋值给$person变量
$person : Person()
// 当参数中的age >=18时,进入then处理
Person(age >= 18)
then
// 调用Spring管理的Service处理
myService.elderThan18($person);
System.out.println("The person is an adult");
end
rule "Teenager Rule"
when
// 将规则赋值给$person变量
$person : Person()
// 当参数中的age <18时,进入then处理
Person(age < 18)
then
// 调用Spring管理的Service处理
myService.youngerThan18($person);
System.out.println("The person is a teenager");
end
步骤4: 规则触发
这里核心是基于kieSession触发规则。
KieSession是Drools规则引擎的执行环境,它用于执行规则。在KieSession中,我们可以插入事实(Person),并调用规则引擎来匹配规则并执行匹配的规则。
KieSession提供了多种执行规则的方法,例如fireAllRules()用于执行所有匹配的规则。KieSession通常在需要执行规则的时候创建,并在执行完规则后关闭。
也就是说,KieContainer用于加载和管理规则文件,而KieSession则提供了规则的执行环境,用于插入事实并执行规则。通过这两个对象的配合使用,我们可以实现规则的加载、管理和执行。
@Service
@Slf4j
public class DroolsService {
@Autowired
private KieContainer kieContainer;
/**
* 规则中需要使用的SpringBean
*/
@Autowired
private DroolsTestService droolsTestService;
/**
* 该方法用于将给定的Person对象应用到Drools规则中,并触发规则的执行。
* @param person
*/
public void applyRules(Person person) {
// 创建一个KieSession
KieSession kieSession = kieContainer.newKieSession();
try {
// 通过设置全局变量到规则文件中去
kieSession.setGlobal("myService", droolsTestService);
// 添加规则运行时事件监听器,用于调试
kieSession.addEventListener(new DebugRuleRuntimeEventListener());
kieSession.addEventListener(new DebugAgendaEventListener());
// 将变量插入到规则中
kieSession.insert(person);
// 触发规则
kieSession.fireAllRules();
} catch (Exception e) {
log.error("applyRules error", e);
} finally {
kieSession.dispose();
}
}
}
步骤5: 验证一下
规则使用使用到的Service 代码
@Service
@Slf4j
public class DroolsTestService {
public void youngerThan18(Person person) {
person.setName(person.getName() + "<----> youngerThan18");
}
public void elderThan18(Person person) {
person.setName(person.getName() + "<----> elderThan18");
}
}
触发使用的controller
@RestController
@RequestMapping(value = "/ruleEngine")
public class RuleEngineController {
@Autowired
private DroolsService droolsService;
@PostMapping("/test")
public Person test(@RequestBody Person person) {
droolsService.applyRules(person);
return person;
}
}
可以通过日志判断规则的执行情况,可以看到规则是命中了adult规则,并且也执行到了我们的Service中。 Adult规则测试:
Teenager规则测试: