Drools-决策表使用1-快速开始

前言

决策表(decision-table)即以xls表格的形式定义规则,而不再是只有开发人员能看懂的drl文本。
对业务人员来说,这种EXCEL表格肯定是友好的;对开发人员而言,需要使用官方API将xls内容“翻译”为熟悉的drl串,即编译器SpreadsheetCompiler

快速开始

  • 新建Maven工程
    <drools.version>7.42.0.Final</drools.version>
    
    <dependency>
    	<groupId>org.drools</groupId>
    	<artifactId>drools-decisiontables</artifactId>
    </dependency>
    
  • 项目结构图
    image
  • 本次测试实体类
    @Data
    @Accessors(chain = true)
    public class PersonInfoEntity {
    	private String sex;
    	private int age;
    	private double salary;
    }
    
  • xls规则文件参考
    image
  • 开始:直接从类路径读取xls规则文件
    /**
     * 直接从类路径找到目标xls文件,翻译,加载,触发
     */
    @Test
    public void test() {
    	String classPath = "testRule.xls";
    	SpreadsheetCompiler compiler = new SpreadsheetCompiler();
    
    	//文件读取与编译
    	InputStream is = this.getClass().getClassLoader().getResourceAsStream(classPath);
    	String drl = compiler.compile(is, InputType.XLS);
    	log.info("解析出的drl文本:\n{}", drl);
    	
    	//载入规则
    	KieHelper kieHelper = new KieHelper();
    	kieHelper.addContent(drl, ResourceType.DRL);
    	
    	//定义fact
    	PersonInfoEntity personInfoEntity = new PersonInfoEntity();
    	personInfoEntity.setSex("女").setAge(35).setSalary(1000);
    
    	//创建会话,fact插入工作内存,触发
    	KieSession session = kieHelper.build().newKieSession();
    	List<String> list = new ArrayList<String>();
    	session.setGlobal("listRules", list);
    	session.insert(personInfoEntity);
    	session.getAgenda().getAgendaGroup("sign").setFocus();
    	session.fireAllRules();
    	for (String s : list) {
    		log.info("输出结果:{}", s);
    	}
    	
    	//关闭会话
    	session.dispose();
    }
    
  • 改进1:切换读取指定路径的磁盘xls文件
    /**
     * 直接从类路径找到目标xls文件,翻译,加载,触发
     */
    @Test
    public void test() {
    	String classPath = "testRule.xls";
    	String fsp = "D:/temp/testRule.xls";
    
    	//文件读取与编译
        //String drl = readXlsDrl("cp", classPath);
    	String drl = readXlsDrl("fs", fsp);
    	
    	//载入规则
    	KieHelper kieHelper = new KieHelper();
    	kieHelper.addContent(drl, ResourceType.DRL);
    	...
    }
    
    private String readXlsDrl(String type, String path) {
    	InputStream is = null;
    	if("cp".equals(type)) {
    		is = this.getClass().getClassLoader().getResourceAsStream(path);
    	}else if("fs".equals(type)) {
    		try {
    			is = new FileInputStream(new File(path));
    		} catch (FileNotFoundException e) {
    			log.error("文件读取异常", e);
    			throw new RuntimeException("文件读取异常", e);
    		}
    	}
    	SpreadsheetCompiler compiler = new SpreadsheetCompiler();
    	String drl = compiler.compile(is, InputType.XLS);
    	log.info("解析出的drl文本:\n{}", drl);
    	return drl;
    }
    
  • 改进2:添加显式的drl语法检查
    @Test
    public void test() {
    	String classPath = "testRule.xls";
    	String fsp = "D:/temp/testRule.xls";
    
    	//文件读取与编译
        // String drl = readXlsDrl("cp", classPath);
    	String drl = readXlsDrl("fs", fsp);
    	
    	//载入规则
    	KieHelper kieHelper = new KieHelper();
    	kieHelper.addContent(drl, ResourceType.DRL);
    	
    	//drl文本语法校验
    	verifyDrl(kieHelper);
    	...
    }
    
    private void verifyDrl(KieHelper kieHelper) {
    	Results verify = kieHelper.verify();
    	if (verify.hasMessages(Message.Level.WARNING, Message.Level.ERROR)) {
    		List<Message> messages = verify.getMessages(Message.Level.WARNING, Message.Level.ERROR);
    		for (Message message : messages) {
    			log.error("Error: " + message.getText());
    		}
    		throw new IllegalStateException("Compilation errors were found. Check the logs.");
    	}
    }
    

小结

  • 从API可以看出
    • Drools同时也支持从CSV文件读取规则定义
    • 支持任意来源的drl文本串,即初版(见下方demo源码同级工程)的将.drl文件内容直接放置数据库,全权交给开发人员维护
  • 官方文档不太友好,冗长且没有xls模板下载,下方有整理的参考资料

参考

posted @ 2020-09-09 23:28  summaster  阅读(915)  评论(0编辑  收藏  举报