1. 程式人生 > 實用技巧 >Drools-決策表使用1-快速開始

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>
    
  • 專案結構圖
  • 本次測試實體類
    @Data
    @Accessors(chain = true)
    public class PersonInfoEntity {
    	private String sex;
    	private int age;
    	private double salary;
    }
    
  • xls規則檔案參考
  • 開始:直接從類路徑讀取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模板下載,下方有整理的參考資料

參考