日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Drools规则引擎介绍及实践

發布時間:2023/12/10 编程问答 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Drools规则引擎介绍及实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.規則引擎

規則引擎是由推理引擎發展而來,是一種嵌入在應用程序中的組件,實現了將業務決策從應用程序代碼中分離出來,并使用預定義的語義模塊編寫業務決策。接受數據輸入,解釋業務規則,并根據業務規則做出業務決策。開源的代表是Drools,商業的代表是Visual Rules ,I Log

復雜企業級項目運營及維護過程中隨外部條件不斷變化的業務規則(business logic),
迫切需要分離商業決策者的商業決策邏輯和應用開發者的技術決策,
并把這些商業決策放在中心數據庫或其他統一的地方,讓它們能獨立運行;可以動態地管理和修改規則模板從而提供軟件系統的柔性和適應性

2.Drools規則引擎

Drools具有一個易于訪問企業策略、易于調整以及易于管理的開源業務規則引擎,符合業內標準,速度快、效率高。業務分析師或審核人員可以利用它輕松查看業務規則,從而檢驗是否已編碼的規則執行了所需的業務規則。

Drools是為Java量身定制的基于Charles Forgy的RETE算法的規則引擎的實現。支持Java代碼直接嵌入到規則文件中,使得商業規則有了更自然的表達。

Drools主要分為兩個部分:一是Drools規則,二是Drools規則的解釋執行。規則的編譯與運行要通過Drools 提供的相關API 來實現。而這些API 總體上游可分為三類:規則編譯、規則收集和規則的執行

3.Drools規則引擎優點

3.1申明式編程

明確規則機制讓我們可以“做什么”

規則機制的核心優勢在于可以簡化對于復雜問題的邏輯表述,并對這些邏輯進行驗證。

規則機制提供一個如何解決問題的說明,并說明每個決策的是如何得出的

3.2業務邏輯和數據分離

業務數據存儲業務對象中,業務決策存儲規則中,獨立運行

3.3速度和可擴展性

使用網絡算法(Rete algorithm),跳躍算法(Leaps algorithm),提供了非常高效的方式根據業務對象的數據匹配規則

3.3.1 Rete算法

Rete算法是一個快速的模式匹配算法,它通過存儲關于規則的信息而獲得速度

Rete算法的基本思想是保存過去匹配過程中留下的全部信息,以空間代價來換取執行效率 。對每一個模式 ,附加一個匹配元素表來記錄WorkingMemory中所有能與之匹配的元素。當一個新元素加入到WorkingMemory時, 找出所有能與之匹配的模式, 并將該元素加入到匹配元素表中; 當一個無素從WorkingMemory中刪除時,同樣找出所有與該元素匹配的模式,并將元素從匹配元素表中刪除。 Rete算法接受對工作存儲器的修改操作描述 ,產生一個修改沖突集的動作

Rete的高效率主要來自兩個重要的假設

時間冗余性:facts在推理過程中的變化是緩慢的, 即在每個執行周期中,只有少數的facts發生變化,因此影響到的規則也只占很小的比例。所以可以只考慮每個執行周期中已經匹配的facts.
結構相似性:許多規則常常包含類似的模式和模式組。

?

Rete算法的步驟如下:
1.將初始數據(fact)輸入Working Memory。
2.使用Pattern Matcher比較規則(rule)和數據(fact)。
3.如果執行規則存在沖突(conflict),即同時激活了多個規則,將沖突的規則放入沖突集合。
4.解決沖突,將激活的規則按順序放入Agenda。
5.使用規則引擎執行Agenda中的規則。

重復步驟2至5,直到執行完畢所有Agenda中的規則

3.3.2 Leaps 算法


前向推理引擎,包括LEAPS,都包括了匹配-選擇-執行(match-select-action)循環。即,確定可以匹配的規則,選擇某個匹配 的元 組,此元組相應的規則動作被執行。重復這一過程,直到某一狀態(如沒有更多的規則動作)。RETE和TREAT匹配算法速度慢的原因是,它們把滿足規則條 件的元組都實例化。Leaps算法的最大的改進就是使用一種"lazy"的方法來評估條件(conditions),即僅當必要時才進行元組的實例化。這一改進極大的減少了前向推理引擎的時空復雜度,極大提高了規則執行速度。

Leaps算法將所有的 asserted 的 facts ,按照其被 asserted 在 Working Memory 中的順序( FIFO ),放在主堆棧中。它一個個的檢查 facts ,通過迭代匹配 data type 的 facts 集合來找出每一個相關規則的匹配。當一個匹配的數據被發現時,系統記住此時的迭代位置以備待會的繼續迭代,并且激發規則結果( consequence )。當結果( consequence )執行完成以后,系統就會繼續處理處于主堆棧頂部的 fact 。如此反復。
Leaps算法的效率可以比Rete算法和Tread算法快幾個數量級

3.4規則集中化

通過使用規則,可以創建出一個可運行的知識庫。這就意味著對于業務規則可以具備良好的可閱讀性,可以起到文檔的作用

3.5易懂的規則

通過模型對象以及模型說明語言(Domain Specific Languages)能讓你使用很接近自然語言的方式為領域問題建模。借助于這些方式,可讓非技術領域的業務使用來描述業務問題

4.Drools規則模板

package rules; ???????????????????????????????????????????????// 規則包名路徑

import com.xxx.vo.ProductManageVo ???????????// 引入類
import com.xxx.BackList
import com.xxx.service.ProductRiskService
import java.util.HashMap
import java.util.Map

dialect "java" ???????????????????????????????????????????????// 定于語言,標識規則中的代碼表達式
global ProductRiskService productRiskService ?????????????????// 引入外部服務

rule "1001_product" ??????????????????????????????????????????// 規則名稱,全局唯一
????salience 1001 ????????????????????????????????????????????// 規則優先級,值越大越先執行
????lock-on-active true ??????????????????????????????????????// 事件是否重復執行該規則?true 至執行一次
????when ?????????????????????????????????????????????????????// 條件判斷關鍵字
????????event:ProductManageVo() ??????????????????????????????// 條件判斷,是否需要進入action-判斷事件對象是否是ProductManageVo對象并賦值于event
????then ?????????????????????????????????????????????????????// 執行事件關鍵字
????????if(event.getThirdPrice().doubleValue()/event.getTopPrice() <= 0.5){ ?// 事件業務邏輯,支持java編碼
????????????Map<String,Object> ruleContent = new HashMap<>();
????????????ruleContent.put("thirdPrice",event.getThirdPrice().doubleValue());
????????????ruleContent.put("topPrice",event.getTopPrice());
????????????ruleContent.put("message","三方價格小于TOP原價5");
????????????productRiskService.saveProductRiskInfo("1001_product",event,ruleContent);
????????}
????end ??????????????????????????????????????????????????????????// 規則結束關鍵字

4.1無約束匹配模式

???rule "1002"
????when
????????ProductManageVo()
????then
????????System.out.println("無約束的匹配模式,匹配ProductManageVo對象即可");
????end

4.2有條件匹配模式

rule "1003"
????when
????????ProductManageVo(topPrice>0)
????then
????????System.out.println("有條件匹配模式,ProductManageVo.topPrice>0即可");
????end

4.3匹配并綁定屬性模式

rule "1004"
????when
????????event:ProductManageVo($topPrice : topPrice>0)
????then
????????System.out.println("有條件匹配模,ProductManageVo.topPrice>0;" +"并賦值屬性:"

+event.getBarcode()+",$topPrice="+$topPrice);
????end

5.Drools支持的條件約束

rule "1005"
????when
????????ProductManageVo(thirdPrice!=null&&topPrice>0)
????then
????????System.out.println("條件約束表達式");
????end

約束

描述

!.

使用此運算符可以以空安全的方式取消引用屬性。!.運算符左側的值不能為null(解釋為!= null)

[]

按List索引訪問值或Map按鍵訪問值

<,<=,>,>=

在具有自然順序的屬性上使用這些運算符

==, !=

在約束中使用這些運算符作為equals()和!equals()方法

&&,||

組合關系條件

matches,not matches

使用這些運算符可以指示字段與指定的Java正則表達式匹配或不匹配

contains,not contains

使用這些運算符可以驗證Array或字段是否包含或不包含指定值

memberOf,not memberOf

使用這些運算符可以驗證字段是否為定義為變量Array的成員

soundslike

使用英語發音來驗證單詞是否具有與給定值幾乎相同的聲音(類似于該matches運算符)

in,notin

使用這些運算符可以指定一個以上的可能值來匹配約束(復合值限制)

6.Drools集合應用

6.1從集合中取數據

rule "1006"
????when
????????$event:ProductManageVo()
????????$backList : BackList(type==0) from?$event.backLists
????then
???????System.out.println("遍歷集合數據:"+$backList);
????end

?

7.SpringBoot引入Drools.jar

<dependency>
????<groupId>org.drools</groupId>
????<artifactId>drools-compiler</artifactId>
????<version>6.4.0.Final</version>
????<scope>runtime</scope>
</dependency>
<dependency>
????<groupId>org.kie</groupId>
????<artifactId>kie-ci</artifactId>
????<version>6.4.0.Final</version>
</dependency>

8.Java Demo

RiskConfig表結構

CREATE TABLE `r_risk_config` (
? `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
? `risk_code` varchar(128) NOT NULL COMMENT '規則編碼',
? `risk_name` varchar(256) DEFAULT NULL COMMENT '規則名稱',
? `risk_content` text COMMENT '規則模板',
? `risk_key` varchar(64) DEFAULT NULL COMMENT '規則模板md5,驗證是否需要重新加載',
? `risk_type` tinyint(3) DEFAULT '0' COMMENT '0-商品,1-訂單',
? `risk_level` tinyint(3) DEFAULT '0' COMMENT '風控等級',
? `is_send_email` tinyint(3) DEFAULT '0' COMMENT '是否發送郵件0-否,1-是',
? `is_wx_news` tinyint(3) DEFAULT '1' COMMENT '是否發送告警信息0-否,1-是',
? `is_fuse` tinyint(3) DEFAULT '0' COMMENT '是否熔斷流程0-否,1-是',
? `is_black_list` tinyint(3) DEFAULT '0' COMMENT '是否添加黑名單0-否,1-是',
? `status` tinyint(3) NOT NULL DEFAULT '1' COMMENT '是否生效0-否,1-是',
? `create_time` datetime DEFAULT NULL COMMENT '創建時間',
? `creator` bigint(20) DEFAULT NULL COMMENT '創建人',
? `modifier` bigint(20) DEFAULT NULL COMMENT '修改人',
? `modify_time` datetime DEFAULT NULL COMMENT '修改時間',
? `dr` tinyint(1) DEFAULT '0' COMMENT '刪除標志',
? `ver` int(11) DEFAULT '1' COMMENT '版本號',
? `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '時間戳',
? PRIMARY KEY (`id`),
? UNIQUE KEY `uni_risk_code` (`risk_code`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 COMMENT='風控規則表';

規則模板RiskConfig配置

?

@Service
@Slf4j
public class KieServiceImpl implements KieService {

????private StatelessKieSession kieSession;

????private KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

????@Resource
????private RiskConfigService riskConfigService;
????//商品規則處理
????@Resource
????private ProductRiskService productRiskService;

????@Override
????public void loadRules(String ruleCode) {
????????RiskConfig riskConfig = riskConfigService.queryRiskConfig(ruleCode);
????????if(riskConfig!=null){
????????????loadRule(ruleCode,riskConfig.getRiskContent());
????????}
????}

????/**
?????* 單一規則下線
?????*
?????* @param ruleName
?????*/
????@Override
????public void removeRule(String ruleName) {
????????if (kbase.getRule("rules", ruleName) != null) {
????????????kbase.removeRule("rules", ruleName);
????????????log.info("remove rule: rules." + ruleName);
????????????kieSession = kbase.newStatelessKieSession();
????????????printRules();
????????} else {
????????????log.error("no rule: rules." + ruleName);
????????}
????}

????/**
?????* 規則引擎執行
?????*
?????* @param object
?????*/
????@Override
????public void execute(Object object) {
????????this.kieSession.execute(object);
????}

????/**
?????* drools全局服務變量
?????*/
????@PostConstruct
????public void init() {
????????loadRulesAll();
????}

????/**
?????* @description: 加載所有規則模板
?????* @param:
?????* @return:
????*/
????private void loadRulesAll() {
????????RiskConfig config = new RiskConfig();
????????List<RiskConfig> riskConfigList = riskConfigService.queryRiskConfigs(config);
????????if(riskConfigList!=null){
????????????for(RiskConfig riskConfig : riskConfigList){
????????????????loadRule(riskConfig.getRiskCode(),riskConfig.getRiskContent());
????????????}
????????}
????}

????/**
?????* 單一規則上線
?????*
?????* @param ruleCode
?????* @param ruleContent
?????*/
????private void loadRule(String ruleCode,String ruleContent){
????????try {
????????????KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
????????????kbuilder.add(ResourceFactory.newByteArrayResource(ruleContent.getBytes()), ResourceType.DRL);
????????????if(kbuilder.hasErrors()){
????????????????log.error("加載規則模板引擎異常{},{}",ruleCode,kbuilder.getErrors());
????????????????return;
????????????}
????????????kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
????????????kieSession = kbase.newStatelessKieSession();
????????????printRules();
????????????setGlobal();
????????}catch (Exception e){
????????????log.error("加載規則模板引擎異常",e);
????????}
????}

????/**
?????* @description: 設置全區實現對象
?????* @param:
?????* @return:
????*/
????private void setGlobal(){
????????kieSession.setGlobal("productRiskService", productRiskService);
????}

????/**
?????* 打印規則
?????*/
????private void printRules() {
????????log.info("print rule start: ---------");
???????kbase.getKnowledgePackages().forEach(knowledgePackage ->
????????????????knowledgePackage.getRules().forEach(rule ->
????????????????????????log.info("print rule: " + knowledgePackage.getName() + "." + rule.getName())));
????????log.info("print rule end: ---------");
????}
}

總結

以上是生活随笔為你收集整理的Drools规则引擎介绍及实践的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。