Drools中文网

基于java的功能强大的开源规则引擎

本站QQ群:
446150745

规则引擎 Drools 使用解析

Drools 5 采用了原生的规则语言,那是一种非 XML 文本格式。在符号方面,这种格式是非常轻量的,它的应用非常简单。可以适用于比较复杂的业务逻辑,本例是用于计费系统的批价,粗略来说,有按次收费,按月收费,按照流量收费,又根据前提不同,使用不同的优惠策略,比如购买了某产品赠送800通话实践100分钟,又有可能根据当月实际使用天数赠送一定的通话时长。如此复杂场景使用规则引擎再好不过了,将动态的都用规则标识,模型里只存有静态数据。

  首先Drools 规则要卸载drl 的文件里,通过程序加载这个drl,然后才可以运算

 

  1. 引入jar包(maven 编译)

 

Xml代码  收藏代码

  1. <dependency>  
  2.     <groupId>org.drools</groupId>  
  3.     <artifactId>drools-core</artifactId>  
  4.     <version>5.0.1</version>  
  5.   </dependency>  
  6.   <dependency>  
  7.     <groupId>org.drools</groupId>  
  8.     <artifactId>drools-compiler</artifactId>  
  9.     <version>5.0.1</version>  
  10.   </dependency>  

 2. 包装下drools

 

 

Java代码  收藏代码

  1. public class RuleRunner {  
  2.       
  3.     public RuleRunner() {  
  4.     }  
  5.     private static final String RULES_FILE=“rules/charge.drl”;  
  6.       
  7.         public void runRules(Object[] facts){  
  8.   
  9.             KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();  
  10.             KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();  
  11.             System.out.println( “Loading file: “ + RULES_FILE );  
  12.             kbuilder.add( ResourceFactory.newClassPathResource( RULES_FILE,RuleRunner.class ),ResourceType.DRL );  
  13.             if (kbuilder.hasErrors() ) {  
  14.                 throw new ServiceException(“charge.drl is a invalid rule file!”);  
  15.             }  
  16.             Collection<KnowledgePackage> pkgs = kbuilder.getKnowledgePackages();  
  17.             kbase.addKnowledgePackages( pkgs );  
  18.             StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();  
  19.             for ( int i = 0; i < facts.length; i++ ) {  
  20.                 Object fact = facts[i];  
  21.                 System.out.println( “Inserting fact: “ + fact );  
  22.                 ksession.insert( fact );  
  23.             }  
  24.             ksession.fireAllRules();  
  25.         }  
  26.     }  

 

 3. 调用这个封装进行异步的规则处理

 

 

 

 

 

 

 

Java代码  收藏代码

  1. Object[] facts={chargeRulesModel,chargePriceResult};  
  2.         new RuleRunner().runRules(facts);  

 

 

 facts 就是要传入传出的对象。

 

  4. 一个规则的解析

Java代码  收藏代码

  1. #created on: 2010426  
  2. package charge  
  3.   
  4. #list any import classes here.  
  5. import java.math.BigDecimal;  
  6.   
  7. rule “rule_800yz:be707 -2” #800月租费优惠<span style=“color: #ff0000;”> 规则头注释</span>  
  8.     when   <span style=“color: #ff0000;”>#条件</span>  
  9.         $chargeModel : ChargeRulesModel($pricePlan:pricePlan,$featureList:featureList,eval($pricePlan.getPricePlanMain().getRuleCode().equals(“rule_800yz”)),eval(String.valueOf($featureList.get(“pp900_1000”)).equals(“10Express”)))  
  10.         $chargeResult : ChargePriceResult()  
  11.     then    <span style=“color: #ff0000;”># 执行逻辑</span>  
  12.     double price=$pricePlan.getCyclePolicy().getPrice();  
  13.       int usage=(Integer)($featureList.get(“pp900_61”));  
  14.       int accountLength=(Integer)($featureList.get(“pp900_59”));  
  15.       int totalAccount=(Integer)($featureList.get(“pp900_88”));  
  16.       int preferValue= Integer.parseInt($pricePlan.getPreferentialPolicy().getPreferentValue());  
  17.       ##总使用量-赠送量>账期     则取账期的使用量作为使用天数  
  18.       if(totalAccount- preferValue>= accountLength){ <span style=“color: #ff0000;”>#使用类似java语言的判断逻辑</span>  
  19.         usage=  accountLength;  
  20.       }else{  
  21.         usage = totalAccount- preferValue;  
  22.       }  
  23.       BigDecimal result=  new BigDecimal(price*usage/accountLength);  
  24.       $chargeResult.setAmount(result);  
  25.       System.out.println(“800月租费优惠”);  
  26. end  

 主要包含注释,条件,要执行的业务,还可以写方法-也就相当于helper类,实际运行时会转化为java类,但是不建议这么写,你完全可以另外写个java类,这里调用就可以了。

 

    到这里就可以完成你的drools 应用了,具体原理下回分解

分享到:  
参考知识库

HTML5知识库920  关注 | 145  收录OpenCV知识库369  关注 | 934  收录软件测试知识库460  关注 | 244  收录C++知识库1215  关注 | 756  收录

评论

19 楼 di1984HIT 2014-09-06  
谢谢你,如果Drools都是这种程序逻辑的话,我觉得还不如用脚本语言来做,一样满足。

18 楼 windhello 2011-03-02  
后面一段的代码怎么这么长?
现在用drools对于数据类型可以自动转换了吧,不用写这么长来进行数据转换

17 楼 lkf520java 2011-02-22  
ltian 写道
我对规则引擎的理念也很感兴趣,但是联想到实际的工作场景,我发现Drools并没有想象中的完美,以下疑问请教众位大侠: 

1.规则里面很多的判据不是直接就具备的,需要一些整理过程,那么这些整理过程到底是在Java类里面做还是在Drools规则里面做?举例子说: 
规则如下: 
如果用户购买的商品中有两个以上的A产品和一个B产品就打85折。 
如果用户购买的商品中有两个以上的B产品,就打8折。 

在实际开发中,我们会把用户准备购买的产品都放在一个列表中。 
如果要应用规则引擎,直接以产品列表为“事实”是最理想的,但是以直接以产品列表为“事实”就需要在规则中插入Java代码,用来整理出产品A和产品B的数量。这样一来,整理产品列表的Java代码就脱离了Java的运行环境,调试起来比较困难。至于更复杂的一些业务规则,用Rule去实现岂不是很难阅读和理解? 

如果我们不直接以产品列表为”事实”,而已采购的产品A和B的数量为事实,那么在调用规则之前,就要在Java中整理产品列表,求出产品A和B的数量,然后将其作为“事实”调用规则。此种方案的缺点就是不够灵活。一旦规则变化了,需要纳入产品C的数量来作为打折的依据,那么既要修改Java中整理产品列表的代码,又要修改规则文件。这也是我们不愿意看到的场面! 

2.所谓的“业务规则”和“业务逻辑”区别到底在哪?是不是所有业务逻辑都可以看做是“业务规则”?如果是这样,那么复杂的业务逻辑或者说复杂的业务规则用规则文件去编写是否合适?如何把握将哪些业务规则用规则引擎去实现的度? 

3. 如果要推入工作内存的事实量较大,或者需要用到的规则量较大,规则引擎的性能可否满足要求呢? 

4. “部门经理(角色)能够批准2天以内的请假,总经理(角色)可以批准2天以上的请假”,这样的规则算不算业务规则?这样的规则中,什么是事实,什么是结论?在工作流的场景下,我期望的是给出申请的请假天数,然后根据业务规则找出可以批准的角色,然后将工作任务发给该角色。那么规则引擎是否具有这样类似的查询功能呢?或者我该如何去实现? 

这位仁兄关心的问题,也正是我关心的问题.希望大侠能够给出好的方案和建议.

16 楼 gxb_1985 2010-06-18  
怎么还在drl中写if else啊 
这个可以写在function中

15 楼 qyhdt 2010-05-28  
说实话,很想熟悉,但是不会

14 楼 sandy320 2010-05-28  
规则drl文件中可以应用HTML的页面元素? 

还是只能用Java 相关的啊

13 楼 andyivy6 2010-05-10  
在rhs中还用if else啊?

12 楼 felixshao 2010-05-09  
ltian 写道
我对规则引擎的理念也很感兴趣,但是联想到实际的工作场景,我发现Drools并没有想象中的完美,以下疑问请教众位大侠: 

1.规则里面很多的判据不是直接就具备的,需要一些整理过程,那么这些整理过程到底是在Java类里面做还是在Drools规则里面做?举例子说: 
规则如下: 
如果用户购买的商品中有两个以上的A产品和一个B产品就打85折。 
如果用户购买的商品中有两个以上的B产品,就打8折。 

在实际开发中,我们会把用户准备购买的产品都放在一个列表中。 
如果要应用规则引擎,直接以产品列表为“事实”是最理想的,但是以直接以产品列表为“事实”就需要在规则中插入Java代码,用来整理出产品A和产品B的数量。这样一来,整理产品列表的Java代码就脱离了Java的运行环境,调试起来比较困难。至于更复杂的一些业务规则,用Rule去实现岂不是很难阅读和理解? 

如果我们不直接以产品列表为”事实”,而已采购的产品A和B的数量为事实,那么在调用规则之前,就要在Java中整理产品列表,求出产品A和B的数量,然后将其作为“事实”调用规则。此种方案的缺点就是不够灵活。一旦规则变化了,需要纳入产品C的数量来作为打折的依据,那么既要修改Java中整理产品列表的代码,又要修改规则文件。这也是我们不愿意看到的场面! 

没有用过Drools,但前公司(刚失业)用得很多(自己开发的商业规则引擎)。 我先讲一下它有的功能。 
1.  规则引擎 理论上是给BA用的, 而不是给开发人员用的。(现实是BA基本上复杂一点的规则就写不出来了,但开发人员写的Rules BA必须能看懂。) 
2.规则引擎能接受输入。我们的系统实现是: 
建立一个巨大无比的树Domain Object, 里面有所有的信息。每一条Rules By Default 都有Access到Domain Object。 
提供图形化的Column Picker。 应该说规则引擎跟你的Data Model是紧紧的结合在一起的。 
Rule 应该有steps。前一个Step的值可以传到下一个Step。提供API调用Java。提供Rule 的调试工具。 

2.所谓的“业务规则”和“业务逻辑”区别到底在哪?是不是所有业务逻辑都可以看做是“业务规则”?如果是这样,那么复杂的业务逻辑或者说复杂的业务规则用规则文件去编写是否合适?如何把握将哪些业务规则用规则引擎去实现的度? 

基本上大部分的业务逻辑都可以看做是“业务规则”。其实越复杂的业务逻辑越应该用用规则文件去编写,(前提)因为BA是可以看得懂Rule的,如果我们把业务逻辑放到Java里面,只能通过测试才知道是否符合要求,但复杂的业务逻辑有很多时候很多地方Test Case 没有Cover。 

3. 如果要推入工作内存的事实量较大,或者需要用到的规则量较大,规则引擎的性能可否满足要求呢? 
取决于规则引擎的实现方式。 

4. “部门经理(角色)能够批准2天以内的请假,总经理(角色)可以批准2天以上的请假”,这样的规则算不算业务规则?这样的规则中,什么是事实,什么是结论?在工作流的场景下,我期望的是给出申请的请假天数,然后根据业务规则找出可以批准的角色,然后将工作任务发给该角色。那么规则引擎是否具有这样类似的查询功能呢?或者我该如何去实现? 

肯定算业务规则。不过你的例子不是很完善, 例如部门经理不应该能够批准自己的请假,所有给出申请的请假天数,然后根据业务规则找出可以批准的角色不是很合理。 
应该是:定义好员工之间的关系。每一个员工根据不同的请求都有一个default NextAppover(当default NextAppover 请假了或者出差了怎么办太复杂了,讲不完)。default NextAppover 是根据条件不同而不同的。例如你要请假,你的default NextAppover 是谁,或者你要审批某一样东西default NextAppover 是不同的。所以default NextAppover本身应该由Rule决定。决定了NextAppover,再根据user请假的天数决定NextAppover是否有权批准,如果没有,通常由NextAppover决定下一步怎么办,通常是Pass 到他自己的NextAppover。 在你的例子中,假如是普通员工请假三天,你是否想直接找到总经理,然后把工作任务发给总经理而部门经理不知道呢?更复杂一点的例子是:如果你要请假,哪些人你是要CC的。 
一些使用规则引擎必须要注意的问题: 
那些Rule需要Versioning, 就是说不同的时间用不同Rule。哪些不要。 
Rule 的命名和查找? 
Rule 如何能够重复使用?(把十条Rule的逻辑放到一条里可能比Java Extract 一个方法难很多)。 

11 楼 dingjob 2010-05-09  
ltian 写道
我对规则引擎的理念也很感兴趣,但是联想到实际的工作场景,我发现Drools并没有想象中的完美,以下疑问请教众位大侠: 

1.规则里面很多的判据不是直接就具备的,需要一些整理过程,那么这些整理过程到底是在Java类里面做还是在Drools规则里面做?举例子说: 
规则如下: 
如果用户购买的商品中有两个以上的A产品和一个B产品就打85折。 
如果用户购买的商品中有两个以上的B产品,就打8折。 

在实际开发中,我们会把用户准备购买的产品都放在一个列表中。 
如果要应用规则引擎,直接以产品列表为“事实”是最理想的,但是以直接以产品列表为“事实”就需要在规则中插入Java代码,用来整理出产品A和产品B的数量。这样一来,整理产品列表的Java代码就脱离了Java的运行环境,调试起来比较困难。至于更复杂的一些业务规则,用Rule去实现岂不是很难阅读和理解? 

如果我们不直接以产品列表为”事实”,而已采购的产品A和B的数量为事实,那么在调用规则之前,就要在Java中整理产品列表,求出产品A和B的数量,然后将其作为“事实”调用规则。此种方案的缺点就是不够灵活。一旦规则变化了,需要纳入产品C的数量来作为打折的依据,那么既要修改Java中整理产品列表的代码,又要修改规则文件。这也是我们不愿意看到的场面! 

2.所谓的“业务规则”和“业务逻辑”区别到底在哪?是不是所有业务逻辑都可以看做是“业务规则”?如果是这样,那么复杂的业务逻辑或者说复杂的业务规则用规则文件去编写是否合适?如何把握将哪些业务规则用规则引擎去实现的度? 

对于这个问题,我认为,规则是可以动态加载的,在线上环境下更新,不需要停应用的,建议尽量放在规则里面,还有现在都有eclipse插件支持调试的,对于简单的计算应该还是方便的。如果是很复杂的业务逻辑,或者要组装一个很复杂的对象,肯定要放在java处理比较好。 

ltian 写道

3. 如果要推入工作内存的事实量较大,或者需要用到的规则量较大,规则引擎的性能可否满足要求呢? 

使用规则引擎对于不是用户访问web应用的情况,最好是异步的,规则量太大则需要使用缓存。 

ltian 写道

4. “部门经理(角色)能够批准2天以内的请假,总经理(角色)可以批准2天以上的请假”,这样的规则算不算业务规则?这样的规则中,什么是事实,什么是结论?在工作流的场景下,我期望的是给出申请的请假天数,然后根据业务规则找出可以批准的角色,然后将工作任务发给该角色。那么规则引擎是否具有这样类似的查询功能呢?或者我该如何去实现? 

这个显然不是规则引擎擅长的领域,就像OGNL同样可以解析规则,但是很难定义出来规则。这种就用工作流来做吧  

你描述问题很清晰,哈哈 学习。

10 楼 dingjob 2010-05-09  
elvishehai 写道
看了之后还是不明白了。呵呵,

其实我写的有些大意,我的基本目的不是如何写规则,而是能够用起来规则引擎,规则应该写简单点,我从代码里copy了一段比较复杂的规则。

9 楼 turionboy 2010-05-07  
不知道这家伙是做什么地,插不上嘴呀

8 楼 ltian 2010-05-07  
这么好的探讨主题,怎么没人感兴趣吗?

7 楼 ltian 2010-05-07  
我对规则引擎的理念也很感兴趣,但是联想到实际的工作场景,我发现Drools并没有想象中的完美,以下疑问请教众位大侠: 

1.规则里面很多的判据不是直接就具备的,需要一些整理过程,那么这些整理过程到底是在Java类里面做还是在Drools规则里面做?举例子说: 
规则如下: 
如果用户购买的商品中有两个以上的A产品和一个B产品就打85折。 
如果用户购买的商品中有两个以上的B产品,就打8折。 

在实际开发中,我们会把用户准备购买的产品都放在一个列表中。 
如果要应用规则引擎,直接以产品列表为“事实”是最理想的,但是以直接以产品列表为“事实”就需要在规则中插入Java代码,用来整理出产品A和产品B的数量。这样一来,整理产品列表的Java代码就脱离了Java的运行环境,调试起来比较困难。至于更复杂的一些业务规则,用Rule去实现岂不是很难阅读和理解? 

如果我们不直接以产品列表为”事实”,而已采购的产品A和B的数量为事实,那么在调用规则之前,就要在Java中整理产品列表,求出产品A和B的数量,然后将其作为“事实”调用规则。此种方案的缺点就是不够灵活。一旦规则变化了,需要纳入产品C的数量来作为打折的依据,那么既要修改Java中整理产品列表的代码,又要修改规则文件。这也是我们不愿意看到的场面! 

2.所谓的“业务规则”和“业务逻辑”区别到底在哪?是不是所有业务逻辑都可以看做是“业务规则”?如果是这样,那么复杂的业务逻辑或者说复杂的业务规则用规则文件去编写是否合适?如何把握将哪些业务规则用规则引擎去实现的度? 

3. 如果要推入工作内存的事实量较大,或者需要用到的规则量较大,规则引擎的性能可否满足要求呢? 

4. “部门经理(角色)能够批准2天以内的请假,总经理(角色)可以批准2天以上的请假”,这样的规则算不算业务规则?这样的规则中,什么是事实,什么是结论?在工作流的场景下,我期望的是给出申请的请假天数,然后根据业务规则找出可以批准的角色,然后将工作任务发给该角色。那么规则引擎是否具有这样类似的查询功能呢?或者我该如何去实现? 

6 楼 ziyu_1 2010-05-07  
都不知道是什么, 最后那一堆代码看得蛋疼

5 楼 董瑞龙 2010-05-07  
正在使用drools期待更多交流

4 楼 coffeesweet 2010-05-07  
用过drolls,但总是一知半解,感觉不太符合JAVA程序编写习惯,总觉得很别扭!

3 楼 mooninday 2010-05-07  
以前用drools,在drl文件里加了很多function,写起来超难受。。。

2 楼 elvishehai 2010-05-06  
看了之后还是不明白了。呵呵,

1 楼 hongliangpan 2010-05-06  
Drools规则引擎介绍.ppt 

什么是规则引擎? 
Drools规则引擎介绍 
信用卡申请实例介绍 
Drools实现信用卡申请规则 
编写客户端测试信用卡申请规则


Warning: count(): Parameter must be an array or an object that implements Countable in /www/wwwroot/www.drools.org.cn/wp-includes/class-wp-comment-query.php on line 405

留下评论