天天看点

规则引擎 drools_Drools规则引擎入门指南(一)引入依赖创建配置类HelloWord基础学习

规则引擎 drools_Drools规则引擎入门指南(一)引入依赖创建配置类HelloWord基础学习

学习更多Java干货,戳上面的 蓝色字题关注我!

最近项目需要增加风控系统,在经过一番调研以后决定使用Drools规则引擎。因为项目是基于SpringCloud的架构,所以此次学习使用了SpringBoot2.0版本结合Drools7.14.0.Final版本。

引入依赖

<dependency>    <groupId>org.droolsgroupId>    <artifactId>drools-coreartifactId>    <version>7.14.0.Finalversion>dependency><dependency>    <groupId>org.kiegroupId>    <artifactId>kie-springartifactId>    <version>7.14.0.Finalversion>dependency>           

创建配置类

@Configurationpublic 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() {            public ReleaseId getReleaseId() {                return kieRepository.getDefaultReleaseId();            }        });        KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem());        kieBuilder.buildAll();        return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());    }    @Bean    @ConditionalOnMissingBean(KieBase.class)    public KieBase kieBase() throws IOException {        return kieContainer().getKieBase();    }    @Bean    @ConditionalOnMissingBean(KieSession.class)    public KieSession kieSession() throws IOException {        KieSession kieSession = kieContainer().newKieSession();        return kieSession;    }    @Bean    @ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class)    public KModuleBeanFactoryPostProcessor kiePostProcessor() {        return new KModuleBeanFactoryPostProcessor();    }    public KieServices getKieServices() {        System.setProperty("drools.dateformat","yyyy-MM-dd");        return KieServices.Factory.get();    }}           

在这个时候我们的基本环境已经搭建好了,接下来我们一起来学习Drools吧

HelloWord

程序员的世界里,我们学习任何一门语言都是以HelloWord开启的,本次学习也不例外。

1.创建规则文件

Drools的规则文件是以*.drl结尾的文件,我们来看一个最简单的规则文件中都是包含什么。

通常来说,我们会把规则文件放在resources资源文件夹下,这里呢我们在resources文件夹下新建一个rules文件夹,然后再新建一个HelloWord.drl文件

package rules;import cn.org.zhixiang.entity.User;import java.lang.String;import java.util.List;rule "hello,word"    when        eval(true)    then        System.err.println("hello,word!");end           
  1. 规则文件,就是我们新建的这个HelloWord.drl可以理解为一个Java类
  2. package,这个跟Java中的包名是差不多的
  3. import,此文件中需要的类。
  4. rule,可以理解为给这个规则起的一个名字,一个规则文件中可以包含多个rule。
  5. when,when下面可以放置一些条件判断的表达式以及定义一些变量什么的。如果里面内容为空的话则会默认添加一个eval(true)代表一个为true的表达式
  6. then,当when下面的表达式为true是then下方的代码才会执行,在这里可以直接编写Java代码(代码所需要的类通过import引入),当然也可以使用when模块定义的一些变量
  7. end 代表规则hello,word的结束。

2.Java调用

现在我们的规则文件写好以后就可以在Java中来进行调用了。

1. 新建一个测试类DroolsApplicationHelloWordTests

@RunWith(SpringRunner.class)@SpringBootTestpublic class DroolsApplicationHelloWordTests {    @Autowired    KieSession kieSession;}           

上方注入的kieSession对象就是以后与Drools打交道最常用的一个对象了,通过它可以直接操作在配置类kieFileSystem方法中加载的所有的规则文件

2. 编写测试代码

@Testpublic void testHelloWord() {    kieSession.fireAllRules();}           

kieSession.fireAllRules方法是执行所有的规则,在运行了这个测试方法之后我们应该就可以看到控制台打印的一句hello,word!了

基础学习

1. 向规则文件传参

1. 在entity包下新增一个User的实体类

public class User {    private String name;    private int age;    public User(String name, int age) {        this.name = name;        this.age = age;    }    //省略getter,setter}           

2. 在hello,word规则下方再次新建一个规则user

rule "user"    when      $u:User(name=="张三",age==18)    then        $u.setName("李四");        System.err.println("hello,word:"+$u.getName());end           

$u:User(name==“张三”,age==18)的意思就是当存在一个user对象,并且它的name属性等于张三age等于18时就把这个对象赋值给$u。

在下方的then模块,如果上方的条件成立时就把$u的name属性更新一下,然后打印。

3. 编写测试代码

@Testpublic void testUser() {    User user=new User("张三",18);    kieSession.insert(user);    kieSession.fireAllRules();    System.err.println("规则执行完毕后张三变为了:"+user.getName());}           

我们可以使用kieSession.insert方法向规则文件中传参,然后在调用方法后你会发现在规则文件中更改的值在Java代码中也被更改了。

4. 存在的小问题

可能你会发现上方代码执行的时候连那句helloword也打印了,为什么呢,这是因为HelloWord那条规则没有验证条件再加上kieSession.fireAllRules()本来就是执行所有被加载的规则的。那么避免这种情况的办法就是执定本次执行的规则

@Test    public void testOneRule() {        User user=new User("张三",18);        kieSession.insert(user);        kieSession.fireAllRules(new RuleNameEndsWithAgendaFilter("user"));    }           

上方的user就是指定的本次执行的规则名称了。

5.扩展操作

上方我们通过RuleNameEndsWithAgendaFilter对象成功指定了需要执行的规则文件,其实通过查看此对象的源码我们发现这个对象是AgendaFilter的一个实现类,决定执不执行一个规则的条件是accept方法返回的boolean值决定的。

所以说如果我们希望可以一次批量匹配多个规则的话可以通过继承AgendaFilter重写accept方法哦

2. 常用运算符

1. 连接符

Drools中存在的三种连接符,上方的代码中我们已经使用过一个了,那就$u:User(name==“张三”,age==18)中的逗号,这里的逗号其实就是and的意思。另外的两个运算符就是&&和||,相信它们两个的意思不用我来介绍了吧。

不过有一点需要注意的是&&和|| 和逗号,不能同时出现。要不你选择用&&和||要不就只用逗号, 。

2. 类型比较操作符

1.首先就是,==,!=,>=,<=这六个

它们是配合eval使用的,比如上方我们使用的eval(true)就是直接返回的true。当我们比较常量时可以使用eval(u.age>b.age)

2. contains not contains

contains用于判断对象的某个字段是否包含另外一个对象

rule "contains"    when      $s:String()      $u:User(name contains $s)    then        System.err.println("用户张三存在");end           
@Test    public void testContains() {       String name="张三";        User user=new User("张三",18);        kieSession.insert(name);        kieSession.insert(user);        kieSession.fireAllRules(new RuleNameEndsWithAgendaFilter("contains"));    }           

not contains顾明思议就是不包含

3. memberOf not memberOf

memberOf用于判断对象的某个字段是否存在一个集合中

rule "memberOf"    when      $list:List()      $u:User(name memberOf $list)    then        System.err.println("用户李四存在");end           
@Test    public void testMemberOf() {        List list=new ArrayList();        list.add("张三");        list.add("李四");        User user=new User("李四",18);        kieSession.insert(list);        kieSession.insert(user);        kieSession.fireAllRules(new RuleNameEndsWithAgendaFilter("memberOf"));    }           

not memberOf顾明思议就是不存在

3. matches not matches

matches就是用于匹配正则表达式的了

rule "matches"    when      $u:User(name matches "张.*")    then        System.err.println("用户张xx存在");end           
@Test   public void testMatches() {       User user=new User("张三",18);       kieSession.insert(user);       kieSession.fireAllRules(new RuleNameEndsWithAgendaFilter("matches"));   }           

not matches不用我说了吧

点击下方“阅读原文”查看源码!!!