本文中所有文件在同一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
希望對你有幫助,祝你有一個好心情,加油!
若有錯誤、不全、可優化的點,歡迎糾正與補充!