Drools6.4动态加载规则之(二)动态创建kjar

1.简述

业务需求总是千变万化,如何把业务需求中的业务规则给抽取出来;如何让技术和决策分开来,规则引擎的动态加载为我们提供了一个方案;drools从6.0版本开始提供动态加载规则,6.4.0.Final版本改变了很多API;

本期的方案将把drools的规则放置到数据库中,并动态生成规则:demo中第一次不命中规则,中间动态增加一个规则文件,第二次再次匹配则命中;

2.代码

 

核心工具类 :DroolsUtils.java
package com.caicongyang.drools.utils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.ReleaseId;
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.conf.EqualityBehaviorOption;
import org.kie.api.conf.EventProcessingOption;
import org.kie.internal.io.ResourceFactory;

/**
 * 动态生成kjar工具类
 * @author caicongyang1
 * @version id: DroolsUtils, v 0.1 16/10/26 下午1:58 caicongyang1 Exp $$
 */
public class DroolsUtils {

    /**
     * 默认规则文件所在路径
     */
    private static final String RULES_PATH = "rules";

    /**
     * 获取规定目录下的规则文件
     *
     * @return
     * @throws IOException
     */
    private static List<File> getRuleFiles() throws IOException {
        List<File> list = new ArrayList<File>();
        String filePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
        File rootDir = new File(filePath);
        File[] files = rootDir.listFiles();
        for (File itemFile : files) {
            if (itemFile.isDirectory() && itemFile.getName().equals(RULES_PATH)) {
                for (File f : itemFile.listFiles()) {
                    if (f.getName().endsWith(".drl")) {
                        list.add(f);
                    }
                }
            }
        }
        return list;
    }

    /**
     * 初始化一个kjar:把原有的drl包含进新建的kjar中
     *
     * @param ks
     * @param releaseId
     * @return
     * @throws IOException
     */
    public static InternalKieModule initKieJar(KieServices ks, ReleaseId releaseId) throws IOException {
        KieFileSystem kfs = createKieFileSystemWithKProject(ks, true);
        kfs.writePomXML(getPom(releaseId));
        for (File file : getRuleFiles()) {
            kfs.write("src/main/resources/" + file.getName(),
                    ResourceFactory.newClassPathResource(RULES_PATH + File.separator + file.getName(), "UTF-8"));
        }
        KieBuilder kieBuilder = ks.newKieBuilder(kfs);
        if (!kieBuilder.buildAll().getResults().getMessages().isEmpty()) {
            throw new IllegalStateException("Error creating KieBuilder.");
        }
        return (InternalKieModule) kieBuilder.getKieModule();
    }

    public static InternalKieModule createKieJar(KieServices ks, ReleaseId releaseId, ResourceWrapper resourceWrapper) {
        KieFileSystem kfs = createKieFileSystemWithKProject(ks, true);
        kfs.writePomXML(getPom(releaseId));
        kfs.write("src/main/resources/" + resourceWrapper.getTargetResourceName(), resourceWrapper.getResource());
        KieBuilder kieBuilder = ks.newKieBuilder(kfs);
        if (!kieBuilder.getResults().getMessages().isEmpty()) {
            System.out.println(kieBuilder.getResults().getMessages());
            throw new IllegalStateException("Error creating KieBuilder.");
        }
        return (InternalKieModule) kieBuilder.getKieModule();
    }

    /**
     * 创建默认的kbase和stateful的kiesession
     *
     * @param ks
     * @param isdefault
     * @return
     */
    public static KieFileSystem createKieFileSystemWithKProject(KieServices ks, boolean isdefault) {
        KieModuleModel kproj = ks.newKieModuleModel();
        KieBaseModel kieBaseModel1 = kproj.newKieBaseModel("KBase").setDefault(isdefault)
                .setEqualsBehavior(EqualityBehaviorOption.EQUALITY).setEventProcessingMode(EventProcessingOption.STREAM);
        // Configure the KieSession.
        kieBaseModel1.newKieSessionModel("KSession").setDefault(isdefault)
                .setType(KieSessionModel.KieSessionType.STATEFUL);
        KieFileSystem kfs = ks.newKieFileSystem();
        kfs.writeKModuleXML(kproj.toXML());
        return kfs;
    }

    /**
     * 创建kjar的pom
     *
     * @param releaseId
     * @param dependencies
     * @return
     */
    public static String getPom(ReleaseId releaseId, ReleaseId... dependencies) {
        String pom = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
                + "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
                + "         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n"
                + "  <modelVersion>4.0.0</modelVersion>\n" + "\n" + "  <groupId>" + releaseId.getGroupId()
                + "</groupId>\n" + "  <artifactId>" + releaseId.getArtifactId() + "</artifactId>\n" + "  <version>"
                + releaseId.getVersion() + "</version>\n" + "\n";
        if (dependencies != null && dependencies.length > 0) {
            pom += "<dependencies>\n";
            for (ReleaseId dep : dependencies) {
                pom += "<dependency>\n";
                pom += "  <groupId>" + dep.getGroupId() + "</groupId>\n";
                pom += "  <artifactId>" + dep.getArtifactId() + "</artifactId>\n";
                pom += "  <version>" + dep.getVersion() + "</version>\n";
                pom += "</dependency>\n";
            }
            pom += "</dependencies>\n";
        }
        pom += "</project>";
        return pom;
    }
}
资源包装类:ResourceWrapper.java
package com.caicongyang.drools.utils;

import org.kie.api.io.Resource;

/**
 * 资源包装类
 * @author caicongyang1
 * @version id: ResourceWrapper, v 0.1 16/10/26 下午2:15 caicongyang1 Exp $$
 */
public class ResourceWrapper {
    private Resource resource;

    private String   targetResourceName;

    public ResourceWrapper(Resource resource, String targetResourceName) {
        this.resource = resource;
        this.targetResourceName = targetResourceName;
    }

    public Resource getResource() {
        return resource;
    }

    public String getTargetResourceName() {
        return targetResourceName;
    }

    public void setResource(Resource resource) {
        this.resource = resource;
    }

    public void setTargetResourceName(String targetResourceName) {
        this.targetResourceName = targetResourceName;
    }
}
fact类:Message.java
package com.caicongyang.drools.fact;

import java.io.Serializable;

/**
 * bean
 * @author caicongyang1
 * @version id: Message, v 0.1 16/10/26 下午2:49 caicongyang1 Exp $$
 */
public class Message implements Serializable {

    private static final long serialVersionUID = 1L;

    private String            status;

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}
主测试类:dynamicDrlTest.java
package com.caicongyang.drools.test;

import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.kie.api.KieServices;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.ReleaseId;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;

import com.caicongyang.drools.fact.Message;
import com.caicongyang.drools.utils.DroolsUtils;
import com.caicongyang.drools.utils.ResourceWrapper;

/**
 *
 * drools6.4动态加载规则文件:第一次不命中,动态增加规则以后,命中
 *
 * @author caicongyang1
 * @version id: dynamicDrlTest, v 0.1 16/10/26 下午2:00 caicongyang1 Exp $$
 */
public class dynamicDrlTest {

    private static final String RULESFILE_NAME = "rules.drl";

    /**
     * 规则文件内容(可以从数据库中加载)
     */
    private static final String rules      = "package com.caicongyang.drools.test; import com.caicongyang.drools.fact.Message; rule \"Hello World \" when message:Message (status == \"0\") then System.out.println(\"hello, Drools!\"); end";

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

        KieServices kieServices = KieServices.Factory.get();

        /**
         * 指定kjar包
         */
        final ReleaseId releaseId = kieServices.newReleaseId("com", "caicongyang", "1.0.0");

        // 创建初始化的kjar
        InternalKieModule kJar = DroolsUtils.initKieJar(kieServices, releaseId);
        KieRepository repository = kieServices.getRepository();
        repository.addKieModule(kJar);
        KieContainer kieContainer = kieServices.newKieContainer(releaseId);
        KieSession session = kieContainer.newKieSession();
        Message message = new Message();
        message.setStatus("0");
        //同一个fact第一次不命中
        try {
            session.insert(message);
            session.fireAllRules();
        } catch (Exception e) {
        } finally {
            session.dispose();
        }
        System.out.println("-----first fire end-------");

        //新增一个规则文件
        kJar = DroolsUtils.createKieJar(kieServices, releaseId,
            new ResourceWrapper(ResourceFactory.newByteArrayResource(rules.getBytes()), RULESFILE_NAME));
        repository.addKieModule(kJar);
        kieContainer.updateToVersion(releaseId);

        //同一个fact再次过滤规则:命中
        session = kieContainer.newKieSession();
        try {
            session.insert(message);
            session.fireAllRules();
        } catch (Exception e) {
        } finally {
            session.dispose();
        }
        System.out.println("-----senond fire end-------");

    }

}
上一篇:Drools6.4动态加载规则之(一)模板的简单应用 :http://blog.csdn.net/caicongyang/article/details/52702628
 
 

更多精彩内容请继续关注我的博客http://blog.csdn.NET/caicongyang

记录与分享,你我共成长 -from caicongyang

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值