當某個服務的需求經常變的時候,如果使用了硬編碼的方式進行開發會是一件非常麻煩的事。
最近在對項目的積分模塊進行改造的時候想到了規則引擎,使用規則引擎處理復雜而且多變的業務邏輯有其非常大的優勢,包括實時更新、性能等方面。
不多說,直接上代碼:
1、第一步先寫好工具類,有了工具類,只需在應用的業務場景中調用相應方法就可以了
@Component public class KieSessionUtils { private static KieBase kieBase; //定義規則文件的包名,與drl文件里的package對應 private static final String drlPackage = "rules"; //定義drl文件的存放路徑,靜態變量需要通過在其set方法上打@Value注解,才可實現配置注入 private static String drlPath; //通過配置拉取路徑,這里推薦一下apollo配置中心,使用apollo可以實時更改通過@Value拉取的配置 @Value("${drools.points.drlPath}") public void setDrlPath(String drlPath){ KieSessionUtils.drlPath = drlPath; } /** * 生成kieSeesion會話 * @param ruleName * @return * @throws Exception */ public static KieSession newKieSession(String ruleName) throws Exception { //無狀態的kieSession,和有狀態相比,區別在於不維持會話,即使用完后自動釋放資源,不需要手動調dispose //StatelessKieSession kieSession = getKieBase(ruleName).newStatelessKieSession(); //有狀態的kieSession KieSession kieSession = getKieBase(ruleName).newKieSession(); //添加監聽器,這里加的是對規則文件運行debug監聽器,測試時最好加上,用於排查問題,生產上可視情況去掉 kieSession.addEventListener(new DebugRuleRuntimeEventListener()); return kieSession; } /** * 生成kieBase * @param ruleName 規則文件名 * @return * @throws Exception */ protected static KieBase getKieBase(String ruleName) throws Exception { //判斷kieBase和需要獲取的規則文件是否存在,不存在則重新初始化kieBase if (kieBase ==null || kieBase.getRule(drlPackage,ruleName)==null) { KieServices kieServices = KieServices.Factory.get(); KieFileSystem kfs = kieServices.newKieFileSystem(); //獲取規則數據源,這里由於本人項目使用的是springboot,打包會打成jar包,如果想做實時更新,drl文件需要放在jar包外面 //獲取resource的方式很多,不一定要用讀取文件的方式,可根據自己的設計和業務場景采取不同方案 Resource resource = kieServices.getResources().newFileSystemResource(new File(drlPath+"/"+ruleName)); resource.setResourceType(ResourceType.DRL); kfs.write(resource); KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll(); if (kieBuilder.getResults().getMessages(Message.Level.ERROR).size() > 0) { throw new Exception(); } KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId()); kieBase = kieContainer.getKieBase(); } return kieBase; } /** * 更新規則 * @param ruleName 規則名和規則文件名 * @throws Exception */ public static void refreshRules(String ruleName) throws Exception { //判斷規則不為null,則移除規則 if (kieBase !=null && kieBase.getRule(drlPackage,ruleName)!=null){ //為了方便,本人把規則名和drl文件名稱統一定義了 kieBase.removeRule(drlPackage,ruleName); //重新初始化kieBase getKieBase(ruleName); } } }
2、編寫規則文件,這里只給出和規則引擎格式有關的代碼
package rules; //包名 import com.jiuair.dto.AddObject import java.util.List import java.util.HashMap import java.util.Map import java.util.ArrayList import java.util.Date import java.util.Iterator import java.util.Set global com.demo.dto.AddObject addObject //傳入的對象,同時也是返回值對象 rule "add.drl" //規則名,為了方便,設為何drl文件名一樣,可以不一樣 when $s : AddObject(); then 。。。。。//這一段加自己業務代碼邏輯,支持jdk $s.setResult(X); //執行完邏輯后將結果設置到對象中 end
3、在業務場景中調用工具類里的方法
private AddObject executeAddRule(Object data) { AddObject addObject = new AddObject(); addObject.setJsonObject(data); try { //獲取會話 KieSession kieSession = KieSessionUtils.newKieSession("add.drl"); //設置傳入參數 kieSession.insert(addObject); //設置全局參數 kieSession.setGlobal("addObject",addObject); //執行規則 kieSession.fireAllRules(); //釋放會話資源 kieSession.dispose(); } catch (Exception e) { e.printStackTrace(); } return addObject; }
4、實現實時更新drl文件
/** * 更新規則文件,這里只給出service層的代碼了,相信controller大家都會寫。。。 * @param name 名稱為drl的文件名 * @param is 由於dubbo不支持流的方式傳輸,文件需在controller轉為byte數組,再傳到service */ @Override public void refreshRule(String name, byte[] is) { try { FileOutputStream fos = new FileOutputStream(drlPath+"/"+name); fos.write(is); fos.close(); KieSessionUtils.refreshRules(name); } catch (Exception e) { e.printStackTrace(); } }
附maven引包:
<properties> <runtime.version>7.20.0.Final</runtime.version> </properties> <dependency> <groupId>org.kie</groupId> <artifactId>kie-api</artifactId> <version>${runtime.version}</version> </dependency> <dependency> <groupId>org.kie</groupId> <artifactId>kie-internal</artifactId> <version>${runtime.version}</version> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artifactId> <version>${runtime.version}</version> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-decisiontables</artifactId> <version>${runtime.version}</version> </dependency>
沒有英漢互譯結果
請嘗試網頁搜索
請嘗試網頁搜索