自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

轉(zhuǎn)轉(zhuǎn)圖書(shū)對(duì)基于Drools引擎的DMN實(shí)踐

開(kāi)發(fā) 架構(gòu)
DMN主要應(yīng)用在向程序員以外的人員提供決策管理的能力,以求更準(zhǔn)確地反映目的,從程序員的角度講可能和寫(xiě)ifelse沒(méi)什么不一樣,但是其他角色的參與人員可以通過(guò)較低的學(xué)習(xí)成本來(lái)上手實(shí)現(xiàn)規(guī)則,能夠減少溝通成本和不同人的理解差異產(chǎn)生的不符合預(yù)期的結(jié)果。

1 背景介紹

1.1 DMN是什么

DMN全稱Decision Model and Notation(決策模型和符號(hào)、決策模型和表示法),是一種用于表示業(yè)務(wù)決策和規(guī)則的規(guī)范,旨在幫助參與決策的人都能簡(jiǎn)單快速理解決策過(guò)程。

圖片

DMN logo

DMN是由OMG(Object Management Group,對(duì)象管理組織)管理的一種規(guī)范,該組織下比較知名的還有UML等。

圖片

DMN示例

如圖所示,DMN的表現(xiàn)形式近似于流程圖,通過(guò)可視化來(lái)更直觀地體現(xiàn)出流轉(zhuǎn)和處理的過(guò)程,而各個(gè)節(jié)點(diǎn)使用附帶邏輯的表格來(lái)表現(xiàn)該節(jié)點(diǎn)處理數(shù)據(jù)的方式。

由于DMN是一個(gè)規(guī)范,所以在應(yīng)用上,主要依靠各個(gè)DMN工具供應(yīng)商提供具體實(shí)現(xiàn),近似于SQL語(yǔ)句和MySQL、Oracle的關(guān)系。

1.2 為什么要用DMN

應(yīng)用DMN主要目的是為了解決轉(zhuǎn)轉(zhuǎn)圖書(shū)項(xiàng)目定價(jià)邏輯過(guò)于復(fù)雜的問(wèn)題。

在引入DMN之前,圖書(shū)項(xiàng)目使用java代碼實(shí)現(xiàn)產(chǎn)品人員提供的定價(jià)邏輯。但是隨著邏輯越來(lái)越復(fù)雜,定價(jià)邏輯的代碼也越來(lái)越難以閱讀和維護(hù)。同時(shí),將產(chǎn)品人員的邏輯翻譯成代碼是一個(gè)單向過(guò)程,只有程序員能理解實(shí)現(xiàn)過(guò)程,產(chǎn)品人員只能通過(guò)結(jié)果反推是否正確合理,在邏輯變得復(fù)雜之后,很難快速發(fā)現(xiàn)問(wèn)題。

圖片

復(fù)雜規(guī)則的一部分,區(qū)間和系數(shù)

而通過(guò)DMN,可以可視化的表示出邏輯過(guò)程,產(chǎn)品人員也可以直觀的看到是否符合預(yù)期,還能夠進(jìn)行編輯,從而解決了只有程序員掌握實(shí)現(xiàn)而過(guò)于依賴程序員的問(wèn)題,也能減少表述交流的過(guò)程產(chǎn)生理解偏差進(jìn)而導(dǎo)致的錯(cuò)誤。

圖片

使用DMN實(shí)現(xiàn)的規(guī)則表現(xiàn)

1.3 什么是Drools

Drools是用java語(yǔ)言編寫(xiě)的開(kāi)源規(guī)則引擎,是DMN規(guī)范的一種實(shí)現(xiàn)。舉例來(lái)說(shuō)DMN規(guī)范就是接口,Drools就是實(shí)現(xiàn)了接口的其中一個(gè)工具類。

圖片

Drools logo

Drools屬于Kie開(kāi)源社區(qū),而kie社區(qū)由Red Hat贊助,有比較高的社區(qū)活躍度。

圖片

Kie旗下的產(chǎn)品

1.4 為什么選擇Drools

Drools引擎是基于java實(shí)現(xiàn)的,這使得不需要為Drools單獨(dú)部署運(yùn)行環(huán)境,運(yùn)維成本是0,十分友好。

其次,DMN規(guī)范規(guī)定實(shí)現(xiàn)其規(guī)范的軟件必須滿足三級(jí)遞增的符合性級(jí)別,三級(jí)最高,一級(jí)最低,滿足三級(jí)級(jí)別時(shí)必須同時(shí)滿足一級(jí)和二級(jí)級(jí)別。而Drools引擎對(duì)DMN規(guī)范的支持屬于三級(jí)級(jí)別,功能完善。

圖片

Drools引擎對(duì)DMN各個(gè)版本提供支持

同時(shí),Drools引擎社區(qū)活躍度高,同時(shí)提供了完整的工作組件,可靠性高。

2 Drools引擎應(yīng)用

以下內(nèi)容基于7.61.0版本,與8.x及以上的版本存在差異

2.1 官方推薦的最直接的應(yīng)用方式

首先需要部署運(yùn)行一個(gè)Kie Server用來(lái)執(zhí)行DMN規(guī)則,然后部署Drools官方提供的基于Web的工作站軟件用來(lái)編輯、測(cè)試、發(fā)布DMN規(guī)則。

圖片

Drools提供的工作站軟件

當(dāng)部署完成DMN規(guī)則之后,可以通過(guò)Kie Server REST API來(lái)運(yùn)行規(guī)則獲取結(jié)果,即通過(guò)Http的方式請(qǐng)求Kie Server提供的接口。

2.2 轉(zhuǎn)轉(zhuǎn)圖書(shū)的限制

首先說(shuō)圖書(shū)項(xiàng)目并沒(méi)有直接按照官方推薦的做法部署應(yīng)用,原因有幾個(gè)方面:

第一點(diǎn),轉(zhuǎn)轉(zhuǎn)內(nèi)部項(xiàng)目部署運(yùn)行有自有的框架體系,而Kie Server是基于JBoss運(yùn)行的服務(wù)器軟件,在現(xiàn)有體系中部署一個(gè)外部項(xiàng)目需要額外的運(yùn)維成本。

其次,Kie Server作為一個(gè)第三方工具,當(dāng)出現(xiàn)問(wèn)題時(shí)僅靠圖書(shū)項(xiàng)目的人員難以解決,而等待社區(qū)反饋對(duì)于轉(zhuǎn)轉(zhuǎn)圖書(shū)這種線上的商業(yè)項(xiàng)目難以接收。所以為了盡可能的減少出現(xiàn)問(wèn)題的概率,節(jié)約人力,圖書(shū)項(xiàng)目?jī)A向于盡可能少的引入外部依賴。

基于以上原因,圖書(shū)項(xiàng)目在應(yīng)用Drools的時(shí)候選擇了另外一種方式。

3 脫離Kie Server的Drools引擎實(shí)踐

脫離開(kāi)Kie Server,自然就沒(méi)有了REST API的http接口,同時(shí)也失去了官方工作站的支持,但是相對(duì)的,Drools提供了一些對(duì)這種場(chǎng)景下的支持。

3.1 在線編輯DMN規(guī)則

在Kie旗下有另一款名為Kogito的產(chǎn)品,是一個(gè)提供在線編輯BPMN和DMN的服務(wù)器軟件,同時(shí)其中有一個(gè)all-in-one的js文件,實(shí)現(xiàn)了在線編輯DMN的全部功能。

圖片

js提供的接口

圖書(shū)項(xiàng)目基于這個(gè)js文件進(jìn)行了包裝,增加易用性,使得DMN編輯功能融入到現(xiàn)有的工作后臺(tái)之中。

圖片

包裝頁(yè)面,下方是js提供的功能區(qū)

同時(shí)增加編輯記錄列表用來(lái)便于管理和回滾。

圖片

編輯列表

js工具編輯后的DMN規(guī)則內(nèi)容是xml格式的字符串,可以使用js提供的getContent()接口導(dǎo)出。

3.2 使用Drools引擎執(zhí)行DMN規(guī)則

沒(méi)有了Kie Server的支持之后,需要通過(guò)代碼的方式運(yùn)行Drools引擎。

首先在項(xiàng)目中引入Drools引擎的組件

圖片

引入Drools引擎組件

然后在項(xiàng)目中創(chuàng)建Drools引擎的引用并執(zhí)行。

// 初始化KieServices
KieServices kieServices = KieServices.Factory.get();
// 通過(guò)指定的maven依賴創(chuàng)建Kie容器
ReleaseId releaseId = kieServices.newReleaseId( "com", "my-kjar", "1.0.0" );
KieContainer kieContainer = kieServices.newKieContainer( releaseId );
// 通過(guò)容器獲取DMN運(yùn)行時(shí)
DMNRuntime dmnRuntime = KieRuntimeFactory.of(kieContainer.getKieBase()).get(DMNRuntime.class);
// 通過(guò)DMN運(yùn)行時(shí)獲取需要執(zhí)行的DMNModel,其中包含了DMN規(guī)則
String namespace = "my-namespace";
String modelName = "dmn-model-name";
DMNModel dmnModel = dmnRuntime.getModel(namespace, modelName);
// 獲取上下文,并傳入DMN規(guī)則需要用到的數(shù)據(jù)
DMNContext dmnContext = dmnRuntime.newContext();
dmnContext.set("inputData", "123");
// 執(zhí)行規(guī)則獲取結(jié)果
DMNResult dmnResult = dmnRuntime.evaluateAll(dmnModel, dmnContext);
for (DMNDecisionResult dr : dmnResult.getDecisionResults()) {
log.info("Decision: '" + dr.getDecisionName() + "', " + "Result: " + dr.getResult());
}

由于Kie容器使用maven作為讀取DMN配置的手段,所以要求DMN規(guī)則內(nèi)容需要打包到Kie容器能夠識(shí)別的jar包里,并且部署到項(xiàng)目可訪問(wèn)的maven環(huán)境中。

3.3 完善處理流程

按照上述流程就可以實(shí)現(xiàn)脫離Kie server運(yùn)行Drools引擎。但是距離落地上線還有一小點(diǎn)距離。

官方的工作站可以提供DMN規(guī)則上線前的驗(yàn)證和測(cè)試功能,但是all-in-one的js文件沒(méi)有,所以為了保證準(zhǔn)確性和穩(wěn)定性,需要額外實(shí)現(xiàn)DMN規(guī)則的驗(yàn)證動(dòng)作。

這里可以使用KieContainer提供的verify接口來(lái)觸發(fā)Drools引擎的驗(yàn)證動(dòng)作并獲取結(jié)果。

Results verify = kieContainer.verify();
for (Message message : verify.getMessages()) {
log.info(message.getLevel().name() + ": " + message.getText());
}

將驗(yàn)證流程放到保存DMN規(guī)則的時(shí)候,就可以快速發(fā)現(xiàn)是否存在編寫(xiě)錯(cuò)誤。

3.4 DLC - 脫離maven環(huán)境運(yùn)行Drools引擎

前面說(shuō)了Drools引擎需要使用maven獲取運(yùn)行的DMNjar文件,但是在實(shí)際應(yīng)用中,線上環(huán)境不一定會(huì)部署maven。例如圖書(shū)項(xiàng)目需要在公司內(nèi)部公用的spark集群上運(yùn)行Drools,但是spark集群上沒(méi)有部署maven環(huán)境,按照上述流程運(yùn)行就會(huì)報(bào)錯(cuò)。

所以需要一個(gè)能夠使Drools脫離maven環(huán)境的手段。

通過(guò)分析源碼可以發(fā)現(xiàn),在創(chuàng)建KieContainer的時(shí)候,會(huì)使用KieServices.getRepository()方法獲取數(shù)據(jù)源,并通過(guò)maven坐標(biāo)查找其中的KieModule。所以需要做的就是直接我們需要的jar寫(xiě)入KieServices的數(shù)據(jù)源中:

// 首先通過(guò)JarOutputStream生成包含DMN規(guī)則字符串,且符合Drools規(guī)范的jar二進(jìn)制流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
JarOutputStream jos = new JarOutputStream(outputStream);
// kmodule.xml
jos.putNextEntry(new JarEntry("/META-INF/kmodule.xml"));
jos.write("<?xml versinotallow=\"1.0\" encoding=\"UTF-8\"?><kmodule xmlns=\"http://www.drools.org/xsd/kmodule\"><kbase name=\"kbase_1\" packages=\"rules\" default=\"true\"><ksession name=\"ksession_1\" default=\"true\"/></kbase></kmodule>".getBytes(StandardCharsets.UTF_8));
// pom.properties
jos.putNextEntry(new JarEntry("/META-INF/maven/com.myspace/test/pom.properties"));
jos.write("groupId=com.myspace\nartifactId=test\nversinotallow=1.0.0".getBytes(StandardCharsets.UTF_8));
// pom.xml
jos.putNextEntry(new JarEntry("/META-INF/maven/com.myspace/test/pom.xml"));
jos.write("<?xml versinotallow=\"1.0\" encoding=\"UTF-8\"?><project xsi:schemaLocatinotallow=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\" xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> <modelVersion>4.0.0</modelVersion> <groupId>com.myspace</groupId> <artifactId>test</artifactId> <version>1.0.0</version> <packaging>kjar</packaging> <name>test</name> <description></description></project>".getBytes(StandardCharsets.UTF_8));
// dmn
jos.putNextEntry(new JarEntry("/config/rules/test.dmn"));
jos.write(dmn.getBytes(StandardCharsets.UTF_8));
jos.finish();
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
// 初始化KieServices
KieServices kieServices = KieServices.Factory.get();
// 獲取KieServices的數(shù)據(jù)源
KieRepository repository = kieServices.getRepository();
// 向數(shù)據(jù)源中加入基于生成二進(jìn)制流構(gòu)造的KeiModule
KieModule kieModule = repository.addKieModule(kieServices.getResources().newInputStreamResource(inputStream));

如上就可以實(shí)現(xiàn)在沒(méi)有maven環(huán)境的時(shí)候仍然能夠讓KieServices獲取到我們需要DMN規(guī)則。

但是僅僅如此還不夠,在創(chuàng)建KieContainer的時(shí)候,內(nèi)部會(huì)生成一個(gè)KieProject實(shí)例,KieProject在實(shí)例化的過(guò)程中會(huì)默認(rèn)生成一個(gè)基于maven的MavenClassLoaderResolver用于查找jar,而缺少maven環(huán)境的情況下在生成MavenClassLoaderResolver的時(shí)候也會(huì)報(bào)錯(cuò)。為此,我們需要一個(gè)取代MavenClassLoaderResolver的辦法。

通過(guò)分析Drools源碼可以發(fā)現(xiàn),在源碼中,某些時(shí)候會(huì)使用ProjectClassLoader.findParentClassLoader()來(lái)獲取基于當(dāng)前運(yùn)行環(huán)境的ClassLoader。

所以,需要在創(chuàng)建KieContainer的時(shí)候使用ProjectClassLoader.findParentClassLoader()生成的ClassLoader來(lái)取代默認(rèn)的MavenClassLoaderResolver:

// 使用另外一個(gè)接收ClassLoader的接口來(lái)生成KieContainer
KieContainer kieContainer = kieServices.newKieContainer(kieModule.getReleaseId(), ProjectClassLoader.findParentClassLoader());

如此一來(lái),就可以完全脫離maven環(huán)境來(lái)使用Drools引擎了,而Drools引擎也可以融入到任意的java項(xiàng)目之中,部署到任意的java環(huán)境之下。

4 總結(jié)

DMN在實(shí)際應(yīng)用中有比較明顯的優(yōu)點(diǎn):

  • 可以在不修改代碼的情況下更新邏輯,減少上線過(guò)程中可能產(chǎn)生的問(wèn)題
  • 可以通過(guò)一套代碼實(shí)現(xiàn)各種場(chǎng)景的需求
  • 流程可視化,便于理解邏輯的運(yùn)行
  • 能夠讓一部分不熟悉程序代碼的人員也可以參與編輯,避免流程全部只由程序員了解

但是相對(duì)的也存在一些弊端或者表現(xiàn)不夠好的地方:

  • 流程復(fù)雜時(shí)圖形化表現(xiàn)比較雜亂,尤其是多個(gè)決策節(jié)點(diǎn)依賴相同的上游時(shí)
  • 編輯規(guī)則時(shí)還是會(huì)有一部分場(chǎng)景條件需要寫(xiě)代碼才能實(shí)現(xiàn),例如列表包含(可以使用DMN專用代碼FEEL實(shí)現(xiàn),或者引用已經(jīng)實(shí)現(xiàn)的java方法實(shí)現(xiàn))
  • 運(yùn)行規(guī)則的時(shí)間相較于使用java代碼實(shí)現(xiàn)要慢,因?yàn)橹虚g涉及規(guī)則文件解析和各個(gè)節(jié)點(diǎn)的計(jì)算,而java代碼可以更直接的實(shí)現(xiàn)

圖片

復(fù)雜規(guī)則示例

總體而言,DMN主要應(yīng)用在向程序員以外的人員提供決策管理的能力,以求更準(zhǔn)確地反映目的,從程序員的角度講可能和寫(xiě)ifelse沒(méi)什么不一樣,但是其他角色的參與人員可以通過(guò)較低的學(xué)習(xí)成本來(lái)上手實(shí)現(xiàn)規(guī)則,能夠減少溝通成本和不同人的理解差異產(chǎn)生的不符合預(yù)期的結(jié)果。

5 參考資料

Drools官方網(wǎng)站:https://www.drools.org/

Drools官方的DMN教學(xué):https://www.drools.org/learn/dmn.html

Drools官方的15分鐘簡(jiǎn)易教學(xué):https://learn-dmn-in-15-minutes.com/learn/introduction

Kogito在線編輯網(wǎng)頁(yè):https://sandbox.kie.org/#/

Kie官方網(wǎng)站:https://www.kie.org/

OMG官方網(wǎng)站的DMN頁(yè):https://www.omg.org/dmn/

作者簡(jiǎn)介

項(xiàng)贏,轉(zhuǎn)轉(zhuǎn)資深java工程師。長(zhǎng)期服務(wù)于轉(zhuǎn)轉(zhuǎn)圖書(shū)項(xiàng)目。

責(zé)任編輯:武曉燕 來(lái)源: 轉(zhuǎn)轉(zhuǎn)技術(shù)
相關(guān)推薦

2023-06-07 08:32:32

引擎技術(shù)while

2024-07-31 20:45:45

2023-10-16 17:41:40

Drools

2023-07-12 08:33:34

引擎LiteFlow編排

2023-11-01 07:44:29

轉(zhuǎn)轉(zhuǎn)Flutter業(yè)務(wù)

2022-11-07 14:45:26

轉(zhuǎn)轉(zhuǎn)價(jià)格DDD

2023-12-27 19:12:42

OLAP自助分析

2022-10-28 08:31:43

2023-03-02 08:32:41

2023-03-02 08:54:32

2023-03-22 08:32:35

2022-10-28 09:15:02

2023-02-08 09:42:30

策略方式容量

2022-12-15 08:35:01

用戶畫(huà)像平臺(tái)

2023-04-19 13:18:41

動(dòng)態(tài)線程池平臺(tái)

2024-06-06 08:18:42

回收業(yè)務(wù)

2024-07-18 08:40:28

2024-11-25 08:20:22

2023-08-24 08:11:39

斷路器監(jiān)控報(bào)警

2023-03-29 08:33:03

倉(cāng)儲(chǔ)自動(dòng)化系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)