Osmanthus 是什么?
Osmanthus 是一款JAVA实现的轻量级开源的规则引擎框架,它是基于MVEL组件实现的,相比drools使用更容易且更轻量级;支持复杂的规则集,例如:决策树,评分卡等;配置规则可以像配置流程一样;支持规则的并行的执行。
源码地址:https://github.com/wangwei86609/osmanthus
另注:该框架还在持续更新中,欢迎广大编程爱好者积极参与该框架的开发和维护。
Osmanthus 目标
取代drools,实现一款更加强大的规则引擎框架。
核心特征
轻量级JAVA实现,且宜用
基于XML文件规则配置,规则更容易维护,且后期升级空间会更大
支持MVEL表达式语言,使规则中Condition 和 Action配置更方便,不需要硬编码
对规则做了很好的抽象,实现复杂规则例如:决策树和决策树林,评分卡等等
可以并行执行规则
Osmanthus使用
让我们实现如下流程规则集,该规则集相当复杂,包含了:决策树,评分看,并行规则,并行规则合并:
对于以上如此复杂的规则,在Osmanthus中是很容易实现的,定义如下xml的规则的配置文件,详见源码
<?xml version="1.0" encoding="UTF-8"?> <flow id="flow1"> <start id="start" toNodeId="feerule"/> <ruleset id="feerule" fromNodeId="start" toNodeId="split1" external="true"/> <split id="split1" fromNodeId="feerule"> <constraint toNodeId="card"> <condition><![CDATA[fee>1]]></condition> </constraint> <constraint toNodeId="end"> <condition><![CDATA[fee<=1]]></condition> </constraint> </split> <ruleset id="card" fromNodeId="split1" toNodeId="mlines" external="true"/> <parallel id="mlines" fromNodeId="card"> <line toNodeId="p1"/> <line toNodeId="p2"/> </parallel> <rule id="p1" fromNodeId="mlines" toNodeId="end"> <condition><![CDATA[1==1]]></condition> <action><![CDATA[rule1="p1"]]></action> </rule> <rule id="p2" fromNodeId="mlines" toNodeId="mlines2"> <condition><![CDATA[2==2]]></condition> <action><![CDATA[rule2="p2"]]></action> </rule> <parallel id="mlines2" fromNodeId="p2"> <line toNodeId="p3"/> <line toNodeId="p4"/> </parallel> <rule id="p3" fromNodeId="mlines2" toNodeId="merge"> <condition><![CDATA[1==1]]></condition> <action><![CDATA[rule3="p3"]]></action> </rule> <rule id="p4" fromNodeId="mlines2" toNodeId="merge"> <condition><![CDATA[2==2]]></condition> <action><![CDATA[rule4="p4"]]></action> </rule> <merge id="merge" fromNodeId="p3,p4" lineCnt="2" toNodeId="p5"/> <rule id="p5" fromNodeId="merge" toNodeId="end"> <condition><![CDATA[2==2]]></condition> <action><![CDATA[rule5="p5"]]></action> </rule> <end id="end"/> </flow>
执行规则代码:
package org.wei86609.osmanthus; import junit.framework.TestCase; import org.wei86609.osmanthus.event.Event; public class OsmanthusExecutorTest extends TestCase { public void testExecute() { Event event=new Event(); event.setEventId("flow1"); event.add("salary", 5000); event.add("weight", 500); event.add("isBlackName", true); event.add("fee", 500); event.add("name", "test"); event.add("reg", "12312"); try { OsmanthusExecutor executor= new OsmanthusExecutor(); executor.newEvent(event, null); Thread.sleep(5000); } catch (Exception e) { e.printStackTrace(); } } }
输出结果:
2017-07-02 23:12:47,644-DEBUG [pool-1-thread-1]->(FlowEngine.java:37) Osmanthus start to execute the event[Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=500, isBlackName=true, weight=500, reg=12312, name=test, salary=5000}]] 2017-07-02 23:12:47,896-DEBUG [pool-1-thread-1]->(FlowEngine.java:41) Node is blank, will get the first node [start] of flow to execute. 2017-07-02 23:12:47,896-DEBUG [pool-1-thread-1]->(EmptyNodeExecutor.java:13) The empty node[start] of the event{Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=500, isBlackName=true, weight=500, reg=12312, name=test, salary=5000}]} executed. 2017-07-02 23:12:47,899-DEBUG [pool-1-thread-1]->(GeneralRuleSetExecutor.java:33) The ruleset[feerule] of the event{Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=500, isBlackName=true, weight=500, reg=12312, name=test, salary=5000}]} has [8] rules 2017-07-02 23:12:47,976-DEBUG [pool-1-thread-1]->(RuleExecutor.java:22) The node[step2] of the event {flow1} condition=[salary>3500 && salary<=5000] is true and action=[fee=(salary-3500)*0.03] 2017-07-02 23:12:47,977-DEBUG [pool-1-thread-1]->(GeneralRuleSetExecutor.java:64) The node[step2] of the event {Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=500, reg=12312, name=test, salary=5000}]} is exclusive, remain nodes will not be executed. 2017-07-02 23:12:47,978-DEBUG [pool-1-thread-1]->(SplitRuleExecutor.java:18) Split[split1] of the event {Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=500, reg=12312, name=test, salary=5000}]} has [2] Constraints 2017-07-02 23:12:47,978-DEBUG [pool-1-thread-1]->(SplitRuleExecutor.java:21) Split[split1] of the event {Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=500, reg=12312, name=test, salary=5000}]} Constraint's condition [fee>1] result is true, will link to Node[card]. 2017-07-02 23:12:47,978-DEBUG [pool-1-thread-1]->(GeneralRuleSetExecutor.java:33) The ruleset[card] of the event{Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=500, reg=12312, name=test, salary=5000}]} has [4] rules 2017-07-02 23:12:47,979-DEBUG [pool-1-thread-1]->(RuleExecutor.java:22) The node[gc2] of the event {flow1} condition=[isBlackName] is true and action=[weight=weight-200] 2017-07-02 23:12:47,980-DEBUG [pool-1-thread-1]->(RuleExecutor.java:22) The node[gc3] of the event {flow1} condition=[name=='test'] is true and action=[weight=weight-500] 2017-07-02 23:12:47,982-DEBUG [pool-1-thread-1]->(RuleExecutor.java:22) The node[gc4] of the event {flow1} condition=[reg ~= "[1-9][0-9]{4,}"] is true and action=[weight=weight-600] 2017-07-02 23:12:47,983-DEBUG [pool-1-thread-1]->(ParallelRuleExecutor.java:21) Parallel[mlines] of the event {flow1} has [2] thread lines 2017-07-02 23:12:47,984-DEBUG [pool-1-thread-1]->(FlowEngine.java:44) Osmanthus execute the event {Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=-800, reg=12312, name=test, salary=5000}]} end 2017-07-02 23:12:47,984-DEBUG [pool-1-thread-2]->(FlowEngine.java:37) Osmanthus start to execute the event[Event [eventId=flow1, threadId=pool-1-thread-2, model=FIRST, parameters={isBlackName=true, fee=45.0, weight=-800, reg=12312, name=test, salary=5000}]] 2017-07-02 23:12:47,985-DEBUG [pool-1-thread-3]->(FlowEngine.java:37) Osmanthus start to execute the event[Event [eventId=flow1, threadId=pool-1-thread-3, model=FIRST, parameters={isBlackName=true, fee=45.0, weight=-800, reg=12312, name=test, salary=5000}]] 2017-07-02 23:12:48,032-DEBUG [pool-1-thread-2]->(RuleExecutor.java:22) The node[p1] of the event {flow1} condition=[1==1] is true and action=[rule1="p1"] 2017-07-02 23:12:48,033-DEBUG [pool-1-thread-2]->(EmptyNodeExecutor.java:13) The empty node[end] of the event{Event [eventId=flow1, threadId=pool-1-thread-2, model=FIRST, parameters={isBlackName=true, fee=45.0, weight=-800, reg=12312, name=test, rule1=p1, salary=5000}]} executed. 2017-07-02 23:12:48,033-DEBUG [pool-1-thread-2]->(FlowEngine.java:44) Osmanthus execute the event {Event [eventId=flow1, threadId=pool-1-thread-2, model=FIRST, parameters={isBlackName=true, fee=45.0, weight=-800, reg=12312, name=test, rule1=p1, salary=5000}]} end 2017-07-02 23:12:48,070-DEBUG [pool-1-thread-3]->(RuleExecutor.java:22) The node[p2] of the event {flow1} condition=[2==2] is true and action=[rule2="p2"] 2017-07-02 23:12:48,070-DEBUG [pool-1-thread-3]->(ParallelRuleExecutor.java:21) Parallel[mlines2] of the event {flow1} has [2] thread lines 2017-07-02 23:12:48,070-DEBUG [pool-1-thread-2]->(FlowEngine.java:37) Osmanthus start to execute the event[Event [eventId=flow1, threadId=pool-1-thread-2, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=-800, reg=12312, name=test, salary=5000, rule2=p2}]] 2017-07-02 23:12:48,070-DEBUG [pool-1-thread-3]->(FlowEngine.java:44) Osmanthus execute the event {Event [eventId=flow1, threadId=pool-1-thread-3, model=FIRST, parameters={isBlackName=true, fee=45.0, weight=-800, reg=12312, name=test, rule2=p2, salary=5000}]} end 2017-07-02 23:12:48,070-DEBUG [pool-1-thread-1]->(FlowEngine.java:37) Osmanthus start to execute the event[Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=-800, reg=12312, name=test, salary=5000, rule2=p2}]] 2017-07-02 23:12:48,115-DEBUG [pool-1-thread-2]->(RuleExecutor.java:22) The node[p3] of the event {flow1} condition=[1==1] is true and action=[rule3="p3"] 2017-07-02 23:12:48,116-DEBUG [pool-1-thread-2]->(MergeNodeExecutor.java:16) Merge[merge] of the event {Event [eventId=flow1, threadId=pool-1-thread-2, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=-800, reg=12312, name=test, rule3=p3, salary=5000, rule2=p2}]} has [0] threads need to merge 2017-07-02 23:12:48,116-DEBUG [pool-1-thread-1]->(RuleExecutor.java:22) The node[p4] of the event {flow1} condition=[2==2] is true and action=[rule4="p4"] 2017-07-02 23:12:48,117-DEBUG [pool-1-thread-1]->(MergeNodeExecutor.java:16) Merge[merge] of the event {Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=-800, rule4=p4, reg=12312, name=test, salary=5000, rule2=p2}]} has [0] threads need to merge 2017-07-02 23:12:48,117-DEBUG [pool-1-thread-2]->(MergeNodeExecutor.java:18) Merge[merge] of the event {Event [eventId=flow1, threadId=pool-1-thread-2, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=-800, reg=12312, name=test, rule3=p3, salary=5000, rule2=p2}]} will merge all threads 2017-07-02 23:12:48,117-DEBUG [pool-1-thread-1]->(MergeNodeExecutor.java:18) Merge[merge] of the event {Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=-800, rule4=p4, reg=12312, name=test, salary=5000, rule2=p2}]} will merge all threads 2017-07-02 23:12:48,117-DEBUG [pool-1-thread-2]->(RuleExecutor.java:22) The node[p5] of the event {flow1} condition=[2==2] is true and action=[rule5="p5"] 2017-07-02 23:12:48,117-DEBUG [pool-1-thread-1]->(RuleExecutor.java:22) The node[p5] of the event {flow1} condition=[2==2] is true and action=[rule5="p5"] 2017-07-02 23:12:48,118-DEBUG [pool-1-thread-2]->(EmptyNodeExecutor.java:13) The empty node[end] of the event{Event [eventId=flow1, threadId=pool-1-thread-2, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=-800, rule5=p5, reg=12312, name=test, rule3=p3, salary=5000, rule2=p2}]} executed. 2017-07-02 23:12:48,118-DEBUG [pool-1-thread-1]->(EmptyNodeExecutor.java:13) The empty node[end] of the event{Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=-800, rule5=p5, rule4=p4, reg=12312, name=test, salary=5000, rule2=p2}]} executed. 2017-07-02 23:12:48,118-DEBUG [pool-1-thread-2]->(FlowEngine.java:44) Osmanthus execute the event {Event [eventId=flow1, threadId=pool-1-thread-2, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=-800, rule5=p5, reg=12312, name=test, rule3=p3, salary=5000, rule2=p2}]} end 2017-07-02 23:12:48,118-DEBUG [pool-1-thread-1]->(FlowEngine.java:44) Osmanthus execute the event {Event [eventId=flow1, threadId=pool-1-thread-1, model=FIRST, parameters={fee=45.0, isBlackName=true, weight=-800, rule5=p5, rule4=p4, reg=12312, name=test, salary=5000, rule2=p2}]} end
相关推荐
英敏特月度热点成分:桂花 Ingredient Newsletter - 【BPC vol2】- Osmanthus - final.pdf
osmanthus(桂花)这个名字的由来:公司大神的框架Pomelo(柚子), 于是也想弄个水果当名字,不想水果太火热了,npm上基本都注册完了。那就用花吧,刚好园区里的桂花开了,就它了。 osmanthus?这是个什么东东? ...
【网络文档】:《美食译苑——中文菜单英文译法》是北京市人民政府外事办公室与北京市民讲外语活动组委会办公室联合发布的,旨在为中餐菜品提供规范化英文译名,以适应日益增长的国际交流需求。这本书收录了八大菜系...
“已收购业务”指的是公司在2019年进行的一项重要战略举措,即收购了Osmanthus Vale Holdings Limited及其附属公司的网络游戏业务,这可能意味着公司在业务扩展或资源整合方面取得进展。 报告还提到了一些关键的...
1. 拉丁文命名在植物学中至关重要,它为全球植物提供了统一的命名规则,避免了因不同地区语言差异导致的混乱。例如,"tomentosa"通常表示植物表面有绒毛或被毛,如Populus tomentosa(毛白杨);"mollissima"意为...
桂花OfMYB1和OfMYB2基因的克隆与表达特性分析,丁海琴,曾祥玲,桂花(Osmanthus fragrance)属于木犀科木犀属植物,具有非常重要的园林应用价值和经济价值。研究利用转录组测序获得的表达序列信息,�
9. **园林应用**:特定的树木因适应性强、景观效果好而常用于城市绿化,如垂柳(Salix babylonica)适合种植于水边,而桂花(Osmanthus fragrans)常用于庭院绿化,因为其芳香的花朵。 10. **行道树的作用**:行道...
为了探讨不同林地对空气微生物的影响,以浙江林学院东湖校区为样地,采用自然沉降法,于春季对樟树 Cin-namomum camphora,桂花 Osmanthus fragrans,杨梅 Myrica rubra和黄皮刚竹 Phyllostachys viridis林的空气微生物...
桂花,学名Osmanthus fragrans,是中国传统的十大名花之一,以其浓郁的香气和独特的形态深受人们喜爱。在描述中,作者将桂花比作满天的星星,形象地展示了桂花密集且明亮的特点。桂花在秋季盛开,恰逢八月,与中秋...
对17个桂花Osmanthus fragrans品种的小花花冠径、着花繁密程度、花色、花香程度、花枝形态等特点进行调查研究。选择生长正常的健康植株采样,其中繁殖器官样本数为10,营养器官样本数为20。根据切花分级标准与桂花的...
3. 桂花 (Osmanthus fragrans) 桂花是木樨科木樨属的常绿灌木或小乔木,主要生长在温带地区。叶子对生,形状为椭圆或长椭圆形,叶面光滑,边缘有锯齿。桂花的花簇生,花冠分裂,花瓣4片,颜色有乳白、黄、橙红等,...
桂花(Osmanthus fragrans)属于木犀科,它喜欢阳光充足、温暖通风的环境,不耐寒冷,偏好湿润、排水良好的酸性至微碱性土壤。桂花四季常青,花期在中秋,香气浓郁,是人们钟爱的园林花卉。 乐昌含笑(Michelia ...
桂花,学名Osmanthus fragrans,是一种常见的观赏花卉,因其秋季盛开的香气四溢的花朵而备受喜爱。以下是桂花盆景的种植与养护方法: 1. **换盆管理**:桂花盆景在不同生长阶段需要更换不同口径的花盆。一般在植株...
桂花树,学名Osmanthus fragrans,是木犀科木犀属的一种常绿灌木或小乔木,因其秋季盛开的芬芳花朵而备受喜爱。这种植物的高度通常在1.5到8米之间,其树冠形状多样,可呈圆头形、半圆形或椭圆形。树叶对生,质地坚韧...
- 桂花:Osmanthus fragrans (Thunb.) Lour. - 广玉兰:Magnolia grandiflora L - 金钱松:Pseudolarix kaempferi (Lindl.) Gord - 银杏:Ginkgo biloba L - 山茶:Camellia japonica L - 悬铃木:Platanus ...
Alice hope to reunite the hearts leap in space, the Moon Palace osmanthus trees to Syria under an eternal theme." 这段话富有诗意,通过秋风、相思树等元素,表达了对团圆的期盼。 8. "The moon cake is ...
1. **桂花**(Osmanthus fragrans):桂花是木犀科的常绿灌木或小乔木,以其芬芳的香气而著名。它有多个变种,如金桂、银桂、丹桂和四季桂,花色各异,花期主要在秋季。 2. **月季**(Rosa chinensis):被誉为“花...