zoukankan      html  css  js  c++  java
  • 规则引擎 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();
    		}
    	}
    

      

  • 相关阅读:
    04: Dom
    03: JavaScript基础
    02: css常用属性
    01: html常用标签
    03: Memcached
    01: Redis缓存系统
    01: RabbitMQ
    04: 事件驱动、五种I/O操作、I/O多路复用select和epoll
    03: 进程、线程、协程
    [Android] 任意时刻从子线程切换到主线程的实现
  • 原文地址:https://www.cnblogs.com/achengmu/p/10601510.html
Copyright © 2011-2022 走看看