Drools 6.0 Hello World
来源:互联网 发布:sql rownum 编辑:程序博客网 时间:2024/06/07 04:41
0x00 开始
Drools是JBoss旗下的一款开源规则引擎。
规则引擎可以实现业务规则和代码的分离,使得非技术人员也可以配置业务规则,使业务规则有更强的可维护性。而Drools是开源的规则引擎中使用最广泛的。
目前Drools的最高版本是7.0.0beta,网上大多数例子都是以Drools 5.x为例,而中文的Drools 6.x 例子较少,在本文中已Drools 6.4.0.Final为例,只使用Drools 6.x的新API。
官方文档地址:
https://docs.jboss.org/drools/release/6.4.0.Final/drools-docs/html_single/
Drools 6.0对5.x的主要改进有:
1. Kie API
整合了jBPM
、UberFire
等等一票项目,Kie
的意思是Knowledge is everything
。
2. 利用maven repo管理规则,分离系统和规则代码,根据maven版本更新规则。
3. PHREAK
算法,官方文档认为其改善了多线程下的性能
4. 支持定时器表达式
0x01 例子
由于Drools 6.0 和maven高度耦合,所以建议项目都使用maven管理。
规则项目
pom.xml
<groupId>org.drools.test</groupId> <artifactId>artifact-rule</artifactId> <version>1.0</version>
Drools的规则预发并没有什么变化,这里只演示最简单的规则
放在src/main/resources/pkg/rule.drl
import drools.Bean;rule "Len0"when m : Bean( value == 0 )then System.out.println("Hello World 0");end# ......rule "Len999"when m : Bean( value == 999 )then System.out.println("Hello World 999");end
定义KieModulesrc/main/resources/META-INF/kmodule.xml
,注意rule、pkg、first,这必须和其他配置匹配。
<?xml version="1.0" encoding="UTF-8"?><kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <kbase name="rule" packages="pkg"> <ksession name="first" /> </kbase></kmodule>
主项目
maven依赖:
<!-- 不需要再关心每个Drools组件的版本了 --><dependencyManagement> <dependencies> <dependency> <groupId>org.drools</groupId> <artifactId>drools-bom</artifactId> <type>pom</type> <version>6.4.0.Final</version> <scope>import</scope> </dependency> </dependencies></dependencyManagement><dependencies> <dependency> <groupId>org.kie</groupId> <artifactId>kie-api</artifactId> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <scope>runtime</scope> </dependency> <!-- 引入规则项目 --> <dependency> <groupId>org.drools.test</groupId> <artifactId>artifact-rule</artifactId> <version>1.0</version> </dependency></dependencies>
Bean文件:src/main/java/drools/Bean.java
package drools;public class Bean { private Integer value; // 唯一的属性 public Integer getValue() { return value; } public void setValue(Integer value) { this.value = value; }}
测试文件:
KieServices ks = KieServices.Factory.get();KieContainer kContainer = ks.getKieClasspathContainer();// 从默认的kmodule.xml路径读取KieModule配置,然后根据kmodule.xml中的定义查找drl文件KieSession kSession = kContainer.newKieSession("first");for (int i = 0; i < 100; ++i) { Bean bean = new Bean(); bean.setValue(i); kSession.insert(bean); kSession.fireAllRules();}
0x02 无状态Session
Drools 6.x 文档中将PHREAK
算法描述为一个惰性规则匹配算法,当有多个线程并发请求Drools执行规则时,只会有一个线程会执行,而其他线程在kSession.fireAllRules();
会直接返回,而不做任何执行(该方法返回执行的Fact数目,所以此时返回0)。
所以如果需要一个同步的规则匹配并执行,则需要使用无状态的Session。
修改src/main/resources/META-INF/kmodule.xml
,type="stateless"
<?xml version="1.0" encoding="UTF-8"?><kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <kbase name="rule" packages="pkg"> <ksession type="stateless" name="first" /> </kbase></kmodule>
KieServices ks = KieServices.Factory.get();KieContainer kContainer = ks.getKieClasspathContainer();StatelessKieSession kSession = kContainer.newStatelessKieSession("first");for (int i = 0; i < 100; ++i) { Bean bean = new Bean(); bean.setValue(i); kSession.execute(bean);}
查看源代码可知,其底层是对有状态的Session进行了包装,只是会做一次复制,这样当前线程就是这个Session唯一的执行线程了,可以保证同步调用。
0x03 动态规则加载
规则引擎最大的好处是规则和系统分离,这使得可以单独更新规则。6.x与maven耦合,可以直接通过maven坐标更新规则。
KieServices ks = KieServices.Factory.get();KieContainer kContainer = ks.newKieContainer( ks.newReleaseId("org.drools.test", "artifact-rule", "1.0") );StatelessKieSession kSession = kContainer.newStatelessKieSession();
在更多的时候,我们希望自己进行规则的生成和加载,最直接的想法是给定一个规则字符串,直接更新。
(此时不需要kmodule.xml
和rule.drl
)
KieServices ks = KieServices.Factory.get();KieFileSystem kfs = ks.newKieFileSystem();kfs.write("src/main/resources/simple.drl", ruleString); // ruleString是规则字符串KieBuilder kb = ks.newKieBuilder(kfs);kb.buildAll();// 以下几行代码可以看到载入错误Results results = kb.getResults();if (results.hasMessages(org.kie.api.builder.Message.Level.ERROR)) { System.out.println(results.getMessages()); throw new IllegalStateException("### errors ###");}KieContainer kContainer = ks.newKieContainer(kb.getKieModule().getReleaseId());StatelessKieSession kSession = kContainer.newStatelessKieSession();
Drools底层仍然是动态生成一个如同maven打包的jar,然后再将其载入。
Drools会将规则动态地编译成类以构建整个引擎,所以动态加载规则时候不可能避免地会占用一部分持久代,那么会OOM吗?
在我的机器上,我用以下JVM参数,启用了类卸载
-Xmx1024m-XX:PermSize=64m-XX:MaxPermSize=64m-XX:+CMSClassUnloadingEnabled
规则是前面提到的rule.drl文件,一千条简单等于规则,结果:
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
说明是会OOM的。但是如果将持久代区域提高到128M,在我的机器上则不会发生OOM。
但动态加载后几乎每次都触发了FullGC,此时GC+加载时间会从几十秒到几百秒(是的,单位是秒)。将持久代大小提高后,可以减少触发FullGC的频率,但每次触发FullGC之后的加载还是耗时很久。(这里测试的规则较简单占用内存相对较少,真实的规则文件会导致不同的加载时间和内存占用)
0x04 定时器
Drools 6.x的一个新功能是直接支持在表达式中编写定时器,Drools规则支持的定时方法有很多,这里只演示基于cron表达式的规则。
规则文件rule.drl
,每秒打印一次时间
import java.util.Date;rule "Timer" timer (cron:0/1 * * * * ?)when eval(true)then System.out.println(new Date());end
调用代码
KieServices ks = KieServices.Factory.get();// 启用定时器规则KieSessionConfiguration ksconf = ks.newKieSessionConfiguration();ksconf.setOption( TimedRuleExectionOption.YES );KieContainer kContainer = ks.getKieClasspathContainer();KieSession kSession = kContainer.newKieSession("first", ksconf);kSession.fireAllRules();
0x05 总结
Drools 6.x 并没有什么有价值的改进,6.x仍可以使用5.x的API。
另外这样一个规则稍微一多就吃内存的规则引擎,到底有多大意义?
- Drools 6.0 Hello World
- Drools Hello world
- drools 6学习2--伟大的hello world
- Hello World!【Hello World】
- Hello, world!
- Hello World!
- Hello world!
- Hello World!
- Hello World!
- hello world!
- Hello World !
- Hello,World!
- Hello World!
- Hello world!
- Hello World!
- Hello World
- Hello World
- Hello world
- iOS开发中的Web Service
- <a>标签跳转和执行js函数,href和onclick属性
- 合金
- 详解资源文件Drawable下面的shape标签
- Sum of Two Integers
- Drools 6.0 Hello World
- iOS-获取图像尺寸
- JAVA7、JAVA8的堆内存有啥变化
- Java程序员修炼之道 之 Logging(3/3) - 怎么分析Log
- Linux的进程/线程通信方式总结
- sql查询条件where 1=1,1=2
- Jackson反序列化的实现方法
- UNITY的drawcall计算
- 中介者模式