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

引入依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.14.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-spring</artifactId>
<version>7.14.0.Final</version>
</dependency>

创建配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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() {
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文件

1
2
3
4
5
6
7
8
9
10
11
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

1
2
3
4
5
6
7
8
@RunWith(SpringRunner.class)
@SpringBootTest
public class DroolsApplicationHelloWordTests { @Autowired
KieSession kieSession; }

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

2. 编写测试代码

1
2
3
4
@Test
public void testHelloWord() {
kieSession.fireAllRules();
}

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

基础学习

1. 向规则文件传参

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

1
2
3
4
5
6
7
8
9
10
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

1
2
3
4
5
6
7
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. 编写测试代码

1
2
3
4
5
6
7
@Test
public 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()本来就是执行所有被加载的规则的。那么避免这种情况的办法就是执定本次执行的规则

1
2
3
4
5
6
@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用于判断对象的某个字段是否包含另外一个对象

1
2
3
4
5
6
7
rule "contains"
when
$s:String()
$u:User(name contains $s)
then
System.err.println("用户张三存在");
end
1
2
3
4
5
6
7
8
@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用于判断对象的某个字段是否存在一个集合中

1
2
3
4
5
6
7
rule "memberOf"
when
$list:List()
$u:User(name memberOf $list)
then
System.err.println("用户李四存在");
end
1
2
3
4
5
6
7
8
9
10
@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就是用于匹配正则表达式的了

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

not matches不用我说了吧

本文所有源码:https://github.com/shiyujun/drools

本文出自http://zhixiang.org.cn/,转载请保留

Drools规则引擎入门指南(一)的更多相关文章

  1. Drools规则引擎入门指南(三)——使用Docker部署Workbench

    其实本来我也是打算使用Tomcat来部署Workbench的,但是在网上看了几篇文章,超级繁琐的配置.各种版本.实在看不下去了索性就直接使用Docker来部署了.本次部署的版本是最新稳定版,对应dro ...

  2. Drools规则引擎入门指南(二)

    本篇博客主要讲解Drools常用的属性以及函数 属性 首先我们在resources\rules文件夹下创建一个Property.drl,还有一个DroolsApplicationPropertyTes ...

  3. Drools规则引擎

    一.简介 Drools is a Business Rules Management System (BRMS) solution. It provides a core Business Rules ...

  4. Drools规则引擎-如果判断某个对象中的集合是否包含指定的值

    规则引擎集合相关处理 在实际生产过程中,有很多关于集合的处理场景,比如一个Fact对象中包含有一个集合,而需要判断该集合是否包含某个值.而Drools规则引擎也提供了多种处理方式,比如通过from.c ...

  5. Drools规则引擎-如果Fact对象参数为null如何处理

    问题场景 在技术交流群(QQ:715840230)中有同学提出这样的问题: 往kiesession里面传入fact,如果不做输入检查fact里面有些字段可能是null值.但是如果在外面做输入检查,规则 ...

  6. Drools 规则引擎应用

    规则引擎-drools 1 .场景 1.1需求 商城系统消费赠送积分 100元以下, 不加分 100元-500元 加100分 500元-1000元 加500分 1000元 以上 加1000分 .... ...

  7. Drools 规则引擎应用 看这一篇就够了

    1 .场景 1.1需求 商城系统消费赠送积分 100元以下, 不加分 100元-500元 加100分 500元-1000元 加500分 1000元 以上 加1000分 ...... 1.2传统做法 1 ...

  8. 线上故障排查——drools规则引擎使用不当导致oom

    事件回溯 1.7月26日上午11:34,告警邮件提示:tomcat内存使用率连续多次超过90%: 2.开发人员介入排查问题,11:40定位到存在oom问题,申请运维拉取线上tomcat 内存快照dum ...

  9. drools规则引擎初探

    https://www.cnblogs.com/yuebintse/p/5767996.html 1.drools是什么 Drools是为Java量身定制的基于Charles  Forgy的RETE算 ...

随机推荐

  1. 关于键盘事件对象code值

    e.keyCode || e.which || e.charCode; //IE只有keyCode属性,FireFox中有which和charCode属性,Opera中有keyCode和which属性 ...

  2. 解决Dynamic Web Module 3.1 requires Java 1.7 or newer

    需要检查和确认Eclipse项目属性的java版本和本地jdk的版本一致,以1.7版本为例: 1. 在 Java Build Path的libraries中修改对应的JDK版本为1.7: 2.在Jav ...

  3. 在centos7 部署bbr

    How to Deploy Google BBR on CentOS 7 Published on: Thu, Jan 5, 2017 at 6:34 pm EST CentOS Linux Guid ...

  4. Vmware 无法启动虚拟机 -VMware Workstation and Device/Credential Guard are not compatible.

    因为在学习Linux,起初尝试用Hyper-V安装Linux进行学习,之后为了方便和老师的设置一样,所以改装了VMware,所有初始设置先好后发现,虚机机无法启用. VMware也提示不支持CPU虚拟 ...

  5. python3中 tkinter模块创建window窗体、添加按钮、事务处理、创建菜单等的使用

    开始接触桌面图形界面编程,你可以到安装路径  \lib\tkinter 打开__init__.py 文件了解tkinter 1    tkinter 模块创建窗体,代码如下截图: 运行结果,如有右图显 ...

  6. node-sass 不能正常安装解决办法

    web前端在安装node包时,总是报错,究其原因是node-sass没有被正常安装. 根本原因是国内网络的原因. 最终的解决方法是通过淘宝的npm镜像安装node-sass 首先安装cnpm npm ...

  7. 网页手机wap2.0网页的head里加入下面这条元标签,在iPhone的浏览器中页面将以原始大小显示,并不允许缩放

    网页手机wap2.0网页的head里加入下面这条元标签,在iPhone的浏览器中页面将以原始大小显示,并不允许缩放. <meta name="viewport" conten ...

  8. lwip协议栈移植(1)

    lwip移植分为两类: 1,只移植内核核心,用户应用程序编写只能基于raw/callback api进行 2,移植内核核心和上层API函数模块,用户可以使用所有三种API编程,即 raw/callba ...

  9. C语言中结构体(struct)的几种初始化方法

    转自https://www.jb51.net/article/91456.htm     本文给大家总结的struct数据有3种初始化方法 1.顺序 2.C风格的乱序 3.C++风格的乱序 下面通过示 ...

  10. MySQL数据库(四)多表查询

    两张假设有两张表格A和B,把表格当作一个集合,那么表格中的记录就是集合中的一个元素. 两张表格如下: TableA:TableB: 2.1 内连接(只有一种场景) inner join 或者join( ...