https://www.jianshu.com/p/725811f420db
深入了解Drools
简单介绍
笔者正在做风控系统,风控系统里边存在非常多的规则(比如:age < 16 || age > 50 -> REJECT )。最便捷的实现就是用 if-else 来写,但是随着规则的增加以及需求的变动,代码将变得越来越难阅读和变动。这时候就要引入Drools等规则引擎了。Drools就是为了解决业务代码和业务规则分离的引擎。
开发环境搭建
网上一般都是eclipse下的教程,这里讲下intellij下的教程。
- 安装JBoss Drools Support插件。主要是为了intellij可以识别drools文件,使用快捷的智能提示。
- 下载依赖jar (https://download.jboss.org/drools/release/7.3.0.Final/droolsjbpm-tools-distribution-7.3.0.Final.zip)
好了,就这么点步骤,就是如此简单。
Hello Drools
下面立马上手Hello Drools。实现需求:判断一个人的 age < 16 || age > 50 的时候,打印年龄不符合要求。
- 建立工程
就是典型的maven工程,除外需要做以下事情:
- 导入drools有关jar包。就是droolsjbpm-tools-distribution-7.3.0.Final.zip解压出来后的binaries下的jar包。
- 新建配置文件/src/resources/META-INF/kmodule.xml
- 新建drools规则文件/src/resources/rules/age.drl
工程搭建完毕,效果如图:
- 开始编写代码
- kmodule.xml
<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <kbase name="specialerrorDrl" packages="rules"> <ksession name="spacialerrorSession"/> </kbase> </kmodule>
packages:指定drl文件的目录
SpecialErrorHandle.java
其中flag,用来判断解析后传进来的text,与需要对比的数据是否相等
public boolean flag() {
return StringUtils.equals(text, StringUtils.deleteWhitespace(equalStr));
}
public class SpecialErrorHandle { /**解析text*/ private String text; /**对比的数据**/ private String equalStr; /**返回错误码**/ private String code; /**提示数据**/ private String tips; private boolean flag; public SpecialErrorHandle(String text, String equalStr, String tips){ this.text = text; this.equalStr = equalStr; this.tips = tips; } public SpecialErrorHandle(String text, String equalStr, String code, String tips){ this.text = text; this.equalStr = equalStr; this.code = code; this.tips = tips; } public String getText() { return text; } public void setText(String text) { this.text = text; } public String getEqualStr() { return equalStr; } public void setEqualStr(String equalStr) { this.equalStr = equalStr; } public String getTips() { return tips; } public void setTips(String tips) { this.tips = tips; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public boolean flag() { return StringUtils.equals(text, StringUtils.deleteWhitespace(equalStr)); } public void setFlag(boolean flag) { this.flag = flag; } }
规则库drl文件:specialErrorHandle.drl
import common.tribe.error.SpecialErrorHandle; import common.exception.ServiceException; rule "specialErrorHandl" when $specialErrorHandle : SpecialErrorHandle(flag == true) then throw new ServiceException($specialErrorHandle.getTips(), $specialErrorHandle.getCode()); end
其中:ServiceException,是异常错误抛出类,
ServiceException.java
/** * 服务异常 */ public class ServiceException extends RuntimeException { private static final long serialVersionUID = 2956071387027987098L; private String msg; // 通用错误为-1,其他错误应该有编码 private String code = "-1"; public ServiceException(String msg) { super(msg); this.msg = msg; } public ServiceException(String msg, Throwable e) { super(msg, e); this.msg = msg; } public ServiceException(String msg, String code) { super(msg); this.msg = msg; this.code = code; } public ServiceException(String msg, String code, Throwable e) { super(msg, e); this.msg = msg; this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } }
OK .就这么点代码,记住将各种资源文件设为resources(右键可以设置你懂的,不然运行会报各种空指针)。现在用junit 测试下:
public String test() { String methodStr = "CreateProfileForm"; String resultJson = "{"SplashPage":{"PageInfo":{"Locale":"zh_CN","ReadOnly":"false","CurrencyRoundTo":"1","ConversationID":"OJ1548071788914","UserIP":"60.174.206.71","skin":"hainan","SessionPageRandom":"","LayoutType":"","NavSelect":"","Language":"zh","FromServicing":"false","POS":{"CompanyCode":""},"Currency":"CNY","SessionID":"CD8BFD11D1AFA6D27375EAF307CB59F5.TVIBEServer4"},"CreateSessionForm":{"LanguageInput":{"name":"language","type":"list","value":"zh"},"method":"post","RemoveLowPriceCacheQueryInput":{"name":"removeLowPriceCacheQuery","type":"fixed","value":"false"},"TestModeInput":{"name":"testMode","type":"fixed","value":"A"},"name":"CreateSessionForm","action":"/common/homeRedirect.do","RedirectedInput":{"name":"redirected","type":"fixed","value":"true"},"MarketInput":{"name":"market","type":"list","value":"CN"},"ChannelInput":{"name":"channel","type":"fixed","value":"IBE"},"RequestorIDInput":{"name":"requestorID","Error":{"Param":[{"_text":"Unauthorised RequestorID"}],"Validator":"Error"},"type":"fixed","value":"IBE"},"ShowLowPriceAirLineNumInput":{"name":"showLowPriceAirLineNum","type":"fixed","value":""}}}}"; // 处理一般错误 if (resultJson.contains("Error")) { List<String> errorStrList = TribeCheckErrorUtils.checkedError(methodStr, resultJson); if (errorStrList != null && errorStrList.size() > 0) { String shortDiscription = ""; for (String str : errorStrList) { shortDiscription = TribeCheckErrorUtils.getValidator(str); handleSpecialError(str, shortDiscription); } throw new ServiceException("内部服务发生错误", shortDiscription); } } return "test"; } private void handleSpecialError(String specialErrorMessage, String shortDiscription){ String _text = ""; if (org.apache.commons.lang.StringUtils.equals(shortDiscription, "Error") && org.apache.commons.lang.StringUtils.startsWith(specialErrorMessage, "{")) { JSONObject parseObject = JSONObject.parseObject(specialErrorMessage); if (parseObject.containsKey("Param") && parseObject.get("Param") instanceof JSONArray) { Object object = ((JSONArray) parseObject.get("Param")).get(0); if (object instanceof JSONObject && ((JSONObject) object).containsKey("_text")) { _text = ((JSONObject) object).getString("_text"); } } } if(org.apache.commons.lang.StringUtils.isNotEmpty(_text)) { KieServices kieServices = KieServices.Factory.get(); KieContainer kieContainer = kieServices.getKieClasspathContainer(); KieSession kieSession = kieContainer.newKieSession("spacialerrorSession"); SpecialErrorHandle errorHandle = new SpecialErrorHandle(_text, "Unauthorised RequestorID", "您的账户已被禁用,请联系客服进行处理!" ); kieSession.insert(errorHandle); kieSession.fireAllRules(); kieSession.dispose(); } }