Drools 5.1.1(一)
?http://shikonglaike.iteye.com/blog/1236354
第一章歡迎
我總是和終端業(yè)務(wù)用戶爭論不休,理解規(guī)則和流程、最新規(guī)則和事件處理的區(qū)別。對(duì)此,在他們的意識(shí)中有這樣的問題,并且他們希望使用某些軟件模擬它。使用兩個(gè)供應(yīng)商提供的傳統(tǒng)方式,強(qiáng)迫業(yè)務(wù)用戶與一個(gè)剛剛獲得方式的面向流程或面向規(guī)則的方法一起工作,他們將使用該工具模擬這點(diǎn),往往整體是極為混亂的。
PegaSystems和Microsoft做了大量的工作,顯示兩者可以被結(jié)合,并且可以使用一個(gè)行為的模擬方法。這讓業(yè)務(wù)用戶更自然地應(yīng)用提供給他們的各種方法工作,不必使用獲得方式的工具。從面向流程到面向規(guī)則或中間的灰色地帶——任何當(dāng)時(shí)的相應(yīng)問題被模擬。
Drools5.0更進(jìn)了一步,不僅增加了基于工作流與Drools流的BPMN2,而且增加了事件處理與DroolsFusion(熔合),為軟件開發(fā)者創(chuàng)建了一個(gè)更全面的方法。此處的術(shù)語“全面的”被用來強(qiáng)調(diào)整體和它局部間的相互依賴性的重要性。
Drools5.0現(xiàn)在被劃分為5個(gè)模塊,每個(gè)都自帶手冊(cè)——Guvnor(BRMS/BPMS),Expert(Rules),Fusion(CEP),Flow(Process/Workflow)和Planner。Guvnor是我們的基于網(wǎng)頁的管理系統(tǒng),在規(guī)則世界中傳統(tǒng)提及的,如一個(gè)BRMS(商業(yè)規(guī)則管理系統(tǒng))。我們決定拋棄一個(gè)擔(dān)當(dāng)管理工作的BRMS術(shù)語,因?yàn)樗皇且?guī)則的細(xì)節(jié)。Expert是傳統(tǒng)的規(guī)則引擎。Fusion是事件處理邊,它擔(dān)當(dāng)數(shù)據(jù)/傳感器的熔合術(shù)語。Flow是我們的工作流模塊,由KrisVerlaenen領(lǐng)導(dǎo),已經(jīng)做了一些了不起的工作;他正把流與jBPM5合成一體。第5個(gè)模塊是Planner,由GeoffreyDeSmet撰寫,解決分配和調(diào)度類型的問題。雖然還處在開發(fā)的初期階段,但已顯示了許多期望。我們希望為2011版增加Semantics(語義),基于描述邏輯,并讓它擔(dān)當(dāng)下一代Drools引擎的一部分。
我一直工作在規(guī)則領(lǐng)域,現(xiàn)在大約7年了。我終于感覺到我緊握東西,想法開始成形,并且真正的創(chuàng)新開始出現(xiàn)。對(duì)我來說,感覺就象我確實(shí)知道我們現(xiàn)在將做什么,與過去相比,有許多瘋狂的猜想和探索。我與EdsonTirelli和DavideSottara一起努力工作在DroolsExpert設(shè)計(jì)文檔上。我邀請(qǐng)你閱讀文檔和參與http://community.jboss.org/wiki/DroolsLanguageEnhancements。該文檔帶有東西給下一級(jí),推動(dòng)Drools成為一個(gè)混合的引擎,不僅是一個(gè)有能力生產(chǎn)規(guī)則的系統(tǒng),而且混合了邏輯編程(prolog)與功能編程,以及帶有其他想法的更有表現(xiàn)力和現(xiàn)代感語言的描述邏輯。
我希望你能感覺到我們的團(tuán)隊(duì)和我在Drools上工作的熱情,希望在你的冒險(xiǎn)期間能感染你。
MarkProctor(Drools創(chuàng)建者和領(lǐng)導(dǎo))
第二章Drools發(fā)行說明
2.1在Drools5.1.0中,值得注意的新東西。
?
2.1.1DroolsAPI
如在Drools5.0中一樣,仍然可以使用配置配置一個(gè)KnowledgeBase(知識(shí)庫),通過一個(gè)xml改變集合(changeset),而不是編程方式。然而,現(xiàn)在的change-set命名空間被版本化了。這意味著,在Drools5.1.0中,1.0.0xsd應(yīng)該被引用。
例子2.1下面是一個(gè)簡單的版本1.0.0改變集合
<change-setxmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-setchange-set-5.0.xsdhttp://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd'>
<add>
<resourcesource='classpath:org/domain/someRules.drl'type='DRL'/>
<resourcesource='classpath:org/domain/aFlow.drf'type='DRF'/>
</add>
</change-set>
?
2.1.2核心
?
2.1.2.1JMX監(jiān)控
JMX監(jiān)控被添加來支持知識(shí)庫監(jiān)控。這尤其重要,象一個(gè)常需要事件處理的長期運(yùn)行流程。初始化整合JOPR也被添加。JMX可以被啟用,使用屬性設(shè)置知識(shí)庫:
drools.mbeans=<enabled|disabled>或者這個(gè)選項(xiàng)在運(yùn)行時(shí)啟用:
kbaseConf.setOption(MBeansOption.ENABLED)
2.1.2.2Spring
Drools現(xiàn)在有擴(kuò)展的Spring支持,XSD可以在drools-springjar中發(fā)現(xiàn)。命名空間為"http://drools.org/schema/drools-spring"。
例子2.2知識(shí)庫構(gòu)建器例子
?
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:drools="http://drools.org/schema/drools-spring"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://drools.org/schema/drools-springhttp://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-container/drools-spring/src/main/resources/org/drools/container/spring/drools-spring-1.0.0.xsd
http://camel.apache.org/schema/springhttp://camel.apache.org/schema/spring/camel-spring.xsd">
<drools:resourceid="resource1"type="DRL"source="classpath:org/drools/container/spring/testSpring.drl"/>
<drools:kbaseid="kbase1">
<drools:resources>
<drools:resourcetype="DRL"source="classpath:org/drools/container/spring/testSpring.drl"/>
<drools:resourceref="resource1"/>
<drools:resourcesource="classpath:org/drools/container/spring/IntegrationExampleTest.xls"type="DTABLE">
<drools:decisiontable-confinput-type="XLS"worksheet-name="Tables_2"/>
</drools:resource>
</drools:resources>
<drools:configuration>
<drools:mbeansenabled="true"/>
<drools:event-processing-modemode="STREAM"/>
</drools:configuration>
</drools:kbase>
</beans>
知識(shí)庫接受下面的配置:"advanced-process-rule-integration,multithread,mbeans,event-processing-mode,accumulate-functions,evaluatorsandassert-behavior"。
?
根據(jù)kbase參考可以創(chuàng)建ksessions
例子2.3知識(shí)會(huì)話
<drools:ksessionid="ksession1"type="stateless"name="stateless1"kbase="kbase1"/>
<drools:ksessionid="ksession2"type="stateful"kbase="kbase1"/>
象知識(shí)庫的知識(shí)會(huì)話可以接受一些配置,包括"work-item-handlers,"keep-references","clock-type","jpa-persistence"。
例子2.4知識(shí)會(huì)話的配置
<drools:ksessionid="ksession1"type="stateful"kbase="kbase1">
<drools:configuration>
<drools:work-item-handlers>
<drools:work-item-handlername="handlername"ref="handlerid"/>
</drools:work-item-handlers>
<drools:keep-referenceenabled="true"/>
<drools:clock-typetype="REALTIME"/>
</drools:configuration>
</drools:ksession>
StatefulKnowledgeSessions(有狀態(tài)知識(shí)會(huì)話)可以被配置為JPA持久化
?
例子2.5JPA配置用于StatefulKnowledgeSessions
<beanid="ds"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<propertyname="driverClassName"value="org.h2.Driver"/>
<propertyname="url"value="jdbc:h2:tcp://localhost/DroolsFlow"/>
<propertyname="username"value="sa"/>
<propertyname="password"value=""/>
</bean>
<beanid="myEmf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<propertyname="dataSource"ref="ds"/>
<propertyname="persistenceUnitName"value="org.drools.persistence.jpa.local"/>
</bean>
<beanid="txManager"class="org.springframework.orm.jpa.JpaTransactionManager">
<propertyname="entityManagerFactory"ref="myEmf"/>
</bean>
<drools:ksessionid="jpaSingleSessionCommandService"type="stateful"kbase="kbase1">
<drools:configuration>
<drools:jpa-persistence>
<drools:transaction-managerref="txManager"/>
<drools:entity-manager-factoryref="myEmf"/>
<drools:variable-persisters>
<drools:persisterfor-class="javax.persistence.Entity"implementation="org.drools.persistence.processinstance.persisters.JPAVariablePersister"/>
<drools:persisterfor-class="java.lang.String"implementation="org.drools.container.spring.beans.persistence.StringVariablePersister"/>
<drools:persisterfor-class="java.io.Serializable"implementation="org.drools.persistence.processinstance.persisters.SerializableVariablePersister"/>
</drools:variable-persisters>
</drools:jpa-persistence>
</drools:configuration>
</drools:ksession>
知識(shí)庫會(huì)話可以支持啟動(dòng)批處理腳本,前面的版本使用"script"元素名,它將被更新為"batch"。下面的命令被支持:"insert-object","set-global","fire-all-rules","fire-until-halt","start-process","signal-event"。可以使用匿名Bean或命名"ref"屬性。
例子2.6啟動(dòng)批處理命令
?
<drools:ksessionid="jpaSingleSessionCommandService"type="stateful"kbase="kbase1">
<drools:script>
<drools:insert-objectref="person1"/>
<drools:start-processprocess-id="procname">
<drools:parameteridentifier="varName"ref="varRef"/>
</drools:start-process>
<drools:fire-all-rules/>
</drools:script>
</drools:ksession>
?
在Spring中支持執(zhí)行節(jié)點(diǎn)(ExecutionNodes),它們提供了一個(gè)注冊(cè)的ksessions。它可以與Camel一起提供ksessions路由。
2.1.2.3Camel
Spring可以與Camel組合,提供聲明式規(guī)則服務(wù)。一個(gè)Camel策略從Drools被添加,Drools提供魔法注入類加載器(ClassLoader),類加載器被ksession用于任何數(shù)據(jù)的格式化,它還增強(qiáng)了JAXB和XStream數(shù)據(jù)的格式化。假如在Jaxb情況下,它添加另外的Drools路徑信息,利用XStream注冊(cè)Drools相關(guān)聯(lián)的轉(zhuǎn)換器,并取別名。
你可以使用不同的地址,創(chuàng)建你需要的盡可能多的端點(diǎn)。需要CommandMessagBodyReader分配有效負(fù)荷給Camel處理。
例子2.8Rest端點(diǎn)配置
<cxf:rsServerid="rsServer"
address="/kservice/rest"
serviceClass="org.drools.jax.rs.CommandExecutorImpl">
<cxf:providers>
<beanclass="org.drools.jax.rs.CommandMessageBodyReader"/>
</cxf:providers>
</cxf:rsServer>
然后,Camel路由可以連接到CXF端點(diǎn),允許你控制如數(shù)據(jù)的格式化和根據(jù)Droolsksessions執(zhí)行等事情的有效負(fù)荷。Drools策略增加某些智能給路由。如果使用JAXB或XStream,它將注入定制路徑和轉(zhuǎn)換器,它也可以在服務(wù)器邊設(shè)置類加載器,基于目標(biāo)ksessions的。在客戶邊,它自動(dòng)解包Response(響應(yīng))對(duì)象。
?
這個(gè)例子使用了一個(gè)增強(qiáng)的XStream的數(shù)據(jù)格式解組有效負(fù)荷,并且根據(jù)ksession1實(shí)例執(zhí)行它。"node"在這兒引用了ExecutionContext(執(zhí)行上下文),它是一個(gè)注冊(cè)的ksessions上下文。
例子2.9Camel路由
<beanid="droolsPolicy"class="org.drools.camel.component.DroolsPolicy"/>
<camelContextid="camel"xmlns="http://camel.apache.org/schema/spring">
<route>
<fromuri="cxfrs://bean://rsServer"/>
<policyref="droolsPolicy">
<unmarshalref="xstream"/>
<touri="drools://node/ksession1"/>
<marshalref="xstream"/>
</policy>
</route>
</camelContext>
Drools端點(diǎn)"drools:node/ksession1",由執(zhí)行節(jié)點(diǎn)名字、分隔符和可選的知識(shí)會(huì)話名字構(gòu)成。如果知識(shí)會(huì)話沒有指定路由,會(huì)查找在輸入的有效負(fù)荷的實(shí)例中的"lookup"屬性,或者在頭部屬性"DroolsLookup"中去查找。
2.1.2.4Drools服務(wù)器
Spring,Camel和CXF可以被組合,用于聲明式服務(wù),drools-server是一個(gè).war,組合了它們與某些開箱即用的例子xml,就像一類模板。如果你正在jboss容器中使用war,,那么你需要添加這個(gè)組件,http://camel.apache.org/camel-jboss.html。該war包含了一個(gè)test.jsp,顯示一個(gè)象你開始的例子一樣的回顯。這個(gè)例子只是執(zhí)行一個(gè)簡單的"echo"類型的應(yīng)用程序。它發(fā)送一個(gè)消息到規(guī)則服務(wù)器,規(guī)則服務(wù)器預(yù)先增加單詞"echo"到開頭,并發(fā)送它回去。默認(rèn)時(shí),消息是"HelloWorld",使用url參數(shù)msg——test.jsp?msg="MyCustomMessage",可以傳遞不同的消息。
?
2.1.2.5知識(shí)代理增量變化支持
新版的知識(shí)庫代理在它配置中支持newInstance=false(增量變化集合構(gòu)建)。
?
當(dāng)設(shè)置這個(gè)屬性為false,知識(shí)庫代理使用存在的知識(shí)庫參考應(yīng)用增量變化。現(xiàn)在知識(shí)庫代理可以用增量的方式處理監(jiān)控的資源更改。更改的定義被編譯,并和原始版本比較。根據(jù)定義的類型,以不同的方式表現(xiàn):
l?Rules:用于規(guī)則,代理搜索在它的屬性中的更改,左手邊和右手邊。
l?Queries:查詢總在kbase上被替代,無論它們被更改還是沒有被更改。
l?其他定義:所有其他定義總是在kbase中被替代(只要它們被更改)。我們希望在將來的版本中,為更改定義的探測增加更好的支持。
當(dāng)前的實(shí)現(xiàn)只支持規(guī)則、查詢和函數(shù)定義的探測。類型聲明不能被探測。
2.1.2.6會(huì)話檢查與報(bào)告框架
一個(gè)用于運(yùn)行時(shí)會(huì)話檢查與報(bào)告的基于框架的新的API被引入,從而更好地在調(diào)試或應(yīng)用程序成型時(shí)采集數(shù)據(jù)。這個(gè)檢查框架將成為加工功能的基礎(chǔ),用來幫助為每個(gè)會(huì)話的內(nèi)容提供更詳細(xì)的信息。這個(gè)api是實(shí)驗(yàn)性的,并不是用在drools-api中,但可自由的使用,并幫助我們改進(jìn)它。
要檢查一個(gè)會(huì)話,可以使用以下api調(diào)用之一:
例子2.10創(chuàng)建一個(gè)會(huì)話檢查器
StatefulKnowledgeSessionksession=...
//...insertfacts,firerules,etc
SessionInspectorinspector=newSessionInspector(ksession);
StatefulKnowledgeSessionInfoinfo=inspector.getSessionInfo();
StatefulKnowledgeSessionInfo實(shí)例將包含許多在會(huì)話分析期間采集的相關(guān)數(shù)據(jù)。提供了一個(gè)簡單的例子報(bào)告模板,并且可以利用下面的api調(diào)用產(chǎn)生:
例子2.11產(chǎn)生一個(gè)報(bào)告
Stringreport=SessionReporter.generateReport("simple",info,null);
?
2.1.3Expert
2.1.3.1差異更新
傳統(tǒng)Rete算法用retract+assert(撤消+斷言)做一個(gè)更新,對(duì)一個(gè)給定的事實(shí),這導(dǎo)致所有的局部匹配被撤銷,然而,在assert(斷言)期間,其中一些會(huì)被再次重建;因?yàn)樗鼈冊(cè)诟虑盀閠rue,并且在更新后仍然為true。這導(dǎo)致許多不需要的對(duì)象被摧毀,并且這些行為增加了垃圾收集器的負(fù)荷。現(xiàn)在的更新是一個(gè)單程,并在適當(dāng)?shù)奈恢脵z查局部匹配,避免不必要的局部匹配被摧毀。經(jīng)歷事件和實(shí)事維護(hù)的一個(gè)正規(guī)化過程也不再需要;正規(guī)化過程是我們準(zhǔn)備著眼于激活retract(撤消)的地方,被插入的激活斷定真正被添加的東西,由真正插入的東西確定“差異”。
?
2.1.3.2Channels(通道)
退出點(diǎn)已經(jīng)用更合適的名字Channels(通道)替代,我們覺得它更合適,因?yàn)槎鄠€(gè)規(guī)則引擎可以使用它們,并且不是切入點(diǎn)的精確對(duì)立面。切入點(diǎn)明顯與進(jìn)入Rete網(wǎng)絡(luò)中的一個(gè)分區(qū)有關(guān)聯(lián)。
2.1.3.3現(xiàn)場查詢
Doorls一直有一個(gè)查詢支持,但結(jié)果是以一個(gè)可迭代的集合返回;這使監(jiān)測隨著時(shí)間的變化很困難。
?
我們現(xiàn)在用現(xiàn)場查詢實(shí)現(xiàn)它,它與一個(gè)偵聽器相連,而不是返回一個(gè)可迭代的集合。這些現(xiàn)實(shí)查詢持續(xù)打開創(chuàng)建的一個(gè)視圖,并且為這個(gè)視圖的內(nèi)容發(fā)布變化事件。所以,你現(xiàn)在可以執(zhí)行你的查詢,利用參數(shù),并在結(jié)果視圖中偵聽變化。
?
例子2.12實(shí)現(xiàn)ViewChangedEventListener
?
finalListupdated=newArrayList();
finalListremoved=newArrayList();
finalListadded=newArrayList();
?
ViewChangedEventListenerlistener=newViewChangedEventListener(){
publicvoidrowUpdated(Rowrow){
updated.add(row.get("$price"));
}
?
publicvoidrowRemoved(Rowrow){
removed.add(row.get("$price"));
}
?
publicvoidrowAdded(Rowrow){
added.add(row.get("$price"));
?
}
};
?
//OpentheLiveQuery
?
LiveQueryquery=ksession.openLiveQuery("cheeses",newObject[]{"cheddar","stilton"},listener);
...
?
...
query.dispose()//makesureyoucalldisposewhenyouwantthequerytoclose
?
?
一個(gè)Doorls博客文章包含了一個(gè)用于現(xiàn)場查詢的Glazed列表集成的例子
?
http://blog.athico.com/2010/07/glazed-lists-examples-for-drools-live.html(不可用)
?
[http://planet.jboss.org/view/post.seam;jsessionid=8F25E6F156E3093608A38BDCCE17369C?post=glazed_lists_examples_for_drools_live_querries]
?
2.1.3.4定時(shí)器和日歷
規(guī)則現(xiàn)在支持基于interval(間隔)和cron定時(shí)器,替代了過時(shí)的duration(期限)屬性。
例子2.13定時(shí)器屬性使用的例子
timer(int:<initialdelay><repeatinterval>?)
timer(int:30s)
timer(int:30s5m)
timer(cron:<cronexpression>)
timer(cron:*0/15***?)
?
Interval"int:"定時(shí)器遵守JDK語義,初始化延遲,緊跟一個(gè)可選的重復(fù)間隔。Cron"cron:"定時(shí)器遵守標(biāo)準(zhǔn)的cron表達(dá)式:
?
例子2.14一個(gè)Cron例子
rule"SendSMSevery15minutes"
timer(cron:*0/15***?)
when
$a:Alarm(on==true)
then
channels["sms"].insert(newSms($a.mobileNumber,"Thealarmisstillon");
end
當(dāng)規(guī)則被引發(fā)時(shí),現(xiàn)在可以控制日歷。日歷api是模擬Quartzhttp://www.quartz-scheduler.org/:
例子2.15調(diào)節(jié)一個(gè)Quartz日歷
CalendarweekDayCal=QuartzHelper.quartzCalendarAdapter(org.quartz.CalendarquartzCal)
日歷使用StatefulKnowledgeSession(有狀態(tài)知識(shí)會(huì)話)注冊(cè):
例子2.16注冊(cè)一個(gè)日歷
ksession.getCalendars().set("weekday",weekDayCal);
它們可以同時(shí)用于普通規(guī)則和包含定時(shí)器的規(guī)則中。規(guī)則的calendar屬性可以有一個(gè)或多個(gè)逗點(diǎn)日歷名字:
例子2.17一起使用日歷和定時(shí)器
rule"weekdaysarehighpriority"
calendars"weekday"
timer(int:01h)
when
Alarm()
then
send("priorityhigh-wehaveanalarm);
end
?
rule"weekendarelowpriority"
calendars"weekend"
timer(int:04h)
when
Alarm()
then
send("prioritylow-wehaveanalarm);
end
2.1.3.5決策表(Excel)
2.1.3.5.1簡單模板,用于單元格內(nèi)部可變長度逗點(diǎn)分隔的列表
在一個(gè)單元格中可以有一個(gè)逗點(diǎn)分隔的列表,并且用一個(gè)forall模板可以渲染它們。
例子2.18DTableforall語法
forall(<separator>?){<codesnippt>}
例子2.19DTableforall例子
forall(,){propertyName==$}
forall(&&){propertyName==$}
forall(||){propertyName==$}
forall(||){propertyNameA==$}&&forall(||){propertyNameB==$}
等等
2.1.4Flow
2.1.4.1BPMN2
正如我們?cè)缙谝研Q的一樣,Dools團(tuán)隊(duì)已決定支持使用XML指定業(yè)務(wù)流程的即將到來的BPMN2.0規(guī)范。這個(gè)里程碑包含了BPMN2解析器的重大擴(kuò)展,使用DroolsFlow來支持BPMN2的更多功能。更具體的有:
?
l?更廣泛的事件支持:更多的事件類型組合(開始、中間、結(jié)束)和事件觸發(fā)(例如,包括錯(cuò)誤、升級(jí)、定時(shí)器、條件、信號(hào)事件),以及已包括(中斷和非中斷)邊界事件。
l?子流程參數(shù)。
l?發(fā)散的綜合性出入口
l?等等
BPMN2已被集成在完整的Dools工具鏈中,支持業(yè)務(wù)流程的整個(gè)生命周期。它包括:
?
l?能夠與我們的Eclipse工具一起使用BPMN2流程。
l?Guvnor作為流程庫。
l?基于網(wǎng)頁的管理,使用BPM控制臺(tái)。
l?審計(jì)和調(diào)試。
l?特殊域流程。
l?等等
因此,DroolsFlow不僅是一流的開源流程引擎,天然地支持這樣一個(gè)重要的BPMN2結(jié)構(gòu)集合,而且我們的面向知識(shí)的方法,也允許你容易組合你的BPMN2流程與業(yè)務(wù)規(guī)則,以及復(fù)雜的事件處理,完全使用相同的APIs和工具。
2.1.4.2基于網(wǎng)頁的管理控制臺(tái)
現(xiàn)在也可以通過一個(gè)網(wǎng)頁控制臺(tái)管理DroolsFlow流程。它包括的功能有:管理你的流程實(shí)例(開始/停止/檢查),檢查你的(人的)任務(wù)列表,執(zhí)行那些任務(wù),產(chǎn)生報(bào)表。
?
這個(gè)控制臺(tái)實(shí)際上是HeikoBraun的工作(卓越的),他創(chuàng)建了一個(gè)通用的BMP控制臺(tái),可以被用來支持多種流程語言。我們實(shí)現(xiàn)了必要的組件,允許這個(gè)控制臺(tái)能與DroolsFlow引擎通信。
2.1.4.3可插式可變持久化
DroolsFlow可以持久化運(yùn)行流程的運(yùn)行時(shí)間狀態(tài)到一個(gè)數(shù)據(jù)庫(所以它們完全不需要在內(nèi)存,并且在故障情況時(shí)可以被存儲(chǔ))。我們的默認(rèn)持久化機(jī)制是用一個(gè)二進(jìn)制對(duì)象(利用相關(guān)的元數(shù)據(jù))存儲(chǔ)關(guān)聯(lián)于一個(gè)流程實(shí)例的所有運(yùn)行時(shí)間信息。關(guān)聯(lián)這個(gè)流程實(shí)例(又名流程實(shí)例變量)的數(shù)據(jù)也作為這個(gè)二進(jìn)制對(duì)象的一部分被存儲(chǔ)。然而這可以產(chǎn)生問題(1)在數(shù)據(jù)沒有被序列化時(shí),(2)當(dāng)用流程實(shí)例狀態(tài)的部分持久化,對(duì)象太大時(shí),或者(3)在其他地方已經(jīng)被持久化時(shí)。為此,我們實(shí)現(xiàn)了可插式可變持久化,用戶可以定義多少變量的值被存儲(chǔ)。例如,它允許你存儲(chǔ)個(gè)別變量的值,并且支持JPA實(shí)體被分別存儲(chǔ)和引用(避免狀態(tài)重復(fù))。
2.1.4.4改進(jìn)的流程實(shí)例移植
隨著時(shí)間的推移,流程可以進(jìn)化。每當(dāng)一個(gè)流程更新,確定已經(jīng)運(yùn)行的流程實(shí)例會(huì)發(fā)生什么是重要的。我們改進(jìn)了我們的支持,用于移植運(yùn)行的流程實(shí)例到流程定義的一個(gè)新版本。更多信息請(qǐng)看DroolsFlow文檔。
2.1.4.5安裝腳本
Drools構(gòu)建輸出了一個(gè)安裝器,它簡化了Guvnor和gwt-控制臺(tái)的Eclipse插件的安裝。它創(chuàng)建了和復(fù)制了需要的jars和war,并且布置它們到JBossAS。它也包含了一個(gè)簡單的求值流程例子,你可以用它測試你的安裝。更多信息,下載Drools安裝器,請(qǐng)看其內(nèi)部的自述文件readme。
?
2.1.5Guvnor
?
外觀已被清潔,例如少了彈出窗口。意味著用斷言和有關(guān)行為發(fā)生的信息更改之后的節(jié)省,以及如果出錯(cuò)時(shí),更好的錯(cuò)誤報(bào)告。
?
2.1.5.3討論
?
注釋是在下面的“文檔”部分(當(dāng)然是可選的)(并且有一個(gè)Atom供應(yīng)給它們)
圖2.1實(shí)時(shí)討論
?
一個(gè)"backchannel(反向通道)"類型連接,保持了對(duì)瀏覽器的開放,允許消息推回——這意味著(在啟用時(shí))信息實(shí)時(shí)顯示(和其他便利的事情一樣,如果某東西添加到一個(gè)列表——列表就會(huì)被更新)
?
2.1.5.4收件箱
?
收件箱功能提供了這樣的能力,跟蹤你打開或編輯的東西——這顯示在主導(dǎo)航器中的"Inbox"項(xiàng)目下。
?
?
圖2.2收件箱分類
?
?
l?最近打開的
?
點(diǎn)擊recentlyopened條目,會(huì)打開“最近”打開過的所有項(xiàng)目的一個(gè)列表(它跟蹤最近你看過的數(shù)百個(gè)項(xiàng)目)。
?
l?最近編輯的
?
所有你保存過的項(xiàng)目,或者注釋,將馬上顯示在這里。
?
l?收到的更改
?
它跟蹤“其他人”對(duì)“你”的“最近編輯”列表中的項(xiàng)目所做的更改。當(dāng)你打開這些項(xiàng)目,那么它們會(huì)從這個(gè)列表中刪除(但仍然保留在你最近編輯過的列表中)
?
圖2.3收件箱項(xiàng)目列表。
?
2.1.5.5批量導(dǎo)入器
?
Guvnor導(dǎo)入器是一個(gè)maven構(gòu)建工具,遞規(guī)你的規(guī)則目錄結(jié)構(gòu),并且構(gòu)建一個(gè)導(dǎo)入文件,通過import/export管理功能可以手動(dòng)導(dǎo)入它到Drools-Guvnor網(wǎng)頁界面。
?
2.1.5.6DroolsDoc
?
PDF文檔包含了有關(guān)包和每個(gè)DRL資產(chǎn)(asset)的信息。DroolsDoc作為知識(shí)包可以從"InformationandimportantURLs"下的包視圖(packageview)下載。
?
2.1.5.7更新為GWT2.0
?
GWT被更新,使DroolsGuvnor更快。
?
2.1.5.8安裝選擇器
?
安裝選擇器允許用戶選擇什么樣的資產(chǎn)構(gòu)建,依據(jù):
?
n?狀態(tài)(例如,開發(fā),質(zhì)量保證等)
n?分類
n?元數(shù)據(jù)
?
2.1.5.9單資產(chǎn)驗(yàn)證
?
只要是你正在運(yùn)行的資產(chǎn)(規(guī)則流、規(guī)則、決策表),就可以驗(yàn)證。驗(yàn)證發(fā)現(xiàn)諸如在一個(gè)規(guī)則中的沖突限制或在決策表中的多余行等問題。
?
2.1.5.10全局區(qū)
儲(chǔ)存在全局區(qū)的資產(chǎn)可以被所有包共享。
?
2.1.5.11快照之間的差異檢查
?
列出兩個(gè)快照之間的變化。
?
2.1.5.12在一個(gè)標(biāo)簽中查看多個(gè)資產(chǎn)
?
可以在一個(gè)視圖中打開多個(gè)資產(chǎn)。所有的資產(chǎn)可以作為一個(gè)組被保存和編輯。
?
2.1.5.13From/Collect/Accumulate支持
?
指導(dǎo)編輯器已基本支持From,Accumulate和Collect模式。你可以添加它們中的任何一個(gè)結(jié)構(gòu)作為正規(guī)模式。新的表達(dá)式構(gòu)建器組件被創(chuàng)建,增加了對(duì)嵌套方法調(diào)用的一個(gè)變量支持。在規(guī)則的WHEN部分頂部使用了“加”按鈕,或者使用呈現(xiàn)在每個(gè)模式中的新的“在后面增加”按鈕,將打開彈出,添加新的條件元素到你的規(guī)則中。在可能元素的列表中的,你會(huì)發(fā)現(xiàn)三個(gè)新的條目:”From”,“FromAccumulate”和“FromCollect”。
?
當(dāng)你添加一個(gè)新的”From”元素,你會(huì)在指導(dǎo)編輯器看到下面這樣圖象的東西。左邊模式的”From”條件元素是一個(gè)正規(guī)模式。你可以在這里添加你希望的任何類型的條件元素。右邊部分的”From”模式是一個(gè)表達(dá)式構(gòu)建器。
?
圖2.4來自一個(gè)CE構(gòu)建器
?
當(dāng)你在左邊模式中使用“FromCollect”時(shí),你可以選擇“java.util.Collection”,“java.util.List”或“java.util.Set”事實(shí)類型。這個(gè)事實(shí)類型會(huì)被自動(dòng)包含在事實(shí)類型列表中。
?
右邊模式的收集條件元素可以是下面模式之一:
?
n?FactTypePattern(事實(shí)類型模式)
n?FreeFormExpression(自由表單表達(dá)式)
n?FromPattern(From模式)
n?FromCollectPattern(FromCollect模式)
n?FromAccumulatePattern(FromAccumulate模式)
?
圖2.5來自CollectCE構(gòu)建器
?
當(dāng)使用“FromAccumulate”時(shí),左邊模式可以是任何事實(shí)類型模式。這個(gè)條件元素的右邊部分被劃分成兩個(gè):
?
圖2.6來自累積CE構(gòu)建器
?
左邊模式可以是任何事實(shí)類型模式。這個(gè)條件元素的右邊部分被劃分成兩個(gè):
?
源模式:(在載圖中的,Bed$n)可以是任何事實(shí)類型、From、Collect或者Accumulate模式
?
累積函數(shù):在這里你可發(fā)現(xiàn)一個(gè)標(biāo)簽式面板,你可以輸入一個(gè)累積函數(shù)(在截圖中的sum()),或者你可以使用“CustomCode”創(chuàng)建一個(gè)在線定制函數(shù)。
?
2.1.5.14規(guī)則模板
?
規(guī)則模板可以被指導(dǎo)編輯器用于編輯復(fù)雜的規(guī)則,然后通過一個(gè)電子表格的表格數(shù)據(jù)隱喻輕松地編寫它。替代了一個(gè)字段的值,僅是用名為"TemplateKey"標(biāo)識(shí)它,并且該key可以作為網(wǎng)格中的一個(gè)列。每行可以應(yīng)用規(guī)則模板來產(chǎn)生一個(gè)規(guī)則。
?
圖2.7在'WHEN'部分增加了一個(gè)TemplateKey。
?
圖2.8"THEN"部分增加了一個(gè)TemplateKey。
?
圖2.9根據(jù)這些TemplateKey填充行。
?
圖2.10每行產(chǎn)生一個(gè)規(guī)則
?
2.1.5.15工作集
?
在建模規(guī)則時(shí),用戶暴露所有的事實(shí)類型,它可能是整個(gè)的很小部分。工作集允許相關(guān)的事實(shí)類型分組在一起,并在編寫規(guī)則時(shí),提供一個(gè)更易于管理的選擇事實(shí)類型的視圖。
?
圖2.11顯示導(dǎo)入的類型。
?
圖2.12創(chuàng)建一個(gè)動(dòng)物工作集。
?
圖2.13沒有使用工作集,所有類型是可見的。
?
圖2.14選擇動(dòng)物工作集。
?
圖2.15可用的類型減少了。
2.1.5.16事實(shí)約束
工作集可以與事實(shí)約束相結(jié)合,提供額外的設(shè)計(jì)時(shí)間驗(yàn)證。例如,如果你依據(jù)某個(gè)人的年齡編寫一個(gè)規(guī)則,在設(shè)計(jì)時(shí),我們可以分辨有效的范圍,并且使用它來約束作者。事實(shí)約束是工作集的一部分,并且在編輯一個(gè)規(guī)則時(shí),你必然選擇工作集約束,那個(gè)你希望用于作為驗(yàn)證處理部分的約束。
?
圖2.16選擇字段。
?
圖2.17選擇字段約束類型.
?
圖2.18一個(gè)范圍選擇的例子。
?
圖2.19選擇工作集,用于驗(yàn)證年齡字段。
?
圖2.205歲是無效的。
?
2.1.5.17指導(dǎo)規(guī)則編輯器
?
編輯規(guī)則變得更明確。編輯器是更小“盒子”,且用一個(gè)普通文本編寫更多規(guī)則。增加了"contains"關(guān)鍵字,現(xiàn)在在綁定變量給限制是更容易了。
?
2.1.5.17.1模式排序
?
指導(dǎo)編輯器在lhs和rhs部分支持模式重排序,以及位置插入,新的模式可以以任何順序被插入(并不總是在最后)。
?
圖2.21上下移動(dòng)元素。
?
圖2.22在任何位置插入元素。
?
2.1.5.18決策表(Guvnor)
?
增加了關(guān)鍵字"in"。
可以移動(dòng)列,并且新行的位置可以自由選擇。
?
2.1.6Eclipse
?
2.1.6.3在大綱視圖中分組規(guī)則
?
現(xiàn)在你可以為議程組使用排序或分組。
?
圖2.23分組議程組
圖2.24排序議程組
2.1.6.4支持在審計(jì)視圖中拖/放文件。
現(xiàn)在可以拖放日志文件到審計(jì)視圖中。
2.1.7已知的問題
2.1.7.3多線程模式
使用試驗(yàn)的多線程執(zhí)行模式存在一個(gè)已知的問題,如下面JIRA中描述的一樣
https://jira.jboss.org/browse/JBRULES-2125
?
2.2????? 在Drools 5.0.0中值得關(guān)注的新東西
?
2.2.1??? Drools API
?Drools現(xiàn)在有完善的api/實(shí)現(xiàn)分離物,不再面向規(guī)則。當(dāng)我們開始支持其他邏輯形式時(shí),如工作流和事件處理時(shí),這是一個(gè)重要的策略。最重要的改變是我們面向知識(shí),而不是面向規(guī)則。drools-api模塊提供接口和工廠,并且與以前相比,我們已竭力提供更好的javadocs,帶有一些代碼片段。drools-api還有助于清楚地顯示有意作為一個(gè)用戶的api是什么,只是一個(gè)引擎的api是什么,而Drools核心和Drools編譯器沒有充分明確這點(diǎn)。你將使用的最普通的接口有:
?
n?org.drools.builder.KnowledgeBuilder
n?org.drools.KnowledgeBase
n?org.drools.agent.KnowledgeAgent
n?org.drools.runtime.StatefulKnowledgeSession
n?org.drools.runtime.StatelessKnowledgeSession
?
工廠類,帶有靜態(tài)方法,提供上面接口的實(shí)例。一個(gè)可插式提供者方法被用來允許提供者實(shí)現(xiàn)在運(yùn)行時(shí)連接工廠。你將最常使用的工廠有:
?
n?org.drools.builder.KnowledgeBuilderFactory
n?org.drools.io.ResourceFactory
n?org.drools.KnowledgeBaseFactory
n?org.drools.agent.KnowledgeAgentFactory
?
例子2.20 加載一個(gè)規(guī)則資源的一個(gè)典型例子
?
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newUrlResource( url ), ResourceType.DRL );
if ( kbuilder.hasErrors() ) {
? System.err.println( builder.getErrors().toString() );
}????????
?
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( builder.getKnowledgePackages() );
?
StatefulKnowledgeSession ksession = knowledgeBase.newStatefulKnowledgeSession();
ksession.insert( new Fibonacci( 10 ) );
ksession.fireAllRules();
?
ksession.dispose();
?
一個(gè)典型的加載一個(gè)流程資源的例子。注意ResourceType使用相應(yīng)的資源類型被改變。
?
例子 2.21一個(gè)典型的加載一個(gè)流程資源的例子。注意ResourceType使用相應(yīng)的資源類型被改變。
?
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newUrlResource( url ),
??????????? ResourceType.DRF );
if ( kbuilder.hasErrors() ) {
? System.err.println( builder.getErrors().toString() );
}????????
?
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( builder.getKnowledgePackages() );
?
StatefulKnowledgeSession ksession = knowledgeBase.newStatefulKnowledgeSession();
ksession.startProcess( "Buy Order Process" );
?
ksession.dispose();
?
'kbuilder','kbase','ksession'是經(jīng)常使用的變量標(biāo)識(shí)符,用knowledge的k開頭。
?
例子 2.22 我們已統(tǒng)一了決策樹如何加載,現(xiàn)在不再需要利用電子表格編譯器預(yù)先生成一致的DRL。
?
DecisionTableConfiguration dtconf = KnowledgeBuilderFactory.newDecisionTableConfiguration();
dtconf.setInputType( DecisionTableInputType.XLS );
dtconf.setWorksheetName( "Tables_2" );
kbuilder.add( ResourceFactory.newUrlResource( "file://IntegrationExampleTest.xls" ),
??????????? ResourceType.DTABLE,
??????????? dtconf );
?
使用配置也可以配置一個(gè)KnowledgeBase,通過一個(gè)xml更改集,而不是編程方式。
?
例子2.23 一個(gè)簡單的更改集例子
?
<change-set?xmlns='http://drools.org/drools-5.0/change-set'
xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
xs:schemaLocation='http://drools.org/drools-5.0/change-set?change-set-5.0.xsd'?>
??<add>
??????<resource?source='classpath:org/domain/someRules.drl'?type='DRL'?/>
??????<resource?source='classpath:org/domain/aFlow.drf'?type='DRF'?/>
??</add>
</change-set>
?
例子 2.24 可以象其他資源類型一樣添加
?
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newUrlResource( url ),
??????????? ResourceType.ChangeSet );
?
KnowledgeAgent與?RuleAgent相比較,其他較大的變化是輪詢掃描現(xiàn)在是一個(gè)服務(wù)了。進(jìn)一步說,是在代理通知與資源監(jiān)視之間有一個(gè)抽象,允許使用其他輪詢機(jī)制。
?
例子 2.25 這些服務(wù)當(dāng)前不再默認(rèn)啟動(dòng),要啟動(dòng)它們要如下這樣:
?
ResourceFactory.getResourceChangeNotifierService().start();
ResourceFactory.getResourceChangeScannerService().start();
?
增加了兩個(gè)接口,ResourceChangeNotifier和ResourceChangeMonitor。KnowledgeAgent使用ResourceChangeNotifie實(shí)現(xiàn)訂購資源更改通知。通過添加ResourceChangeMonitor通知ResourceChangeNotifie資源改變了。我們現(xiàn)在只提供一個(gè)開箱既用的的監(jiān)視器, ResourceChangeScannerService,它輪詢資源的變化。然而,存在有api用于用戶添加自己的監(jiān)視器,所以可以使用一個(gè)如jms這樣的基于推的監(jiān)視器。
?
ResourceFactory.getResourceChangeNotifierService().addResourceChangeMonitor( myJmsMonitor);
?
2.2.2??? Drools Guvnor
?
n?新外觀的網(wǎng)頁工具
?圖2.25 新外觀
?
n?網(wǎng)頁基于決策表編輯器
圖2.26網(wǎng)頁基于決策表編輯器
?
n?集成的場景測試
?圖2.27 運(yùn)行所有場景
?
圖2.28 運(yùn)行單個(gè)場景
?
n?WebDAV文件基于接口庫
?
圖2.29? WebDAV
?
n?聲明式模擬類型(不使用pojos的類型)
圖2.30 ?聲明式模擬
?
它與"declare"語句一起工作——你現(xiàn)在可以在drl本身內(nèi)聲明類型。然后你可以裝配它們,不必使用pojo(如果你喜歡)。然后這些類型可用于規(guī)則庫中。
?
u?細(xì)粒度安全(鎖定訪問每包或每分類應(yīng)用程序)。只有分類權(quán)限的用戶具有有限的UI能力(針對(duì)企業(yè)用戶)
u?執(zhí)行服務(wù)器——執(zhí)行通過XML或JSON訪問規(guī)則。
u?分類規(guī)則允許你為一個(gè)分類設(shè)置“父規(guī)則”。出現(xiàn)在給定分類的任何規(guī)則會(huì)“繼承”指定的規(guī)則——例如,繼承條件/ LHS。分類的基本規(guī)則可以在包配置標(biāo)簽上設(shè)置。RHS不被繼承,只有LHS被繼承。
u?場景運(yùn)行器檢測無限循環(huán)。
u?現(xiàn)在可以設(shè)置在指南編輯器中的DSL句子,用于顯示作為一個(gè)下接菜單的枚舉、作為一個(gè)數(shù)據(jù)拾取器的數(shù)據(jù)、作為一個(gè)單選框的布爾值,并且使用正則表達(dá)式來校驗(yàn)用戶輸入(在Guvnor中的DSL小飾件)。
u?函數(shù)可以使用文本編輯器進(jìn)行編輯。
u?可以添加對(duì)象到全局集合。
u?翻譯為英語,西班牙語,漢語和日語。
2.2.3??Drools Expert
?
2.2.3.1??非對(duì)稱Rete算法實(shí)現(xiàn)
?
不再需要影子代理。影子代理保護(hù)引擎免受有關(guān)實(shí)事的信息變化的影響,如果發(fā)生在引擎控件的外部,它可能不會(huì)被修改或撤消。
?
2.2.3.2??包構(gòu)建器現(xiàn)在可以構(gòu)建多個(gè)命名空間
?
你不再需要對(duì)一個(gè)包命名空間構(gòu)建一個(gè)PackageBuilder?。只要保持為所有命名空間增加你的DRLs,并且getPackages()為每個(gè)使用的命名空間返加一個(gè)包數(shù)組。
?
例子 2.26 獲得多個(gè)包
?
Package[] packages = pkgBuilder.getPackages();
?
2.2.3.3??規(guī)則庫連接包構(gòu)建器
?
現(xiàn)在可以連接一個(gè)?RuleBase到一個(gè)?PackageBuilder,這意味著規(guī)則被構(gòu)建,并且同時(shí)被添加到規(guī)則庫。PackageBuilder使用現(xiàn)行的RuleBase的Package實(shí)例作為它的資源,取消了發(fā)生在現(xiàn)有方法中的Package創(chuàng)造和融合。
?
例子 2.27 連接規(guī)則庫(RuleBase)到包構(gòu)建器(PackageBuilder)
?
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
PackageBuilder pkgBuilder = new PackageBuilder( ruleBase, null );
?
2.2.3.4??有狀態(tài)會(huì)話的二進(jìn)制編碼
?
有狀態(tài)會(huì)話現(xiàn)在可以保存,并可在以后的日期中恢復(fù)。預(yù)加載數(shù)據(jù)會(huì)話現(xiàn)在可以被創(chuàng)建。對(duì)用戶對(duì)象的持久化可使用可插式策略,例如,hibernate或特征(identity)映射。
?
2.2.3.5??類型聲明
?
Drools現(xiàn)在支持一種新的基礎(chǔ)結(jié)構(gòu),稱為類型聲明。這個(gè)結(jié)構(gòu)達(dá)到兩個(gè)目的:能夠聲明實(shí)事元數(shù)據(jù),以及能夠?yàn)橐?guī)則引擎動(dòng)態(tài)地產(chǎn)生局部的新的事實(shí)類型。Guvnor模擬工具在底層使用了它。下面是該結(jié)構(gòu)的一個(gè)例子:
?
例子 2.28 聲明StockTick
?
declare StockTick
? @role( event )
? @timestamp( timestampAttr )
?
? companySymbol : String
? stockPrice : double
? timestampAttr : long
end
?
2.2.3.6??聲明實(shí)事元數(shù)據(jù)
?
要聲明和關(guān)聯(lián)事實(shí)的元數(shù)據(jù),只需要對(duì)你想聲明的每個(gè)元數(shù)據(jù)ID使用@符號(hào)。例子:
?
例子 2.29 聲明元數(shù)據(jù)
?
declare StockTick
? @role( event )
end
?
2.2.3.7??觸發(fā)Bean產(chǎn)生
?
要激活動(dòng)態(tài)bean產(chǎn)生,僅為你的類型聲明添加字段和類型。
?
例子 2.30 聲明Person
?
declare Person
? name : String
? age : int
end
?
2.2.3.8??DSL的改進(jìn)
?
一系列DSL的改進(jìn)被實(shí)現(xiàn),包括一個(gè)完善的新解析器,并且能夠?yàn)槠ヅ涞淖兞柯暶髌ヅ涞难诖a(mask)。例如,它可限定一個(gè)電話號(hào)碼字段為2位數(shù)的國家代碼+ 3位區(qū)號(hào)+ 8位數(shù)字電話號(hào)碼,所有連接以“ - ”(破折號(hào))連接,通過象這樣聲明DSL映射:電話號(hào)碼為{number:\d{2}-\d{3}-\d{8}},所有有效的Java正則表達(dá)式可以用于變量的掩碼中。
?
2.2.3.9??fireUntilHalt()
?
Drools現(xiàn)在支持fireUntilHalt()功能,它以一種被動(dòng)模式啟動(dòng)引擎,在那兒規(guī)則會(huì)被連續(xù)引發(fā),直到調(diào)用了halt()。這尤其對(duì)CEP(complex event processing)場景有用,CEP場景需要俗稱的“活動(dòng)查詢”。
?
2.2.3.10???規(guī)則庫分區(qū)和多線程傳播
?
Drools ReteOO算法現(xiàn)在支持一個(gè)選項(xiàng),用于以多線程模式啟動(dòng)規(guī)則庫,在那兒Drools ReteOO網(wǎng)絡(luò)被劃分為多個(gè)部分,然后規(guī)則被多個(gè)線程并發(fā)計(jì)算。對(duì)通常有幾個(gè)獨(dú)立規(guī)則并發(fā)運(yùn)行的CEP,它也有一個(gè)要求,接近實(shí)時(shí)性能/吞吐量的要求,并且一個(gè)計(jì)算不能干擾其他的計(jì)算。
?
2.2.3.11???XSD模式支持
?
Drools現(xiàn)在支持XSD模式。記住雖然XSD模式以用于Drools類加載器的本地POJO類生成。在包構(gòu)建器中存在有一個(gè)幫助類用于模式的產(chǎn)生。一旦數(shù)據(jù)模式被生成,你通常使用JAXB數(shù)據(jù)加載器插入數(shù)據(jù)。
?
2.2.3.12???數(shù)據(jù)加載器
?
Drools現(xiàn)在支持兩種數(shù)據(jù)加載器,Smooks和JAXB。Smooks是一個(gè)用于ETL的開源數(shù)據(jù)轉(zhuǎn)換工具,JAXB是一個(gè)標(biāo)準(zhǔn)的Sun數(shù)據(jù)映射工具。單元測試顯示Smooks和JAXB均可在這里找到。
?
2.2.3.13???類型安全配置
?
在Drools中,除了能夠通過配置文件配置選項(xiàng)外,也可用系統(tǒng)屬性配置,通過API的 setProperty()方法設(shè)置屬性,Drools-API現(xiàn)在支持類型安全配置。我們不希望為每個(gè)可能的配置方法增加特殊的方法,有兩個(gè)原因:它污染了API,并且每次都有一個(gè)新選項(xiàng)增加到Drools,API將不得不改變。而這種方式,我們遵循模塊化,類基于配置,在此處為每個(gè)可能的配置,一個(gè)新的選項(xiàng)類增加到了API,除了靈活之外,也維持了API的穩(wěn)定。所以,現(xiàn)在為了設(shè)置配置選項(xiàng),你只需要使用枚舉或者提供每個(gè)選項(xiàng)的工廠。例如,如果你希望為斷言行為"equality"?配置知識(shí)庫,并且自動(dòng)從模式匹配中刪除特征(identities),你只需要使用下面的枚舉:
?
例子2.31 配置
?
KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
config.setOption( AssertBehaviorOption.EQUALITY );
config.setOption( RemoveIdentitiesOption.YES );
?
對(duì)于選項(xiàng),我們不需要預(yù)定義約束,或者可以假設(shè)多個(gè)值,提供一個(gè)工廠方法。例如,配置alpha值為5,只使用get()工廠方法:
?
例子 2.32 配置alpha值
?
config.setOption( AlphaThresholdOption.get(5) );
正如你所見,為每個(gè)不同的可能配置,使用了相同的setOption()方法,然而它們?nèi)匀皇穷愋桶踩摹?/p>
?
2.2.3.14???新的累積函數(shù):collectSet和collectList
?
有時(shí)候,有必要收集來自實(shí)事屬性的值的集合或列表,而不是實(shí)事本身。在這種情況下,不可能使用collect CE。所以對(duì)這種情況,現(xiàn)在Drools有兩個(gè)新的累積函數(shù):collectSet用于收集值的集合(即,無重復(fù)的值),collectList用于收集值的列表(即,允許重復(fù)的值):
?
例子 2.33 新的累積函數(shù)
?
# collect the set of unique names in the working memory
$names : Set() from accumulate( Person( $n : name, $s : surname ),
??????????????????????? collectSet( $n + " " + $s ) )
?
# collect the list of alarm codes from the alarms in the working memory
$codes : List() from accumulate( Alarm( $c : code, $s : severity ),
???????????????????????? collectList( $c + $s ) )
?
2.2.3.15??用于類型聲明的新元數(shù)據(jù):@propertyChangeSupport
?
事實(shí)實(shí)現(xiàn)了象定義在Javabean(tm)規(guī)范中的屬性改變的支持。現(xiàn)在可以注釋,讓引擎注冊(cè)自身來偵聽事實(shí)屬性的變化。在Drools 4 API的insert()方法中使用的布爾參數(shù)已過時(shí),并且不存在于drools-aip模塊中了。
?
例子 2.34? @propertyChangeSupport
?
?declare Person
???????? @propertyChangeSupport
end
?
2.2.3.16??批處理器
?
批處理器允許一個(gè)知識(shí)會(huì)話使用命令腳本,此外,無論是StatelessKnowledgeSession?還是?StatefulKnowledgeSession實(shí)現(xiàn)都可以使用CommandFactory創(chuàng)建這個(gè)接口命令,且使用"execute"?方法執(zhí)行,如下所示:
?
例子 2.35 使用CommandFactory
?
ksession.execute( CommandFactory.newInsert( person ) );
?
盡管這樣,你通常會(huì)希望執(zhí)行一個(gè)批處理命令,通過組合命令?BatchExecution可以完成它。BatchExecutionResults現(xiàn)在用來處理結(jié)果,某些命令可以使用"out"標(biāo)識(shí)符,用它來添加結(jié)果到BatchExecutionResult。現(xiàn)在可以輕松地執(zhí)行查詢,并把結(jié)果添加到BatchExecutionResult。這個(gè)結(jié)果進(jìn)一步被限定到這個(gè)執(zhí)行調(diào)用,并且通過BatchExecutionResults返回。
?
例子 2.36 ?使用BatchExecutionResult
?
List<Command> cmds = new ArrayList<Command>();
cmds.add( CommandFactory.newSetGlobal( "list1", new ArrayList(), true ) );
cmds.add( CommandFactory.newInsert( new Person( "jon", 102 ), "person" ) );
cmds.add( CommandFactory.newQuery( "Get People" "getPeople" );
?
BatchExecutionResults results = ksession.execute( CommandFactory.newBatchExecution( cmds ) );
results.getValue( "list1" ); // returns the ArrayList
results.getValue( "person" ); // returns the inserted fact Person
results.getValue( "Get People" );// returns the query as a QueryResults instance.
End
?
CommandFactory詳細(xì)描述支持的命令,它們所有都可以使用XStream和BatchExecutionHelper進(jìn)行編碼。可以使用管道組合它們來自動(dòng)化會(huì)話腳本。
?
例子 2.37 使用PipelineFactory
?
Action executeResultHandler = PipelineFactory.newExecuteResultHandler();
Action assignResult = PipelineFactory.newAssignObjectAsResult();
assignResult.setReceiver( executeResultHandler );
Transformer outTransformer = PipelineFactory.newXStreamToXmlTransformer( BatchExecutionHelper.newXStreamMarshaller() );
outTransformer.setReceiver( assignResult );
KnowledgeRuntimeCommand batchExecution = PipelineFactory.newBatchExecutor();
batchExecution.setReceiver( outTransformer );
Transformer inTransformer = PipelineFactory.newXStreamFromXmlTransformer( BatchExecutionHelper.newXStreamMarshaller() );
inTransformer.setReceiver( batchExecution );
Pipeline pipeline = PipelineFactory.newStatelessKnowledgeSessionPipeline( ksession );
pipeline.setReceiver( inTransformer );
?
對(duì)一個(gè)規(guī)則集使用上面所述的,會(huì)更新一個(gè)Cheese事實(shí)的價(jià)格,下面給定的xml會(huì)插入一個(gè)使用了輸出標(biāo)識(shí)符(out-identifier)的Cheese實(shí)例。
?
例子 2.38 更新Cheese實(shí)事
?
<batch-execution>
<insert?out-identifier='outStilton'>
??<org.drools.Cheese>
????<type>stilton</type>
????<price>25</price>
????<oldPrice>0</oldPrice>
??</org.drools.Cheese>
</insert>
</batch-execution>
?
然后我們會(huì)得到BatchExecutionResults:
?
例子 2.39 更新Cheese實(shí)事
<batch-execution-results>
?<result?identifier='outStilton'>
???<org.drools.Cheese>
?????<type>stilton</type>
?????<oldPrice>0</oldPrice>???????
?????<price>30</price>
???</org.drools.Cheese>
?</result>
</batch-execution-results>
?
2.2.3.17??編碼
?
MarshallerFactory被用來編碼和解碼StatefulKnowledgeSessions。最簡單的,它可以象下面這樣使用:
?
例子 2.40 使用MarshallerFactory
?
// ksession is the StatefulKnowledgeSession
// kbase is the KnowledgeBase
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Marshaller marshaller = MarshallerFactory.newMarshaller( kbase );
marshaller.marshall( baos, ksession );
baos.close();
?
然而,在處理引用的用戶數(shù)據(jù)時(shí),你需要更有彈性地使用編碼。要達(dá)成它,我們有一個(gè)ObjectMarshallingStrategy接口。我們提供了兩個(gè)實(shí)現(xiàn),但是用戶可以自己實(shí)現(xiàn)它。提供的兩個(gè)是IdentityMarshallingStrategy和SerializeMarshallingStrategy。默認(rèn)為SerializeMarshallingStrategy,如上例所示,它只在一個(gè)用戶實(shí)例上調(diào)用Serializable或Externalizable方法。而IdentityMarshallingStrategy為每個(gè)用戶對(duì)象創(chuàng)建了一個(gè)整數(shù)id,并存儲(chǔ)它們?cè)谝粋€(gè)映射中,該id被寫入到該流中。在解碼時(shí),它只簡單地查看IdentityMarshallingStrategy映射,取回該實(shí)例。這意味著,如果你使用IdentityMarshallingStrategy,它對(duì)編碼實(shí)例的生命周期是有狀態(tài)的,并且會(huì)創(chuàng)建ids,保持它企圖編碼的所有對(duì)象的引用。
?
例子 2.41 使用IdentityMarshallingStrategy編碼
?
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Marshaller marshaller = MarshallerFactory.newMarshaller( kbase, new ObjectMarshallingStrategy[] { MarshallerFactory.newIdentityMarshallingStrategy() } );
marshaller.marshall( baos, ksession );
baos.close();
?
為增加彈性,我們不能想當(dāng)然地認(rèn)為單策略更合適,所以我們?cè)黾恿艘粋€(gè)ObjectMarshallingStrategyAcceptor?接口,每個(gè)ObjectMarshallingStrategy都有。編碼器有一個(gè)策略鏈,并且當(dāng)它企圖讀或?qū)懸粋€(gè)用戶對(duì)象時(shí),它遍歷策略,詢問它們是否承擔(dān)負(fù)責(zé)編碼用戶對(duì)象。提供了一個(gè)實(shí)現(xiàn)為ClassFilterAcceptor。它允許使用字符和通匹符匹配類名。默認(rèn)為"*.*",所以在上面使用的IdentityMarshallingStrategy,它有一個(gè)默認(rèn)的"*.*"接收器。然而,比方說,我們希望序列化所有類,一個(gè)給定的包除外,這種情況,我們會(huì)使用身份查詢,如下所示:
?
例子 2.42 ?使用身份查詢
?
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectMarshallingStrategyAcceptor identityAceceptor = MarshallerFactory.newClassFilterAcceptor( new String[] { "org.domain.pkg1.*" } );
ObjectMarshallingStrategy identityStratetgy = MarshallerFactory.newIdentityMarshallingStrategy( identityAceceptor );
Marshaller marshaller = MarshallerFactory.newMarshaller( kbase, new ObjectMarshallingStrategy[] { identityStratetgy, MarshallerFactory.newSerializeMarshallingStrategy() } );
marshaller.marshall( baos, ksession );
baos.close();
?
2.2.3.18??知識(shí)代理
?
KnowlegeAgent由?KnowlegeAgentFactory創(chuàng)建。KnowlegeAgent提供自動(dòng)加載、緩存和重新加載資源,并且根據(jù)一個(gè)屬性文件配置它。當(dāng)KnowlegeBase使用的資源更改時(shí),KnowlegeAgent可以更新或重構(gòu)KnowlegeBase。通過給定工廠的配置確定KnowlegeAgent的策略,但通常使用基于標(biāo)準(zhǔn)輪詢的拉策略。我們希望增加基于推的更新,并在將來的版本中重構(gòu)它。下面的例子,構(gòu)建了一個(gè)代理,它根據(jù)在路徑字符串中指定的文件構(gòu)建了一個(gè)新的KnowledgeBase。它會(huì)每30秒拉這些文件,而不是更新存在的一個(gè),因?yàn)?"newInstance" 設(shè)置為了"true"?(然而,目前只支持"true"?值,并且很難編碼到引擎中)。
?
例子 2.43 構(gòu)建一個(gè)代理
?
// Set the interval on the ResourceChangeScannerService if you are to use it and default of 60s is not desirable. ResourceChangeScannerConfiguration sconf = ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfiguration(); sconf.setProperty( "drools.resource.scanner.interval", ????????????????? "30" ); // set the disk scanning interval to 30s, default is 60s ResourceFactory.getResourceChangeScannerService().configure( sconf ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration(); aconf.setProperty( "drools.agent.scanDirectories", ????????????????? "true" ); // we want to scan directories, not just files, turning this on turns on file scanning aconf.setProperty( "drools.agent.newInstance", ????????????????? "true" ); // resource changes results in a new instance of the KnowledgeBase being built, ??????????????????????????? // this cannot currently be set to false for incremental building ?? ? KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent( "test agent", // the name of the agent ??????????????????????????????????????????????????????????????? kbase, // the KnowledgeBase to use, the Agent will also monitor any exist knowledge definitions ??????????????????????????????????????????????????????????????? aconf ); kagent.applyChangeSet( ResourceFactory.newUrlResource( url ) ); // resource to the change-set xml for the resources to add?
KnowledgeAgents可以使用一個(gè)空的 KnowledgeBase或植入的一個(gè)。如果提供了一個(gè)植入的KnowledgeBase,KnowledgeAgent會(huì)遍歷KnowledgeBase,并訂閱它發(fā)現(xiàn)的資源。雖然KnowledgeBuilder可以構(gòu)建在一個(gè)目錄中發(fā)現(xiàn)的所有資源,但信息會(huì)被KnowledgeBuilder丟棄,因些那些目錄不會(huì)繼續(xù)被掃描。只有作為applyChangeSet(Resource)方法的一部分指定的目錄才會(huì)被監(jiān)控。
總結(jié)
以上是生活随笔為你收集整理的Drools 5.1.1(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Drools与Spring集成 登录测试
- 下一篇: Oracle查询慢的原因总结