千家信息网

Drools规则引擎的作用是什么

发表于:2024-12-02 作者:千家信息网编辑
千家信息网最后更新 2024年12月02日,本篇内容主要讲解"Drools规则引擎的作用是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Drools规则引擎的作用是什么"吧!一、规则描述及判定规
千家信息网最后更新 2024年12月02日Drools规则引擎的作用是什么

本篇内容主要讲解"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。通常可以运行时根据项目需求动态生成KieBasesKieSessions,依赖于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如下:

@Datapublic 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文件,写入规则引擎。其核心思想是:根据界面规则生成相应的.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.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规则引擎的作用是什么"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

0