drools的懶加載和執行

drools網上資料很多,這裏針對自己的接觸瞭解和實際應用進行如下總結,

  1. 工程引入。
    工程pom.xml,至少需加入
    <dependency>
    	<groupId>org.kie</groupId>
    	<artifactId>kie-api</artifactId>
    	<version>6.5.0.Final</version>
    </dependency>
    <dependency>
    	<groupId>org.drools</groupId>
    	<artifactId>drools-compiler</artifactId>
    	<version>6.5.0.Final</version>
    </dependency>

    從官網下包,例如:drools-distribution-6.5.0.Final,從binaries目錄,大致需手工引入第三方包:
    ant-1.8.3.jar
    core-3.1.1.jar
    ecj-4.4.2.jar
    ……
    忘了還有哪些,這些是運行時用到,所以在實際使用時,可以依據報錯信息(java.lang.ClassNotFoundException),反推還需要哪些jar,反正所需要的都在binaries目錄裏。
  2. 簡單封裝。

package com.pomelo.drools.util;
import java.util.ArrayList;
import java.util.List;

import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.builder.Message;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.AgendaFilter;
import org.kie.api.runtime.rule.Match;

import com.pomelo.drools.model.RuleCfg;

/**
 * @author zxz
 *
 */
public class MyDrools {	
	/**
	 * 對GKS、GKR、GKFS這三個的概念模棱兩可,大概一個應用構建一套就OK了。
	 */
	private static final KieServices GKS = KieServices.Factory.get();
	private static final KieRepository GKR = GKS.getRepository();
	private static final KieFileSystem GKFS = GKS.newKieFileSystem();
	/**
	 * 用於本地應用標記哪個規則文件已加載。
	 */
	private static List<string> gKfsFacade = new ArrayList<string>();
	/**
	 * 用於存放已加載規則的容器,每次加載規則需重新生成。
	 */
	private static KieContainer kc;
	/**
	 * 規則配置,一般存在數據庫中,這裏用靜態語句塊初始化。
	 */
	private static RuleCfg ruleCfg;
	
	static {
		StringBuffer sb = new StringBuffer("package com.pomelo.drools.drl;\n");
		sb.append("import com.pomelo.drools.model.Users\n");
		sb.append("rule \"userStatusChangeRule\"\n");
		sb.append("when\n");
		sb.append("users:Users(status == 0)\n");
		sb.append("then\n");
		sb.append("users.status = 1;\n");
		sb.append("System.out.println(\"done\");\n");
		sb.append("end;\n");

		ruleCfg = new RuleCfg();
		ruleCfg.setRuleId(2000001);
		ruleCfg.setClassify("user_status_change");
		ruleCfg.setRuleName("userStatusChangeRule");
		ruleCfg.setRule(sb.toString());
		ruleCfg.setStatus(0);
	}
	
	/**
	 * ruleId:規則編碼,例如:2000001。
	 * params:規則判斷所需要的參數。
	 */
	public static void invokeIns(final int ruleId, Object... params) {		
		/**
		 * loadCfg:根據規則編碼查詢規則對象,實際應用是查詢數據庫,這裏簡化不做說明。
		 */
		RuleCfg ruleCfg = loadCfg(ruleId);
		/**
		 * 生成規則文件存放路徑,這裏可以大致推測drool部分核心內容,是把規則寫在drl文件,drools內部自己構建一個文件系統。
		 */
		String drlPath = genDrlPath(ruleCfg);
		
		if(ruleCfg.getStatus() == RuleCfg.STATUS_INIT)
			gKfsFacade.remove(drlPath);
		
		if(!gKfsFacade.contains(drlPath)) {
			synchronized(gKfsFacade) {
				if(!gKfsFacade.contains(drlPath)) {
					GKFS.write(drlPath, ruleCfg.getRule());
					KieBuilder kb = GKS.newKieBuilder(GKFS);
					/**
					 * 類似java工程,對文件系統進行編譯。
					 */
					kb.buildAll();
					if(kb.getResults().hasMessages(Message.Level.ERROR)) {
						System.out.println(kb.getResults().toString());
						/**
						 * 若編譯失敗,則把當前規則從文件系統中刪除掉,重新編譯。
						 */
						GKFS.delete(ruleCfg.getClassify());
						kb = GKS.newKieBuilder(GKFS);
						kb.buildAll();
						kc = GKS.newKieContainer(GKR.getDefaultReleaseId());
						throw new RuntimeException("Build Errors:\n" + kb.getResults().toString());
					}
					kc = GKS.newKieContainer(GKR.getDefaultReleaseId());
					ruleCfg.setStatus(RuleCfg.STATUS_LOADED);
					gKfsFacade.add(drlPath);
				}
			}
		}
		fireTheRule(ruleCfg.getRuleName(), params);
	}
	
	private static RuleCfg loadCfg(final int ruleId) {
		return ruleCfg;
	}
	
	private static String genDrlPath(RuleCfg ruleCfg) {
		return "src/main/resources/drl/" + ruleCfg.getClassify() + "/" + ruleCfg.getRuleName() + ".drl";
	}
	
	private static void fireTheRule(String ruleName, Object... params) {
		KieSession ks = kc.newKieSession();
		try {
			for(int i = 0;i < params.length;i++) {
				ks.insert(params[i]);
			}
			ks.fireAllRules(ruleNameEqualsAgendaFilter(ruleName));
		} finally {
			ks.dispose();
		}
	}
	
	private static AgendaFilter ruleNameEqualsAgendaFilter(final String ruleName) {
		return new AgendaFilter() {
			public boolean accept(Match paramMatch) {
				return paramMatch.getRule().getName().equals(ruleName);
			}
		};
	}
}
完整工程,詳見https://github.com/Monicazxz/MyDrools
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章