最近在研究JBPM工作流引擎,發現JBPM是基於Drools的,官方文檔查看得知Drools是一款規則引擎。興趣之下,仔細了解了下 Drools,Drools作為JBoss出品的一款開源推理和規則引擎,被廣泛的應用在各個領域,如JBPM也是基於Drools的。一般我們使用規則 引擎的前提和場景是:業務規則頻繁變化!如果業務規則穩定則無需應用規則引擎的,實際中諸如移動通信商、銀行等領域則廣泛的使用了規則引擎,主要是為了適 應頻繁變更的規則,但又不需要影響業務邏輯代碼。
在看了官方的一些文檔介紹后,通過一個例子體驗了下Drools,例子說明如下:
1、小明手上有50元錢;
2、1元錢可以買一瓶飲料;
3、2個空瓶可以兌換一瓶飲料;
4、問題是:最終小明可以喝多少瓶飲料;
通過Drools的規則推理引擎可以很好的解決這類問題,至於搭建Drools的開發環境就不細說了。直接上代碼說明:
一、規則fact

1 package com.nonbankcard.drools.jisuan; 2 /** 3 * 事實 4 * @author sxf 5 * 6 */ 7 public class User { 8 private int money; // 手中的錢 9 private int kp; // 空瓶數 10 private int totals; // 喝掉的瓶數 11 public int getMoney() { 12 return money; 13 } 14 public void setMoney(int money) { 15 this.money = money; 16 } 17 public int getKp() { 18 return kp; 19 } 20 public void setKp(int kp) { 21 this.kp = kp; 22 } 23 public int getTotals() { 24 return totals; 25 } 26 public void setTotals(int totals) { 27 this.totals = totals; 28 } 29 30 31 }
二、測試規則的代碼

1 package com.nonbankcard.drools.jisuan; 2 3 import java.util.Iterator; 4 5 import org.drools.KnowledgeBase; 6 import org.drools.KnowledgeBaseFactory; 7 import org.drools.builder.KnowledgeBuilder; 8 import org.drools.builder.KnowledgeBuilderError; 9 import org.drools.builder.KnowledgeBuilderFactory; 10 import org.drools.builder.ResourceType; 11 import org.drools.io.ResourceFactory; 12 import org.drools.runtime.StatefulKnowledgeSession; 13 /** 14 * 測試規則的代碼 15 * @author sxf 16 * 17 */ 18 public class DroolsTester { 19 20 public static void main(String[] args) throws Exception { 21 KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); 22 kbuilder.add(ResourceFactory.newClassPathResource("user.drl"), ResourceType.DRL); 23 if (kbuilder.hasErrors()) { 24 System.out.println("規則錯誤:"); 25 Iterator<KnowledgeBuilderError> it = kbuilder.getErrors().iterator(); 26 while (it.hasNext()) System.out.println(it.next()); 27 return; 28 } 29 KnowledgeBase kb = KnowledgeBaseFactory.newKnowledgeBase(); 30 kb.addKnowledgePackages(kbuilder.getKnowledgePackages()); 31 StatefulKnowledgeSession s = kb.newStatefulKnowledgeSession(); 32 User user=new User(); 33 user.setMoney(50); 34 s.insert(user); 35 s.fireAllRules(); 36 s.dispose(); 37 } 38 39 }
三、規則文件

1 package cc.mzone 2 3 //list any import classes here. 4 import com.nonbankcard.drools.jisuan.User; 5 6 7 //declare any global variables here 8 9 10 11 // 規則1,如果有錢就買一瓶喝掉 12 rule "r001" 13 salience 3 14 when 15 $u:User(money>0); 16 then 17 System.out.println("余錢:" + $u.getMoney() + ",花1元購買1瓶並喝掉"); 18 $u.setKp($u.getKp() + 1); 19 $u.setMoney($u.getMoney() - 1); 20 $u.setTotals($u.getTotals() + 1); 21 update($u); 22 end 23 24 // 規則2,如果空瓶數大於2則換購1瓶(兌換成1元錢) 25 rule "r002" 26 salience 2 27 when 28 $u:User(kp>=2); 29 then 30 System.out.println("空瓶數:" + $u.getKp() + ",兌換2個空瓶為1元錢"); 31 $u.setKp($u.getKp() - 2); 32 $u.setMoney($u.getMoney() + 1); 33 update($u); 34 end 35 36 // 規則3,打印已經喝掉的數量 37 rule "r003" 38 salience 1 39 when 40 $u:User(); 41 then 42 System.out.println("總喝掉瓶數:" + $u.getTotals()); 43 end
四:測試結果輸出

1 余錢:50,花1元購買1瓶並喝掉 2 余錢:49,花1元購買1瓶並喝掉 3 余錢:48,花1元購買1瓶並喝掉 4 余錢:47,花1元購買1瓶並喝掉 5 余錢:46,花1元購買1瓶並喝掉 6 余錢:45,花1元購買1瓶並喝掉 7 余錢:44,花1元購買1瓶並喝掉 8 余錢:43,花1元購買1瓶並喝掉 9 余錢:42,花1元購買1瓶並喝掉 10 余錢:41,花1元購買1瓶並喝掉 11 余錢:40,花1元購買1瓶並喝掉 12 余錢:39,花1元購買1瓶並喝掉 13 余錢:38,花1元購買1瓶並喝掉 14 余錢:37,花1元購買1瓶並喝掉 15 余錢:36,花1元購買1瓶並喝掉 16 余錢:35,花1元購買1瓶並喝掉 17 余錢:34,花1元購買1瓶並喝掉 18 余錢:33,花1元購買1瓶並喝掉 19 余錢:32,花1元購買1瓶並喝掉 20 余錢:31,花1元購買1瓶並喝掉 21 余錢:30,花1元購買1瓶並喝掉 22 余錢:29,花1元購買1瓶並喝掉 23 余錢:28,花1元購買1瓶並喝掉 24 余錢:27,花1元購買1瓶並喝掉 25 余錢:26,花1元購買1瓶並喝掉 26 余錢:25,花1元購買1瓶並喝掉 27 余錢:24,花1元購買1瓶並喝掉 28 余錢:23,花1元購買1瓶並喝掉 29 余錢:22,花1元購買1瓶並喝掉 30 余錢:21,花1元購買1瓶並喝掉 31 余錢:20,花1元購買1瓶並喝掉 32 余錢:19,花1元購買1瓶並喝掉 33 余錢:18,花1元購買1瓶並喝掉 34 余錢:17,花1元購買1瓶並喝掉 35 余錢:16,花1元購買1瓶並喝掉 36 余錢:15,花1元購買1瓶並喝掉 37 余錢:14,花1元購買1瓶並喝掉 38 余錢:13,花1元購買1瓶並喝掉 39 余錢:12,花1元購買1瓶並喝掉 40 余錢:11,花1元購買1瓶並喝掉 41 余錢:10,花1元購買1瓶並喝掉 42 余錢:9,花1元購買1瓶並喝掉 43 余錢:8,花1元購買1瓶並喝掉 44 余錢:7,花1元購買1瓶並喝掉 45 余錢:6,花1元購買1瓶並喝掉 46 余錢:5,花1元購買1瓶並喝掉 47 余錢:4,花1元購買1瓶並喝掉 48 余錢:3,花1元購買1瓶並喝掉 49 余錢:2,花1元購買1瓶並喝掉 50 余錢:1,花1元購買1瓶並喝掉 51 空瓶數:50,兌換2個空瓶為1元錢 52 余錢:1,花1元購買1瓶並喝掉 53 空瓶數:49,兌換2個空瓶為1元錢 54 余錢:1,花1元購買1瓶並喝掉 55 空瓶數:48,兌換2個空瓶為1元錢 56 余錢:1,花1元購買1瓶並喝掉 57 空瓶數:47,兌換2個空瓶為1元錢 58 余錢:1,花1元購買1瓶並喝掉 59 空瓶數:46,兌換2個空瓶為1元錢 60 余錢:1,花1元購買1瓶並喝掉 61 空瓶數:45,兌換2個空瓶為1元錢 62 余錢:1,花1元購買1瓶並喝掉 63 空瓶數:44,兌換2個空瓶為1元錢 64 余錢:1,花1元購買1瓶並喝掉 65 空瓶數:43,兌換2個空瓶為1元錢 66 余錢:1,花1元購買1瓶並喝掉 67 空瓶數:42,兌換2個空瓶為1元錢 68 余錢:1,花1元購買1瓶並喝掉 69 空瓶數:41,兌換2個空瓶為1元錢 70 余錢:1,花1元購買1瓶並喝掉 71 空瓶數:40,兌換2個空瓶為1元錢 72 余錢:1,花1元購買1瓶並喝掉 73 空瓶數:39,兌換2個空瓶為1元錢 74 余錢:1,花1元購買1瓶並喝掉 75 空瓶數:38,兌換2個空瓶為1元錢 76 余錢:1,花1元購買1瓶並喝掉 77 空瓶數:37,兌換2個空瓶為1元錢 78 余錢:1,花1元購買1瓶並喝掉 79 空瓶數:36,兌換2個空瓶為1元錢 80 余錢:1,花1元購買1瓶並喝掉 81 空瓶數:35,兌換2個空瓶為1元錢 82 余錢:1,花1元購買1瓶並喝掉 83 空瓶數:34,兌換2個空瓶為1元錢 84 余錢:1,花1元購買1瓶並喝掉 85 空瓶數:33,兌換2個空瓶為1元錢 86 余錢:1,花1元購買1瓶並喝掉 87 空瓶數:32,兌換2個空瓶為1元錢 88 余錢:1,花1元購買1瓶並喝掉 89 空瓶數:31,兌換2個空瓶為1元錢 90 余錢:1,花1元購買1瓶並喝掉 91 空瓶數:30,兌換2個空瓶為1元錢 92 余錢:1,花1元購買1瓶並喝掉 93 空瓶數:29,兌換2個空瓶為1元錢 94 余錢:1,花1元購買1瓶並喝掉 95 空瓶數:28,兌換2個空瓶為1元錢 96 余錢:1,花1元購買1瓶並喝掉 97 空瓶數:27,兌換2個空瓶為1元錢 98 余錢:1,花1元購買1瓶並喝掉 99 空瓶數:26,兌換2個空瓶為1元錢 100 余錢:1,花1元購買1瓶並喝掉 101 空瓶數:25,兌換2個空瓶為1元錢 102 余錢:1,花1元購買1瓶並喝掉 103 空瓶數:24,兌換2個空瓶為1元錢 104 余錢:1,花1元購買1瓶並喝掉 105 空瓶數:23,兌換2個空瓶為1元錢 106 余錢:1,花1元購買1瓶並喝掉 107 空瓶數:22,兌換2個空瓶為1元錢 108 余錢:1,花1元購買1瓶並喝掉 109 空瓶數:21,兌換2個空瓶為1元錢 110 余錢:1,花1元購買1瓶並喝掉 111 空瓶數:20,兌換2個空瓶為1元錢 112 余錢:1,花1元購買1瓶並喝掉 113 空瓶數:19,兌換2個空瓶為1元錢 114 余錢:1,花1元購買1瓶並喝掉 115 空瓶數:18,兌換2個空瓶為1元錢 116 余錢:1,花1元購買1瓶並喝掉 117 空瓶數:17,兌換2個空瓶為1元錢 118 余錢:1,花1元購買1瓶並喝掉 119 空瓶數:16,兌換2個空瓶為1元錢 120 余錢:1,花1元購買1瓶並喝掉 121 空瓶數:15,兌換2個空瓶為1元錢 122 余錢:1,花1元購買1瓶並喝掉 123 空瓶數:14,兌換2個空瓶為1元錢 124 余錢:1,花1元購買1瓶並喝掉 125 空瓶數:13,兌換2個空瓶為1元錢 126 余錢:1,花1元購買1瓶並喝掉 127 空瓶數:12,兌換2個空瓶為1元錢 128 余錢:1,花1元購買1瓶並喝掉 129 空瓶數:11,兌換2個空瓶為1元錢 130 余錢:1,花1元購買1瓶並喝掉 131 空瓶數:10,兌換2個空瓶為1元錢 132 余錢:1,花1元購買1瓶並喝掉 133 空瓶數:9,兌換2個空瓶為1元錢 134 余錢:1,花1元購買1瓶並喝掉 135 空瓶數:8,兌換2個空瓶為1元錢 136 余錢:1,花1元購買1瓶並喝掉 137 空瓶數:7,兌換2個空瓶為1元錢 138 余錢:1,花1元購買1瓶並喝掉 139 空瓶數:6,兌換2個空瓶為1元錢 140 余錢:1,花1元購買1瓶並喝掉 141 空瓶數:5,兌換2個空瓶為1元錢 142 余錢:1,花1元購買1瓶並喝掉 143 空瓶數:4,兌換2個空瓶為1元錢 144 余錢:1,花1元購買1瓶並喝掉 145 空瓶數:3,兌換2個空瓶為1元錢 146 余錢:1,花1元購買1瓶並喝掉 147 空瓶數:2,兌換2個空瓶為1元錢 148 余錢:1,花1元購買1瓶並喝掉 149 總喝掉瓶數:99
根據輸出信息,符合我們的預期,確實是只要有錢就購買。如果換一種策略,只要有2個空瓶了就兌換先,那么可以將規則1和規則2的salience屬性值對調,這樣規則2就會優先執行。
可見輸出信息不一樣了,也非常符合我們的預期。由此可見,不同的規則分析可以導致不同的執行路徑,但最終效果都一樣,很好的推理出了我們想要的結果。通過Drools規則推理引擎還可以解決很多類似的問題。