-
- 在drools中如果使用规则表
典型的用法就是根据excel创建KnowledgeBase,然后将它丢给session执行,执行的参数和结果都在params里面package com.xxx.yyyy; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import junit.framework.Assert; import org.drools.KnowledgeBase; import org.drools.KnowledgeBaseFactory; import org.drools.builder.DecisionTableConfiguration; import org.drools.builder.DecisionTableInputType; import org.drools.builder.KnowledgeBuilder; import org.drools.builder.KnowledgeBuilderFactory; import org.drools.builder.ResourceType; import org.drools.definition.KnowledgePackage; import org.drools.io.ResourceFactory; import org.drools.runtime.StatelessKnowledgeSession; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public class IsP4PTest{ private IsP4P param; private String extected; public IsP4PTest(IsP4P param,String extected) { this.param = param; this.extected = extected; } public static class IsP4P { private String productLine; private String productType; private String playType; public IsP4P(String productLine,String productType,String playType){ this.productLine = productLine; this.productType = productType; this.playType = playType; } public Map<String,Object> getParams(){ Map<String,Object> params = new HashMap<String,Object>(); params.put("productLine", productLine); params.put("productType", productType); params.put("playType", playType); return params; } } public void testExcel(String fileName, Map<String, Object> params) throws Exception { System.out.println("---------------begin------------------------"); DecisionTableConfiguration dtableconfiguration = KnowledgeBuilderFactory .newDecisionTableConfiguration(); dtableconfiguration.setInputType(DecisionTableInputType.XLS); final KnowledgeBuilder kbuilder = KnowledgeBuilderFactory .newKnowledgeBuilder(); File file = new File("D:\\iwork-space\\rule\\src\\test\\resources\\" + fileName); InputStream is = new FileInputStream(file); // InputStream is = new ClassPathResource(fileName).getInputStream(); kbuilder.add(ResourceFactory.newInputStreamResource(is,"UTF-8"), ResourceType.DTABLE); if (kbuilder.hasErrors()) { System.out.println(kbuilder.getErrors().toString()); } Collection<KnowledgePackage> pkgs = kbuilder.getKnowledgePackages(); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages(pkgs); StatelessKnowledgeSession ksession = kbase .newStatelessKnowledgeSession(); ksession.execute(Arrays.asList(new Object[] {params})); System.out.println("---------------end------------------------"); } @Parameters public static Collection<?> contructData(){ return Arrays.asList(new Object[][]{ {new IsP4P("aa","true","null"),"true"}, {new IsP4P("bb","true","null"),"true"}, {new IsP4P("cc","true","aa"),"false"}, {new IsP4P("dd","false","bb"),"other"} }); } @Test public void testP4P() throws Exception{ Map<String,Object> params = new HashMap<String,Object>(); params.putAll(param.getParams()); testExcel("ka/isP4P.xls", params); Assert.assertEquals(extected, params.get("isP4P")); } }
- 什么时候考虑使用规则表
如果规则可以表示成 templates+data(模板+数据),可以考虑使用 decision tables。在决策表的每一行,采集数据和模板一起生成规则。使用基于决策表的Spreadsheet的API在Drools-decisiontables模块中。只有一个类:SpreadsheetCompiler. 这个类可以操作各种格式的Spreadsheet,并生成DRL规则(然后就可以常规的方式使用)。
- 一个典型的规则表的格式
- RuleSet关键字是必须的,名字是可选的
- Import语句非常像java的import,如果有多个import,用逗号隔开
- RuleTable关键字也是必须的,它指示了后面将会有一批rule,ruletable的名称将会作为以后生成rule的前缀
- 条件如果不写的话默认就是==, 比如上面的contract.get("productLine"),其实就是contract.get("productLine") == $param, 如果有多个参数可以使用$1,$2,比如我们经常用到的一个区间数据,这个占位符就派上用场了
- 所有的关键字都是忽略大小写的
- 默认情况下规则引擎只解析第一个sheet的规则
- 规则区域所支持的关键字
Keyword | Value | Usage |
---|---|---|
RuleSet | The package name for the generated DRL file. Optional, the default is rule_table .(默认值是rule_table) | Must be First entry. |
Sequential | "true" or "false". If "true", then salience is used to ensure that rules fire from the top down.(规则触发是从上朝下,如果是false就是乱序) | Optional, at most once. If omitted, no firing order is imposed. |
Import | A comma-separated list of Java classes to import.(逗号隔开) | Optional, may be used repeatedly. |
Variables | Declarations of DRL globals, i.e., a type followed by a variable name. Multiple global definitions must be separated with a comma. 全局变量定义,多个用逗号隔开 | Optional, may be used repeatedly. |
Functions | One or more function definitions, according to DRL syntax. | Optional, may be used repeatedly. |
Queries | One or more query definitions, according to DRL syntax. | Optional, may be used repeatedly. |
需要特别注意的是这些关键字只能出现一次!
- Rule Table的头部所支持的关键字
Keyword | Initial | Value | Usage |
---|---|---|---|
NAME | N | Provides the name for the rule generated from that row. The default is constructed from the text following the RuleTable tag and the row number. | At most one column |
DESCRIPTION | I | A text, resulting in a comment within the generated rule. | At most one column |
CONDITION | C | Code snippet and interpolated values for constructing a constraint within a pattern in a condition. | At least one per rule table |
ACTION | A | Code snippet and interpolated values for constructing an action for the consequence of the rule. | At least one per rule table |
METADATA | @ | Code snippet and interpolated values for constructing a metadata entry for the rule. | Optional, any number of columns |
- 将excel编译成规则文件
package com.xxx.yyy;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.drools.decisiontable.InputType;
import org.drools.decisiontable.SpreadsheetCompiler;
import org.junit.Test;
public class SpreadsheetCompilerTest {
@Test
public void compile() throws FileNotFoundException{
File file = new File("D:\\iwork-space\\rule\\src\\test\\resources\\ka\\isP4P.xls");
InputStream is = new FileInputStream(file);
SpreadsheetCompiler converter = new SpreadsheetCompiler();
String drl = converter.compile(is, InputType.XLS); //--------exception here--------
System.out.println("\n\n" + drl);
}
}
编译后的结果如下:
这个地方注意一点,==和equals是相同的,!= 和 !equals是相同的
// Similar to: java.util.Objects.equals(person.getFirstName(), "John")
// so (because "John" is not null) similar to:
// "John".equals(person.getFirstName())
Person( firstName == "John" )
The != operator has null-safe !equals() semantics:
// Similar to: !java.util.Objects.equals(person.getFirstName(), "John")
Person( firstName != "John" )