likes
comments
collection
share

浅浅学习Spring下Drools规则引擎使用

作者站长头像
站长
· 阅读数 2

背景

近期偶然看到一个介绍了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规则测试:

浅浅学习Spring下Drools规则引擎使用

浅浅学习Spring下Drools规则引擎使用

Teenager规则测试:

浅浅学习Spring下Drools规则引擎使用

浅浅学习Spring下Drools规则引擎使用