Drools

Drools 7.73.0.Final

简介

一种业务规则管理系统,可对业务规则和复杂的事件进行可靠的评估。在业务场景中,经常有很多复杂,多变的业务规则,Drools可以将复杂多变的业务规则从硬编码中拆解出来,以规则脚本的形式存放到数据库中,使得业务规则的变更不需要修改代码即可完成线上修改。

主要应用场景

  1. 风险控制系统。风险贷款,风险评估。

  2. 反欺诈项目。银行贷款,征信验证。

  3. 决策平台系统。财务结算。

  4. 促销平台。满减,打折,加价购。

解决的问题

  1. 复杂多变的业务规则,硬编码难以维护和修改。

  2. 每次业务规则变更,都需要修改代码,进行上线。

名次解释

规则文件

定义规则时的文件。以.drl为后缀。

Rule Base

规则库。所有在规则文件中定义的规则,都会被导入到规则库中。

Working memory

工作内存,drools规则引擎会从工作内存中获取对象,并且和规则文件中定义的规则进行匹配。

Fact

事实。将一个javaBean导入到工作内存中的对象,即表示是一个事实对象。

Pattern matcher

匹配器。将工作内存中的Fact与规则库中的规则进行匹配,匹配成功的规则将会被激活并加到Agenda中。

Agenda

议程。用于存放匹配成功并激活的规则。

Execution engine

执行引擎。用于执行Agenda中的规则。

Api开发步骤

  1. 获取KieService。

  2. 获取KieContainer。

  3. 获取KieSession。

  4. insert fact。

  5. 触发规则。

  6. 关闭KieSession。

语法

Rule

//同一个包名下面可以相互引用
package order_rules
import cn.skuu.entity.Order

//100元以下,不加分
rule "order score rule1"
when
    //赋值:条件
    $order:Order(price<100)
then
    $order.setScore(0);
    System.out.println("触发了规则,100元以下,不加分");
end

Query

//同一个包名下面可以相互引用
package user_rules
import cn.skuu.entity.User

query "query-1"
    //赋值:条件
    $user:User(id>1)
end

query "query-2"(String name)
    //赋值:条件
    $user:User(id>1 && userName == name)
end

spring boot 集成

添加maven依赖

<drools.version>7.47.0.Final</drools.version>

<dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-spring</artifactId>
    <version>${drools.version}</version>
    <exclusions>
        <!-- 依赖的spring版本全部以spring boot依赖的为准 -->
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </exclusion>
    </exclusions>
</dependency>

bean交给spring 容器管理

import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.*;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;
import org.kie.spring.KModuleBeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import java.io.IOException;

/**
 *  drools自动配置
 *
 * @author dcx
 * @since 2023-03-13 15:57
 **/
@Configuration
public class DroolsAutoConfiguration {
    private static final String RULES_PATH = "rules/";

    @Bean
    @ConditionalOnMissingBean(KieFileSystem.class)
    public KieFileSystem kieFileSystem() throws IOException {
        KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
        for (Resource file : getRuleFiles()) {
            kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + file.getFilename(), "UTF-8"));
        }
        return kieFileSystem;
    }

    private Resource[] getRuleFiles() throws IOException {
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        return resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*");
    }

    @Bean
    @ConditionalOnMissingBean(KieContainer.class)
    public KieContainer kieContainer() throws IOException {
        final KieRepository kieRepository = getKieServices().getRepository();

        kieRepository.addKieModule(new KieModule() {
            @Override
            public ReleaseId getReleaseId() {
                return kieRepository.getDefaultReleaseId();
            }
        });

        KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem());
        kieBuilder.buildAll();

        return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());
    }

    private KieServices getKieServices() {
        return KieServices.Factory.get();
    }

    @Bean
    @ConditionalOnMissingBean(KieBase.class)
    public KieBase kieBase() throws IOException {
        return kieContainer().getKieBase();
    }

    @Bean
    //只存在一个
    @ConditionalOnMissingBean(KieSession.class)
    public KieSession kieSession() throws IOException {
        return kieContainer().newKieSession();
    }

    @Bean
    @ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class)
    public KModuleBeanFactoryPostProcessor kiePostProcessor() {
        return new KModuleBeanFactoryPostProcessor();
    }
}

使用

rule

@Autowired
private KieSession kieSession;

public Order getScore(Order order) {
    //fact加入工作内存
    kieSession.insert(order);
    //匹配
    kieSession.fireAllRules();
    kieSession.dispose();
    return order;
}

query

public void getUser() {
    kieSession.insert(User.builder().id(0).userName("user1").build());
    kieSession.insert(User.builder().id(1).userName("user2").build());
    kieSession.insert(User.builder().id(2).userName("user3").build());
    kieSession.fireAllRules();
    QueryResults queryResults = kieSession.getQueryResults("query-2","user3");
    for (QueryResultsRow queryResult : queryResults) {
        User user = (User) queryResult.get("$user");
        log.info("res:{}", user);
    }
    kieSession.dispose();
}

可视化

workbench是官方提供的可视化规则定制。

docker安装

  1. 查找

docker search drools

“drools-workbench-showcase”是官方配置好的“drools-workbench”,因而在“drools-workbench-showcase”中用户不用自己去注册,直接将账号拿来登录就可以了,而“drools-workbench”不是,它还得需要手动去注册账号,因而使用最多的也就是“drools-workbench-showcase”。

  1. 拉取镜像

docker pull jboss/drools-workbench-showcase

  1. 运行

docker run -p 8080:8080 -p 8001:8001 -d --name drools-workbench-showcase docker.io/jboss/drools-workbench-showcase:latest

  1. 访问

/business-central

  1. 默认账户

用户名:admin

密码:admin

Last updated

Was this helpful?