美文网首页
Drools动态加载规则

Drools动态加载规则

作者: 淡淡的小番茄 | 来源:发表于2021-06-27 20:39 被阅读0次

    使用Drools来做规则的动态加载比较简单,本人结合我们的数据转发场景,来具体说一说。主要使用了Drools的模板、自定义函数功能。Drools用的版本是7.6.0.Final。

    定义DRL文件

    DRL文件建议存储在MYSQL中,并提供HTTP服务接口供执行引擎调用。

    forward.drl模板信息:


    template header

    orgId

    orgKey

    productKey

    productLabels

    package drools.example;

    import org.drools.example.api.namedkiesession.Message;

    //自定函数,实现标签包含功能

    function int hasProductLabels(String deviceLabels,String labels){

      return deviceLabels.indexOf(labels)==-1?0:1;

    }

    template "forward"

    rule "mytest"

    when

    $msg : Message(orgId =='@{orgId}' && productKey=='@{productKey}')

    && eval(hasProductLabels('@{productLabels}',$msg.getProductLabels())>0)

    then

    System.out.println("===orgId:@{orgId},orgKey:@{orgKey},ruleName:mytest===)");

    end

    end template



    编译生成DRL规则信息

    示例代码如下,主要通过http接口加载规则信息。ObjectDataCompiler一次无法编译大量规则,我试了下1000个规则会报栈内存溢出。如果规则比较多,可以分批进行编译。

    public static String getRuleByOrg(long orgId,String ruleName) {

        ObjectDataCompiler odc = new ObjectDataCompiler();

    try {

    //执行与管理以http接口通信

    Resource r1 = ResourceFactory.newUrlResource(new URL("http://127.0.0.1:8080/rule/getForwardRules?orgId="+orgId+"&ruleName="+ruleName));

    Map<String, Object> data = new HashMap<>();

    //账户信息

    data.put("orgId", orgId);

    data.put("orgKey", String.valueOf("k"+orgId));

    data.put("orgName", "xxyyzz");

    //设备产品信息

    data.put("productKey", "cu3im1kts3rz8dSc");

    data.put("productName", "智慧水表");

    data.put("deviceKey", "QoearAEbXaU1meN");

    //产品设备标签

    data.put("productLabels","101,102,103");

    data.put("deviceLabels","201,202,203");

    //其它信息

    data.put("type", "123");

    data.put("action", 1);

    return odc.compile(Arrays.asList(data), r1.getInputStream());

    } catch (MalformedURLException e) {

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

    }

    return null;

    }

    规则执行校验

    示例代码如下,主要包括了:规则删除、同session下动态加载、新session下动态加载。

    public static void main(String[] args) throws Exception {

    KieHelper helper = new KieHelper();

    // 先加载规则mytest>>11111

    helper.addContent(getRuleByOrg(11111, "mytest"), ResourceType.DRL);

    KieBase kieBase = helper.build();

    KieSession session = kieBase.newKieSession();

    // 触发规则mytest>>11111

    System.out.println("触发规则:mytest>>11111");

    Message msg = new Message();

    msg.setOrgId(11111L);

    msg.setOrgKey(String.valueOf("k" + 11111));

    msg.setProductKey("cu3im1kts3rz8dSc");

    msg.setProductLabels("101,102,103");

    msg.setDeviceLabels("201,202,203");

    session.insert(msg);

    session.fireAllRules();

    // 移除规则mytest>>11111

    System.out.println("删除规则:mytest>>11111");

    kieBase.removeRule("drools.example", "mytest");

    // 重新添加规则mytest>>22222

    System.out.println("载入新规则:mytest>>22222");

    KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();

    // 装入规则,可以装入多个

    // kb.add(ResourceFactory.newByteArrayResource(drlStr2.getBytes("utf-8")),

    // ResourceType.DRL);

    kb.add(ResourceFactory.newByteArrayResource(getRuleByOrg(22222, "mytest").getBytes("utf-8")), ResourceType.DRL);

    // 重用session方式

    ((InternalKnowledgeBase) kieBase).addPackages(kb.getKnowledgePackages());

    System.out.println("重用session方式,触发规则:mytest>>22222");

    msg = new Message();

    msg.setOrgId(22222L);

    msg.setOrgKey(String.valueOf("k" + 22222));

    msg.setProductKey("cu3im1kts3rz8dSc");

    msg.setProductLabels("101,102,103");

    msg.setDeviceLabels("201,202,203");

    session.insert(msg);

    session.fireAllRules();

    session.dispose();

    // 新开session

    InternalKnowledgeBase ikBase = KnowledgeBaseFactory.newKnowledgeBase();

    ikBase.addPackages(kb.getKnowledgePackages());

    session = ikBase.newKieSession();

    msg = new Message();

    msg.setOrgId(22222L);

    msg.setOrgKey(String.valueOf("k" + 22222));

    msg.setProductKey("cu3im1kts3rz8dSc");

    msg.setProductLabels("101,102,103");

    msg.setDeviceLabels("201,202,203");

    session.insert(msg);

    System.out.println("重新创建session方式,触发规则:mytest>>22222");

    session.fireAllRules();

    }

    运行后最终效果

    相关文章

      网友评论

          本文标题:Drools动态加载规则

          本文链接:https://www.haomeiwen.com/subject/zwnxultx.html