規則引擎是大型系統必不可少的一個組件,基於規則引擎可以實現靈活的規則和控制功能。本文從需求出發,介紹了一種簡單且高效的實現規則引擎的方案。
第一章需求概述
規則引擎的應用可以說非常的廣泛,規則引擎可以分為基於條件配置的簡單規則引擎和基於數據分析統計的復雜的規則引擎,本文檔主要討論的是基於條件配置的簡單規則引擎實現。
1.1 業務場景示例
需要實現根據醫生診斷的症狀來展示可以使用的葯品,比如一個女患者被醫生診斷為:氣血兩虛,身體瘦弱,腰膝酸軟,月經不調,那么系統會根據這些症狀展示合適的調理葯品烏雞白鳳丸。
1.2 業務分析抽象
現在我們來分析一下葯品推薦系統的場景。患者首先是個女的,那么有一個條件是性別為女;氣血的診斷情況為兩虛;身體狀況為瘦弱;腰膝情況是酸軟,月經的狀態是不協調。如果滿足了這些條件的話,那么系統要為醫生展示推薦葯品烏雞白鳳丸。
通過上述分析,我們可以比較容易得出一個抽象場景:即症狀符合了規則,就展示推介的結果,其中規則是由一系列的條件所組成的,當所有的條件都滿足了,那么就符合了規則。
分析完之后,是不是覺得豁然開朗了。下面我們來看一下具體要怎么去設計。
第二章系統設計實現
本章主要結合上一章節業務分析抽象的內容討論簡單的數據庫結構設計和系統編碼實現。
2.1 數據庫設計
2.1.1 症狀規則表
症狀規則表
數據項 |
類型 |
備注 |
規則ID |
文本 |
主鍵 |
規則名稱 |
文本 |
名稱 |
規則表達式 |
文本 |
條件表達式 |
表達式描述 |
文本 |
表達式描述 |
2.1.2 症狀條件表
症狀條件表
數據項 |
類型 |
備注 |
條件ID |
文本 |
主鍵 |
條件名稱 |
文本 |
名稱 |
條件標識符 |
文本 |
條件的唯一標識符 |
條件編碼 |
文本 |
條件的key編碼(如:性別=sex) |
條件計算方式 |
文本 |
計算方式(如:等於,大於,小於,包含…) |
條件值 |
文本 |
條件的值(如:女=femal 或者女=0) |
規則ID |
文本 |
規則ID值 |
2.1.3 展示結果表
展示結果表
數據項 |
類型 |
備注 |
結果ID |
文本 |
主鍵 |
結果名稱 |
文本 |
結果的描述 |
規則ID |
文本 |
規則ID值 |
2.1.4 數據存儲示例
症狀規則表
規則ID |
規則名稱 |
規則表達式 |
表達式描述 |
1001 |
烏雞白鳳丸規則 |
(A1 && A2 && A3 && A4 && A5) |
性別等於femal 而且 氣血等於weak 而且 身體狀況等於thin 而且 腰膝情況等於limp 而且 月經狀態等於menoxenia |
症狀條件表
條件ID |
條件名稱 |
條件標識符 |
條件編碼 |
計算方式 |
條件值 |
規則ID |
1 |
性別等於 |
A1 |
sex |
= |
femal |
1001 |
2 |
氣血等於 |
A2 |
blood |
= |
weak |
1001 |
3 |
身體狀況等於 |
A3 |
body |
= |
thin |
1001 |
4 |
腰膝情況等於 |
A4 |
waist |
= |
limp |
1001 |
5 |
月經狀態等於 |
A5 |
menses |
= |
menoxenia |
1001 |
展示結果表
結果ID |
結果名稱 |
規則ID |
1 |
烏雞白鳳丸:主治女性氣血兩虛,身體瘦弱,腰膝酸軟,月經不調。 |
1001 |
2.2 編碼實現
從數據庫結構和數據存儲的分析,我們從計算機實現的角度來看就是只要滿足症狀規則表中規則表達式的值為真,那么就展示規則對應的結果。即計算(A1 && A2 && A3&& A4 && A5)表達式的真假。
2.2.1 調用說明
外圍系統調用規則引擎傳入參數為:sex=male&blood=weak&body=thin&waist=limp&menses=menoxenia,那么我們拿到這些參數和值后,傳入規則引擎,根據傳入參數編碼和值對比數據庫中存儲的編碼和值。可以得出:
A1=false A2=true A3=true A4=true A5=true
表達式(A1 && A2 && A3 && A4 && A5)計算結果為false,不展示結果;如果傳入參數中sex=female,那么A1=true,表達計算結果為true,則展示相應的結果。
2.2.2 表達式計算示例
importjavax.script.ScriptEngine; importjavax.script.ScriptEngineManager; publicclass TestExpress { public static void main(String[] args)throws Exception { String expr = "(A1 &&A2 && A3 && A4 && A5)"; ScriptEngineManager manager = newScriptEngineManager(); ScriptEngine engine =manager.getEngineByName("js"); engine.put("A1", true); engine.put("A2", true); engine.put("A3", true); engine.put("A4", true); engine.put("A5", true); Object result = engine.eval(expr); System.out.println(result); } }
總結
由於作者水平和認知有限,如有不對的地方請批評和指正。希望本文檔可以幫助到您,或者給您一些啟發.