Drools是一款基于Java语言的开源的规则引擎,可以将复杂且多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件或者特定的存储介质中(eg:数据库表),使得业务规则的变更不需要修正项目代码,重启服务器就可以在线上环境立即生效。可以理解为动态代码(动态业务)。

规则引擎的核心目的之一就是将业务决策从程序代码中分离出来,使其代码与业务解耦合。通过特定的语法内容编写业务模块,由API进行解析并对外提供执行接口,再接收输入数据、进行业务逻辑处理并返回执行结果。

常见的规则引擎

IBM的iLog,商业产品

Drools,开源

最近比较火的FLink CEP,开源

Easy Rule,开源

阿里的qlexpress,开源

SpringBoot整合Drools初步实战

1.引入maven依赖

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.5.12</version>        <relativePath/>    </parent>    <groupId>com.mfc</groupId>    <artifactId>drools-test</artifactId>    <version>0.0.1-SNAPSHOT</version>    <name>drools-test</name>    <description>Demo project for Spring Boot</description>    <properties>        <java.version>8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter</artifactId>        </dependency>
       <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>
       <dependency>            <groupId>org.drools</groupId>            <artifactId>drools-compiler</artifactId>            <version>7.14.0.Final</version>        </dependency>
       <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <version>1.18.20</version>            <scope>compile</scope>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>        </dependency>        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>RELEASE</version>            <scope>test</scope>        </dependency>
   </dependencies>
   <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build>
</project>

2.编写配置类

package com.mfc.droolstest.config;
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.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;
@Configurationpublic class DroolsConfig {
   private static final String RULES_PATH = "rules/";
   @Bean    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();        final Resource[] resources = resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*");        return resources;
   }
   @Bean    public KieContainer kieContainer() throws IOException {
       final KieRepository kieRepository = getKieServices().getRepository();        kieRepository.addKieModule(new KieModule() {            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    public KieBase kieBase() throws IOException {        return kieContainer().getKieBase();    }
   @Bean    public KieSession kieSession() throws IOException {        return kieContainer().newKieSession();    }}

3.新建实体

package com.mfc.droolstest.domain;
import lombok.Data;
@Datapublic class Member {    private String name;    private int sex;    private String drlType;}

4.resources目录新建rules目录

图片

5.编写规则文件

package rules
import com.mfc.droolstest.domain.Memberdialect  "java"
rule "man"    when        $p : Member(sex == 1 && drlType == "member")    then        System.out.println($p.getName() + "性别男");end

6.单元测试(只要正常输出,表示整合是Ok的,接下来就可以任意应用了)

package com.mfc.droolstest;
import com.mfc.droolstest.domain.Member;import org.junit.runner.RunWith;import org.junit.Test;import org.kie.api.runtime.KieSession;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)@SpringBootTest(classes = DroolsTestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)public class DroolsTestApplicationTests {
   @Autowired    private KieSession session;
   @Test    public void member() {
       Member people = new Member();        people.setName("MFC");        people.setSex(1);        people.setDrlType("member");        //插入        session.insert(people);        //执行规则        session.fireAllRules();    }

}

7.输出结果

MFC性别男