您好,登錄后才能下訂單哦!
今天小編給大家分享一下drools入門案例分析的相關(guān)知識點,內(nèi)容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
最近在學(xué)習(xí)規(guī)則引擎drools
,此處簡單記錄一下drools
的入門案例。
drools是一款由JBoss組織提供的基于Java語言開發(fā)的開源規(guī)則引擎,可以將復(fù)雜且多變的業(yè)務(wù)規(guī)則從硬編碼中解放出來,以規(guī)則腳本的形式存放在文件或特定的存儲介質(zhì)中(例如存放在數(shù)據(jù)庫中),使得業(yè)務(wù)規(guī)則的變更不需要修改項目代碼、重啟服務(wù)器就可以在線上環(huán)境立即生效。
假設(shè)我們存在如下場景:在我們到商店購買衣服的時候,經(jīng)常會發(fā)生這樣的事情,購買1件不打折,購買2件打0.98折,購買3件級以上打0.85折。
那么我們在代碼中如果要實現(xiàn)上述功能,是不是就需要編寫if ... else
語句,假設(shè)后期規(guī)則變了,是不是就需要修改這些if ... else
語句,然后程序重新部署。這樣是可以實現(xiàn),但是不夠優(yōu)雅。那么我們是否可以將這些業(yè)務(wù)規(guī)則寫入到規(guī)則文件中,以后規(guī)則變更直接修改規(guī)則文件即可?而drools
就可以實現(xiàn)這個功能。
<dependencyManagement> <dependencies> <dependency> <groupId>org.drools</groupId> <artifactId>drools-bom</artifactId> <type>pom</type> <version>7.69.0.Final</version> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-mvel</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.11</version> </dependency> </dependencies>
此配置文件需要放置在resources/META-INF
目錄下。
<kmodule xmlns="http://www.drools.org/xsd/kmodule"> <!-- kbase 可以存在多個 name: 指定kbase的名字,需要是唯一的 packages: 包名,可以理解為到src/main/resources目錄下查找這個包名下的規(guī)則文件,多個包使用逗號分割 default: 當(dāng)前kbase是否是默認的kbase --> <kbase name="shop-kabse" packages="com.huan.shop" default="false"> <!-- ksession 可以存在多個 name: 指定ksession 的名字,需要唯一 defalut: 當(dāng)前ksession在這個kbase下是否是默認的 type: 指定當(dāng)前ksession是否是有狀態(tài)的 stateless表示是無狀態(tài)的 --> <ksession name="shop-ksession" default="false" type="stateless"/> <ksession name="shop-ksession-stateful" default="false" type="stateful"/> </kbase> </kmodule>
此處我們需要關(guān)注一下 kbase
下package
的值,這個值需要和規(guī)則文件中的package
值一致,否則會找不到規(guī)則,具體看下方。
包名,必須放置在第一行 package // 引入Java中的類,需要些全限定名 import // 定義function ,可選 function // Optional // 定義 query ,可選 query // Optional declare // Optional global // Optional // rule 關(guān)鍵字 "rule name" 規(guī)則的名字 rule "rule name" // Attributes 屬性可選 when // 關(guān)鍵字 // Conditions 條件,可為空 then // Actions // 匹配后執(zhí)行的結(jié)果 end // 關(guān)鍵字
規(guī)則文件的名字無所謂,比如: book-discount.drl
// 包名,必須防止到第一行,這個名字需要和 kbase中package屬性的值一致 package com.huan.shop /** * 倒入類 */ import com.huan.drools.CustomerOrder // 定義規(guī)則 rule "shop-rule-01" when // 模式匹配:到工作內(nèi)存中查找CustomerOrder,并且這個對象的purchaseQuantity值需要是1, // 如果條件成立,$order是綁定變量名,一般以$開頭,和fact對象區(qū)分開 $order:CustomerOrder(purchaseQuantity == 1) then System.out.println("匹配規(guī)則 shop-rule-01"); // 賦值,此處賦值后,在Java代碼中獲取獲取到賦值后的值 $order.setDiscount(1D); end rule "shop-rule-02" when $order:CustomerOrder(purchaseQuantity == 2) then System.out.println("匹配規(guī)則 shop-rule-02"); $order.setDiscount(0.98); end rule "shop-rule-03" when $order:CustomerOrder(purchaseQuantity >= 3) then System.out.println("匹配規(guī)則 shop-rule-03"); $order.setDiscount(0.85); end
如果 shop-discount.drl
的包名修改為com.huan.shop1
則會提示如下警告:
12:43:01.589 [main] WARN org.drools.compiler.kie.builder.impl.KieBuilderImpl - File 'com/huan/shop/shop-discount.drl' is in folder 'com/huan/shop' but declares package 'com.huan.shop1'. It is advised to have a correspondance between package and folder names.
此對象保存的是用戶購買了幾件衣服和對應(yīng)的折扣。
/** * 客戶購買衣服的訂單,省略 getter 和 setter 方法 * * @author huan.fu * @date 2022/5/12 - 11:27 */ public class CustomerOrder { /** * 購買了幾件衣服 */ private Integer purchaseQuantity; /** * 最終打多少折 */ private Double discount; public CustomerOrder(Integer purchaseQuantity) { this.purchaseQuantity = purchaseQuantity; } }
1、無狀態(tài)測試方法statelessSessionTest
規(guī)則規(guī)則2,即最終打0.98
折。
2、有狀態(tài)測試方法statefulSessionTest
規(guī)則規(guī)則3,即最終打0.85
折。
package com.huan.drools; import org.kie.api.KieServices; import org.kie.api.event.rule.DebugRuleRuntimeEventListener; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; import org.kie.api.runtime.StatelessKieSession; /** * drools 測試類 */ public class DroolsApplication { public static void main(String[] args) throws InterruptedException { // 無狀態(tài)session測試 statelessSessionTest(); // 有狀態(tài)session測試 statefulSessionTest(); } private static void statelessSessionTest() { // 獲取kie services KieServices kieServices = KieServices.get(); // 獲取kie容器對象 KieContainer kieContainer = kieServices.getKieClasspathContainer(); // 獲取kie session , 此處獲取的是無狀態(tài)的session,因為 <ksession name="shop-ksession" default="false" type="stateless"/> // 中type="stateless"就是無狀態(tài)的session StatelessKieSession kieSession = kieContainer.newStatelessKieSession("shop-ksession"); // 創(chuàng)建一個對象,可以理解為 Fact對象,即事實對象 CustomerOrder customerOrder = new CustomerOrder(2); // 添加監(jiān)聽器,便于觀察日志 kieSession.addEventListener(new DebugRuleRuntimeEventListener()); // 無狀態(tài)的session只需要執(zhí)行 execute 方法即可。 kieSession.execute(customerOrder); System.err.println("通過規(guī)則后,獲取到的折扣為:" + customerOrder.getDiscount()); } private static void statefulSessionTest() { // 獲取kie services KieServices kieServices = KieServices.get(); // 獲取kie容器對象 KieContainer kieContainer = kieServices.getKieClasspathContainer(); // 獲取kie session , 此處獲取的是有狀態(tài)的session KieSession kieSession = kieContainer.newKieSession("shop-ksession-stateful"); // 創(chuàng)建一個對象,可以理解為 Fact對象,即事實對象 CustomerOrder customerOrder = new CustomerOrder(3); // 添加監(jiān)聽器,便于觀察日志 kieSession.addEventListener(new DebugRuleRuntimeEventListener()); // 將customerOrder對象加入到工作內(nèi)存中 kieSession.insert(customerOrder); // 觸發(fā)所有的規(guī)則,如果只想觸發(fā)指定的規(guī)則,則使用fireAllRules(AgendaFilter agendaFilter)方法 kieSession.fireAllRules(); // 有狀態(tài)的session一定需要調(diào)用dispose方法 kieSession.dispose(); System.err.println("通過規(guī)則后,獲取到的折扣為:" + customerOrder.getDiscount()); } }
此處需要注意有狀態(tài)session
和無狀態(tài)session
寫法的區(qū)別。
到此,我們使用drools
實現(xiàn)的一個簡單的案例就實現(xiàn)了。
1、Rules
:我們自己定義的業(yè)務(wù)規(guī)則,比如我們自己寫的規(guī)則文件。所有規(guī)則必須至少包含觸發(fā)規(guī)則的條件和規(guī)則規(guī)定的操作。
2、Production memory
:規(guī)則存儲在 Drools 引擎中的位置。
3、Facts
:輸入或更改到 Drools 引擎中的數(shù)據(jù),Drools 引擎匹配規(guī)則條件以執(zhí)行適用規(guī)則。在規(guī)則中修改了Fact對象的值,真實的JavaBean的數(shù)據(jù)也會發(fā)生改變。
比如:當(dāng)我們調(diào)用ksession.insert(對象)
,那么插入的這個對象就可以理解成Facts
對象。
4、Working memory
:facts 在 Drools 引擎中存儲的位置。
5、Pattern matcher
:匹配器,將Rule Base中所有的規(guī)則與Working memory
中的Fact
對象進行模式匹配,匹配成功的規(guī)則將被激活并放入到Agenda
中。
6、Agenda
:議程,執(zhí)行Agenda中被激活的排好序的規(guī)則。
以上就是“drools入門案例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。