您好,登錄后才能下訂單哦!
本篇內容主要講解“Drools規(guī)則引擎的作用是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Drools規(guī)則引擎的作用是什么”吧!
規(guī)則約束和判定都是通過DRL(Drools Rule Language)文件完成,一個文件可包含一條或者多條規(guī)則。典型描述規(guī)則如下格式:
Package:包是Drools中相關資產的文件夾,如數(shù)據(jù)對象、DRL文件、決策表和其他資產類型。主要充當每個規(guī)則組的惟一名稱空間,必須位于文件的頂部,和Java中的編寫的相關的類的路徑無關,保證唯一即可。
Import:導入需要使用的類的包或類
Function:函數(shù)定義,如:
function String hello(String applicantName) { return "Hello " + applicantName + "!"; }
Query: 可以根據(jù)規(guī)則名稱在引擎中查詢符合條件的結果對象;
Declare:可以聲明一個類,與使用java 定義的類具有同樣的功能。如:
declare Cheese name : String price : int end
Global:定義全局變量;
Rule: 定義此規(guī)則的唯一標識;
When: 條件判定,如Person( age == 50 ),在Person對象中,滿足age屬性等于50;
Then: 滿足條件時觸發(fā)的動作,包括增、刪、改三個動作;
End:規(guī)則執(zhí)行結束的標識符。
第一次接觸的Drools的話對于各種配置和組件關系還是比較蒙蔽的,結合個人理解,給出一個簡單的關系圖,畫的可能有失偏頗,如有不對,還請指出:
kmodule.xml:定義在/META-INF/kmodule.xml,配置一個或多個Kiebase,每個Kiebase可配置多個KieSession。通常可以運行時根據(jù)項目需求動態(tài)生成KieBases
和 KieSessions
,依賴于KieFileSystem提供各種方法。動態(tài)創(chuàng)建kmodule.xml的內容并加入到KieFileSystem。
KieBase:在項目的KIE模塊描述符文件(kmodule .xml)中定義的存儲庫,它包含Drools中的所有內容,但不包含任何運行時數(shù)據(jù),可通過KieContainer獲得:KieBase kBase = kContainer.getKieBase();
KieServices:接口,可以訪問所有的創(chuàng)建和運行時對象,如日志,資源,環(huán)境,容器等。其中有的方法分為兩大類:getX()和newX(),其中,get只會返回一個對應單例對象的引用,new則會重新創(chuàng)建一個對象。
KieContainer: 裝載與引擎相關的組件,通過KieServices.Factory.get()方式獲得,為其他Kie工具提供服務。KieContainer可以通過ReleaseId,Artifact,Version參數(shù)獲得另外一個KieContainer:
KieSession:在Drools中,KIE會話存儲并執(zhí)行運行時數(shù)據(jù)。如果在項目的KIE模塊描述符文件(kmodu .xml)中定義了KIE會話,則可以從KIE基礎創(chuàng)建KIE會話,或者直接從KIE容器創(chuàng)建,可細分有狀態(tài)和無狀態(tài)連接。
.drl文件:可以動態(tài)的添加,KieResources
提供了多種工廠方式以轉化為InputStream
, URL
, File
, String
創(chuàng)建.drl文件后,重新加載:
嵌套規(guī)則,也可以理解為多重條件判定,這個Drools可以做的很好,主要是了解其drl文件的語法規(guī)則,則能夠很好的處理復雜的邏輯判斷,如嵌套對象、集合等常見需求,下面簡單的給個示例:
1)定義User對象如下:
@Data public class User { private String name; private Integer age; private Pet pet;}
2)定義Pet如下:
@Data public class Pet { private String name; private String color;}
3)定義規(guī)則如下:
rule "nested multiple condition" when $user : User(age>15 && age<60) $pet : Pet() from $user.pet if($pet.getColor()=="black") do[black] if($pet.getColor()=="white") break[white] then System.out.print("測試結束"); then [black] System.out.println("pet color is balck"); then [white] System.out.print("pet color is white"); end
4)執(zhí)行邏輯為:
簡單場景下,drl文件可以預先定義好,但是很多時候我們需要根據(jù)條件來生成drl文件,或者從數(shù)據(jù)庫加載文件內容,此時就要動態(tài)地生成drl文件。其流程簡述為:界面配置,后臺生成drl文件,寫入規(guī)則引擎。其核心思想是:根據(jù)界面規(guī)則生成相應的.drl文件,動態(tài)加載進內存再由引擎判定。代碼參考如下:
public void reload() throws UnsupportedEncodingException { KieServices kieServices = getKieServices(); KieFileSystem kfs = kieServices.newKieFileSystem(); kfs.write("src/main/resources/rules/temp.drl", loadRules()); KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll(); Results results = kieBuilder.getResults(); if (results.hasMessages(Message.Level.ERROR)) { System.out.println(results.getMessages()); throw new IllegalStateException("### errors ###"); } } private String loadRules() { // 假設從數(shù)據(jù)庫加載的規(guī)則 return "package adress\n\n rule \"Postcode 6 numbers\"\n\n when\n then\n System.out.println(\"規(guī)則2中打印日志:我是從數(shù)據(jù)庫加載的!\");\n end"; }
更為普遍地使用場景是:規(guī)則可以動態(tài)生成(如上所述),規(guī)則可以動態(tài)加載進引擎,根據(jù)條件加載指定地規(guī)則。這又如何實現(xiàn)呢?
在Drools中,KieContainer是引擎執(zhí)行時的核心工具,一個container會加載kmodule.xml中的所有資源。因此,可以將不同的kmodule.xml加載進不同的container,那么就可以根據(jù)參數(shù)選擇container,從而觸發(fā)此container中的引擎。注意,drl文件和kmodule.xml不是一對一的關系,但是drl文件的包名和kmodule.xml中package屬性是對應的,詳見下節(jié)討論。為保證項目結構清晰,便于管理,一般可以kmodule.xml對應一個drl文件。
參考代碼如下:
private KieContainer getContainer(String domain) { KieServices kieServices = KieServices.Factory.get(); KieFileSystem kfs = kieServices.newKieFileSystem(); //內部方法,生成kmodule.xml文件,返回此xml文件中KieSession名稱,下次可根據(jù)此sessionName從kieContainer中生成獲得對應的session sessionName = generateXML(domain, kieServices, kfs); //寫入drl文件并加載進 kfs.write("src/main/resources/rules/temp.drl", loadRules()); KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll(); //生成裝載此xml文件的容器 KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId()); //建立對應關系并緩存起來此規(guī)則 cache.put(domain,kieContainer); return kieContainer; } //訪問資源 @ResponseBody @RequestMapping("dynamic/{domain}") public String resource(@PathVariable String domain) { String res="你不是第一次訪問,直接加載相關資源"; KieContainer kieContainer = cache.get(domain); if (null == kieContainer) { res="你是第一次訪問,生成相關資源"; kieContainer=getContainer(domain); } //根據(jù)之前生成的sessionName獲取kieSession,然后規(guī)則校驗 final KieSession kieSession = kieContainer.newKieSession(sessionName); kieSession.insert(new Address()); kieSession.fireAllRules(); kieSession.dispose(); return res; }
這種需求也是很常見的,比如不同的產品在出廠時,其校驗規(guī)則肯定是不一樣的,都有其自身特有的屬性校驗。那么,如何根據(jù)不同的參數(shù)來使用不同規(guī)則呢?如下kmodule.xml文件:
<kmodule xmlns="http://www.drools.org/xsd/kmodule"> <kbase name="kbase1"> <ksession name="ksession1"/> </kbase> <kbase name="kbase2" packages="org.some.pkg"> <ksession name="ksession2"/> </kbase> </kmodule>
可以根據(jù)kmodule.xml中不同的package屬性來指定加載哪個.drl文件,packages="org.some.pkg"表示ksession2只會加載org.some.pkg下的規(guī)則文件,如果沒寫,則默認加載所有的規(guī)則文件。相應Java代碼如下:
KieContainer kc =KieServices.Factory.get().getKieClasspathContainer(); KieSession kieSession = kc.newKieSession("ksession2");
此KieSession只會加載drl文件中有package org.some.pkg 聲明的規(guī)則文件。如果沒有指明kiesession名稱,則會默認加載所有的drl文件,并且此時kmodule.xml中不能聲明任何kbase標簽,否則報錯:
java.lang.RuntimeException: Cannot find a default KieSession
規(guī)則的判定順序可以使用屬性Salience:定義規(guī)則優(yōu)先級的整數(shù)。值越大,優(yōu)先級越高,如salience 10
到此,相信大家對“Drools規(guī)則引擎的作用是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。