本文中所有文件在同一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
希望对你有帮助,祝你有一个好心情,加油!
若有错误、不全、可优化的点,欢迎纠正与补充!