1.简述
业务需求总是千变万化,如何把业务需求中的业务规则给抽取出来;如何让技术和决策分开来,规则引擎的动态加载为我们提供了一个方案;drools从6.0版本开始提供动态加载规则,6.4.0.Final版本改变了很多API;
本期的方案将把drools的规则放置到数据库中,并动态生成规则:demo中第一次不命中规则,中间动态增加一个规则文件,第二次再次匹配则命中;
2.代码
核心工具类 :DroolsUtils.java资源包装类:ResourceWrapper.javapackage 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; } }
fact类:Message.javapackage 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; } }
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.javapackage 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