Drools5.0.1使用excel實例

本文中所有文件在同一Package下:

excelDrools.drt//規則編譯模板

template header
space
chageNum
gainFlag
MaxNum
from
remark

package com.cheng_xy.drools.excel.util

import com.cheng_xy.drools.excel.bean.ExcelDrollsInputParam;
import com.cheng_xy.drools.excel.bean.ExcelDroolsOutputParam;

global ExcelDroolsOutputParam output;

template "Excel規則模板"

rule " Drools_@{remark}"
	when
		ExcelDrollsInputParam(space == "@{space}",starting  matches "@{from}",betweenNum <= @{MaxNum})
	then
	 output.setChageNum("@{chageNum}");
	 output.setGainFlag("@{gainFlag}");
	 output.setRemark("==說明==" + "@{remark}");
end

end template

excelDrools.drt//簡單描述

1 template header
2 space
3 chageNum
4 gainFlag
5 MaxNum
6 from
7 remark
8 
9 package com.cheng_xy.drools.excel.util
10 
11 import com.cheng_xy.drools.excel.bean.ExcelDrollsInputParam;
12 import com.cheng_xy.drools.excel.bean.ExcelDroolsOutputParam;
13 
14 global ExcelDroolsOutputParam output;
15 
16 template "Excel規則模板"
17 
18 rule " Drools_@{remark}"
19 	when
20 		ExcelDrollsInputParam(space == "@{space}",starting  matches "@{from}",betweenNum <= @{MaxNum})
21 	then
22 	 output.setChageNum("@{chageNum}");
23 	 output.setGainFlag("@{gainFlag}");
24 	 output.setRemark("==說明==" + "@{remark}");
25 end
26 
27 end template

第1行:所有規則模板以template header開始。
第2-7行:在標題之後是按照它們在excel表中數據順序排列的列名。
第8行:空行表示excel數據中列定義的結束。
第9-15行:標準規則標題文本。這是DRL的標準規則,將出現在生成的DRL的頂部。將package語句和任何導入以及全局和函數定義放入本節。
第9行:package:對一個規則文件而言,package是必須定義的,必須放在規則文件第一行。特別的是,package的名字是隨意的,不必必須對應物理路徑,跟java的package的概念不同,這裏只是邏輯上的一種區分。同樣的package下定義的function和query等可以直接使用。
第11-12行:import:導入規則文件需要使用到的外部變量,這裏的使用方法跟java相同,但是不同於java的是,這裏的import導入的不僅僅可以是一個類,也可以是這個類中的某一個可訪問的靜態方法。
    比如:
      import com.drools.demo.point.PointDomain;
      import com.drools.demo.point.PointDomain.getById;
第14行:此語法是用來定義全局變量的,被用於提供應用程序對象的規則,一般來說,global是用於提供數據或者服務使用的規則,特別是應用程序服務中使用規則的後果,並返回數據規則。
第16行:關鍵字模板表示規則模板的開始。模板文件中可以有多個模板,但每個模板都應該有唯一的名稱。
第17-26行:模板規則。
第27行:關鍵字結束模板表示模板的結尾。

注:本文是個人見解,歡迎優化指出不足

excelDrools.xls//規則描述文件 即:決策表(decisiontable)決策表就是一個excel文件

ExcelDroolsUtil.java//規則的執行類

package com.cheng_xy.drools.excel.util;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Properties;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.StatefulSession;
import org.drools.compiler.DroolsParserException;
import org.drools.compiler.PackageBuilder;
import org.drools.decisiontable.ExternalSpreadsheetCompiler;
import org.drools.spi.Activation;
import com.cheng_xy.drools.excel.bean.ExcelDrollsInputParam;
import com.cheng_xy.drools.excel.bean.ExcelDroolsOutputParam;

public class ExcelDroolsUtil {
	private static ExcelDroolsUtil excelDroolsUtil = null;
	private RuleBase excelRuleBase = null;
	private static String excelDroolsURL = "";

	public ExcelDroolsUtil() throws DroolsParserException, IOException {
		InputStream in = this.getClass().getResourceAsStream("SysConfig.properties");
		Properties p = new Properties();
		p.load(in);
		excelDroolsURL = p.getProperty("ExcelDroolsURL");
		initExcelDrools();
	}

	/**
	 * 取得ExcelDroolsUtil的實例
	 * 
	 * @return
	 * @throws IOException
	 * @throws DroolsParserException
	 */
	public static ExcelDroolsUtil Instance() throws DroolsParserException,
			IOException {
		if (excelDroolsUtil == null) {
			excelDroolsUtil = new ExcelDroolsUtil();
		}
		return excelDroolsUtil;
	}
	
	/**
	 * 初始化規則引擎:規則的收集
	 * 
	 * @throws IOException
	 * @throws DroolsParserException
	 */
	private void initExcelDrools() throws IOException, DroolsParserException {

		final ExternalSpreadsheetCompiler converter = new ExternalSpreadsheetCompiler();
		String preUrl = "";
		String drl = "";
		/*
		 * excelDrools.drt 定義的參數 與excelDrools.xls文件中的列順序對應
		 * */
		if (excelDroolsURL.equals("")) {
			drl = converter.compile(this.getClass().getResourceAsStream("excelDrools.xls"),
					this.getClass().getResourceAsStream("excelDrools.drt"),
					2,
					2);
		} else {
			preUrl = excelDroolsURL;
			/*  使用助手類的一個實例ExternalSpreadsheetCompiler將模板文件和電子表格中的數據轉換到到DRL文件裏。
			 *  ExternalSpreadsheetCompiler的compile()方法有四個參數:數據,模板,以及電子表格中數據的起始的的行和列。
			 *  在我們的用例裏,數據起始值爲2行2列
			 */
			drl = converter.compile(getFileStream(preUrl + "/excelDrools.xls"),
					getFileStream(preUrl + "/excelDrools.drt"),
					2,
					2);
		}
		excelRuleBase = buildRuleBase(drl);
	}
	
	/**
	 * 讀取規則文件
	 * 
	 * @param file
	 * @return
	 * @throws IOException
	 */
	private InputStream getFileStream(String file) throws IOException {
		InputStream instream = null;
		instream = new FileInputStream(file);
		return instream;
	}

	/**
	 * 構建規則:規則編譯
	 * 
	 * @param drls
	 * @return
	 * @throws DroolsParserException
	 * @throws IOException
	 */
	private RuleBase buildRuleBase(String... drls)
			throws DroolsParserException, IOException {

		PackageBuilder builder = new PackageBuilder();
		for (String drl : drls) {
			builder.addPackageFromDrl(new StringReader(drl));
		}
		RuleBase ruleBase = RuleBaseFactory.newRuleBase();
		ruleBase.addPackage(builder.getPackage());
		return ruleBase;
	}
	
	/**
	 * 通過規則引擎獲取業務想得到的結果:規則的執行
	 * 
	 * @param space			位置標識
	 * @param starting		開始擁有的物品
	 * @param betweenNum	想得到的獎勵
	 * @return
	 */
	public ExcelDroolsOutputParam getExcelDrools(String space,String starting,int betweenNum) {
		
		if (null == excelRuleBase.getPackages() || 0 == excelRuleBase.getPackages().length) {
			System.out.println("規則 獲取失敗!");
			return null;
		}
		
		StatefulSession statefulSession;
		statefulSession = excelRuleBase.newStatefulSession();
		ExcelDrollsInputParam input = new ExcelDrollsInputParam();
		input.setSpace(space);
		input.setStarting(starting);
		input.setBetweenNum(betweenNum);
		/*
		 * Fact對象是指在Drools規則應用當中, 將一個普通的JavaBean插入到規則的WorkingMemory
當中後的對象。規則可以對 Fact 對象進行任意的讀寫操作,當一個 JavaBean 插入到
WorkingMemory 當中變成 Fact 之後,Fact 對象不是對原來的 JavaBean 對象進行 Clon,而是
原來 JavaBean 對象的引用。規則在進行計算的時候需要用到應用系統當中的數據,這些數
據設置在 Fact 對象當中,然後將其插入到規則的 WorkingMemory 當中,這樣在規則當中就
可以通過對 Fact 對象數據的讀寫,從而實現對應用數據的讀寫操作。一個 Fact 對象通常是
一個具有 getter 和 setter 方法的 POJO 對象, 通過這些 getter 和 setter 方法可以方便的實現對
Fact 對象的讀寫操作,所以我們可以簡單的把 Fact 對象理解爲規則與應用系統數據交互的
橋樑或通道。
		 * */
		statefulSession.insert(input);//插入一個fact對象
		statefulSession.setGlobal("output", new ExcelDroolsOutputParam());//設置一個global對象
		// 執行匹配規則
		int num = statefulSession.fireAllRules(
				new org.drools.spi.AgendaFilter() {
					public boolean accept(Activation activation) {
						System.out.println("getExcelDrools()Rule name is:"+ activation.getRule().getName());
						return !activation.getRule().getName().contains("_test");//若規則名裏包含_test,則該規則不生效
					}
				});
		//釋放相關內存資源
		statefulSession.dispose();
		
		if (num == 0) {
			System.out.println("規則引擎執行失敗!沒有匹配到任何規則。");
			return null;
		}
		//通過源碼得知,SetGlobal其實是放的Object,所以在規則文件中,讀取的也是Object,所以我們定義的值,或者是泛型都要通過強轉才能將值取出。
		ExcelDroolsOutputParam edOut = (ExcelDroolsOutputParam) statefulSession.getGlobal("output");
		System.out.println("getExcelDrools()結束 :所有取得的值=" + edOut.toString());

		return edOut;
	}
	
	/**
	 * 刷新規則
	 */
	public void refreshExcelDrools() throws DroolsParserException, Exception {
		// 取得規則包,將其刪除
		org.drools.rule.Package[] packages = excelRuleBase.getPackages();
		for (org.drools.rule.Package pg : packages) {
			excelRuleBase.removePackage(pg.getName());
		}
		// 初始化規則
		initExcelDrools();
	}

	public static void main(String[] args) throws DroolsParserException, Exception {
		//規則的編譯與運行要通過:規則編譯、規則收集和規則的執行
		excelDroolsUtil = ExcelDroolsUtil.Instance();
		long startTime = System.currentTimeMillis(); // 獲取開始時間
		// 調用
		ExcelDroolsOutputParam outputParam = excelDroolsUtil.getExcelDrools("P", "PEK", 90);
		long endTime = System.currentTimeMillis(); // 獲取結束時間
		System.out.println("程序運行時間: " + (endTime - startTime) + "ms");
	}
}

SysConfig.properties//規則文件地址配置//可以沒有

##ExcelDroolsURL=E:/testFile
ExcelDroolsURL=

下載對應jar包後,可以直接運行,我的demo鏈接:https://pan.baidu.com/s/1jRYQq1Y2JTYjP2yEK-DrsA
提取碼:cie0

希望對你有幫助,祝你有一個好心情,加油!

若有錯誤、不全、可優化的點,歡迎糾正與補充!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章