本篇内容主要讲解“Drools规则引擎的作用是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Drools规则引擎的作用是什么”吧!
规则约束和判定都是通过DRL(Drools Rule Language)文件完成,一个文件可包含一条或者多条规则。典型描述规则如下格式:
Package:包是Drools中相关资产的文件夹,如数据对象、DRL文件、决策表和其他资产类型。主要充当每个规则组的惟一名称空间,必须位于文件的顶部,和Java中的编写的相关的类的路径无关,保证唯一即可。
Import:导入需要使用的类的包或类
Function:函数定义,如:
function String hello(String applicantName) { return "Hello " + applicantName + "!"; }
Query: 可以根据规则名称在引擎中查询符合条件的结果对象;
Declare:可以声明一个类,与使用java 定义的类具有同样的功能。如:
declare Cheese name : String price : int end
Global:定义全局变量;
Rule: 定义此规则的唯一标识;
When: 条件判定,如Person( age == 50 ),在Person对象中,满足age属性等于50;
Then: 满足条件时触发的动作,包括增、删、改三个动作;
End:规则执行结束的标识符。
第一次接触的Drools的话对于各种配置和组件关系还是比较蒙蔽的,结合个人理解,给出一个简单的关系图,画的可能有失偏颇,如有不对,还请指出:
kmodule.xml:定义在/META-INF/kmodule.xml,配置一个或多个Kiebase,每个Kiebase可配置多个KieSession。通常可以运行时根据项目需求动态生成KieBases
和 KieSessions
,依赖于KieFileSystem提供各种方法。动态创建kmodule.xml的内容并加入到KieFileSystem。
KieBase:在项目的KIE模块描述符文件(kmodule .xml)中定义的存储库,它包含Drools中的所有内容,但不包含任何运行时数据,可通过KieContainer获得:KieBase kBase = kContainer.getKieBase();
KieServices:接口,可以访问所有的创建和运行时对象,如日志,资源,环境,容器等。其中有的方法分为两大类:getX()和newX(),其中,get只会返回一个对应单例对象的引用,new则会重新创建一个对象。
KieContainer: 装载与引擎相关的组件,通过KieServices.Factory.get()方式获得,为其他Kie工具提供服务。KieContainer可以通过ReleaseId,Artifact,Version参数获得另外一个KieContainer:
KieSession:在Drools中,KIE会话存储并执行运行时数据。如果在项目的KIE模块描述符文件(kmodu .xml)中定义了KIE会话,则可以从KIE基础创建KIE会话,或者直接从KIE容器创建,可细分有状态和无状态连接。
.drl文件:可以动态的添加,KieResources
提供了多种工厂方式以转化为InputStream
, URL
, File
, String
创建.drl文件后,重新加载:
嵌套规则,也可以理解为多重条件判定,这个Drools可以做的很好,主要是了解其drl文件的语法规则,则能够很好的处理复杂的逻辑判断,如嵌套对象、集合等常见需求,下面简单的给个示例:
1)定义User对象如下:
@Data public class User { private String name; private Integer age; private Pet pet;}
2)定义Pet如下:
@Data public class Pet { private String name; private String color;}
3)定义规则如下:
rule "nested multiple condition" when $user : User(age>15 && age<60) $pet : Pet() from $user.pet if($pet.getColor()=="black") do[black] if($pet.getColor()=="white") break[white] then System.out.print("测试结束"); then [black] System.out.println("pet color is balck"); then [white] System.out.print("pet color is white"); end
4)执行逻辑为:
简单场景下,drl文件可以预先定义好,但是很多时候我们需要根据条件来生成drl文件,或者从数据库加载文件内容,此时就要动态地生成drl文件。其流程简述为:界面配置,后台生成drl文件,写入规则引擎。其核心思想是:根据界面规则生成相应的.drl文件,动态加载进内存再由引擎判定。代码参考如下:
public void reload() throws UnsupportedEncodingException { KieServices kieServices = getKieServices(); KieFileSystem kfs = kieServices.newKieFileSystem(); kfs.write("src/main/resources/rules/temp.drl", loadRules()); KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll(); Results results = kieBuilder.getResults(); if (results.hasMessages(Message.Level.ERROR)) { System.out.println(results.getMessages()); throw new IllegalStateException("### errors ###"); } } private String loadRules() { // 假设从数据库加载的规则 return "package adress\n\n rule \"Postcode 6 numbers\"\n\n when\n then\n System.out.println(\"规则2中打印日志:我是从数据库加载的!\");\n end"; }
更为普遍地使用场景是:规则可以动态生成(如上所述),规则可以动态加载进引擎,根据条件加载指定地规则。这又如何实现呢?
在Drools中,KieContainer是引擎执行时的核心工具,一个container会加载kmodule.xml中的所有资源。因此,可以将不同的kmodule.xml加载进不同的container,那么就可以根据参数选择container,从而触发此container中的引擎。注意,drl文件和kmodule.xml不是一对一的关系,但是drl文件的包名和kmodule.xml中package属性是对应的,详见下节讨论。为保证项目结构清晰,便于管理,一般可以kmodule.xml对应一个drl文件。
参考代码如下:
private KieContainer getContainer(String domain) { KieServices kieServices = KieServices.Factory.get(); KieFileSystem kfs = kieServices.newKieFileSystem(); //内部方法,生成kmodule.xml文件,返回此xml文件中KieSession名称,下次可根据此sessionName从kieContainer中生成获得对应的session sessionName = generateXML(domain, kieServices, kfs); //写入drl文件并加载进 kfs.write("src/main/resources/rules/temp.drl", loadRules()); KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll(); //生成装载此xml文件的容器 KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId()); //建立对应关系并缓存起来此规则 cache.put(domain,kieContainer); return kieContainer; } //访问资源 @ResponseBody @RequestMapping("dynamic/{domain}") public String resource(@PathVariable String domain) { String res="你不是第一次访问,直接加载相关资源"; KieContainer kieContainer = cache.get(domain); if (null == kieContainer) { res="你是第一次访问,生成相关资源"; kieContainer=getContainer(domain); } //根据之前生成的sessionName获取kieSession,然后规则校验 final KieSession kieSession = kieContainer.newKieSession(sessionName); kieSession.insert(new Address()); kieSession.fireAllRules(); kieSession.dispose(); return res; }
这种需求也是很常见的,比如不同的产品在出厂时,其校验规则肯定是不一样的,都有其自身特有的属性校验。那么,如何根据不同的参数来使用不同规则呢?如下kmodule.xml文件:
<kmodule xmlns="http://www.drools.org/xsd/kmodule"> <kbase name="kbase1"> <ksession name="ksession1"/> </kbase> <kbase name="kbase2" packages="org.some.pkg"> <ksession name="ksession2"/> </kbase> </kmodule>
可以根据kmodule.xml中不同的package属性来指定加载哪个.drl文件,packages="org.some.pkg"表示ksession2只会加载org.some.pkg下的规则文件,如果没写,则默认加载所有的规则文件。相应Java代码如下:
KieContainer kc =KieServices.Factory.get().getKieClasspathContainer(); KieSession kieSession = kc.newKieSession("ksession2");
此KieSession只会加载drl文件中有package org.some.pkg 声明的规则文件。如果没有指明kiesession名称,则会默认加载所有的drl文件,并且此时kmodule.xml中不能声明任何kbase标签,否则报错:
java.lang.RuntimeException: Cannot find a default KieSession
规则的判定顺序可以使用属性Salience:定义规则优先级的整数。值越大,优先级越高,如salience 10
到此,相信大家对“Drools规则引擎的作用是什么”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。