规则引擎 drools

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工程,除外需要做以下事情:
  1. 导入drools有关jar包。就是droolsjbpm-tools-distribution-7.3.0.Final.zip解压出来后的binaries下的jar包。
  2. 新建配置文件/src/resources/META-INF/kmodule.xml
  3. 新建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();
		}
	}

  

 

 

 

 

 

posted @ 2019-03-26 17:23  穆晟铭  阅读(2215)  评论(0编辑  收藏  举报