规则引擎

在招商报名系统中,需要对店铺和商品的资质进行筛选。这个筛选过程比较复杂,因此开发了一个规则引擎来保存、解析和执行规则。

在规则引擎中,有几个主要的抽象模型:规则、操作符、执行引擎

1. 规则

在规则引擎中,规则是树状结构的,由一个根节点和若干个子节点组成。对应的java类是Rule,该类的属性有:ruleDO(RuleDO),parent(Rule),children(List<Rule>)。

Rule类主要保存的是规则树的结构信息,具体的规则节点信息保存在RuleDO类中。

RuleDO中保存的主要信息有:规则ID,规则组ID(同一个规则树的节点属于一个规则组),父节点ID,左参数,右参数,操作符。

当规则引擎执行时,获取RuleDO对象,根据操作符获取具体的操作符对象并执行。左参数是变量,需要通过其他接口获取的值,一般和店铺或商品有关。右变量是固定的,在活动创建时选择的规则的值。

2. 操作符

操作符是规则是否满足的判断行为的抽象。在招商系统中,目前有10个操作符:And, Or, BitAnd, Between, Equal, In, InCategory, InTag, ItemCatBetween, Not。

这10个操作符可以分为两种类型:原子操作符和非原子操作符。原子操作符指不需要任何子规则计算的,它直接对左参数和右参数进行计算。非原子操作符是指他本身没有左参数和右参数,而是对子规则的计算结果进行计算。

原子操作符:BitAnd, Between, Equal, InCategory, InTag, ItemCatBetween, In。

非原子操作符:And, Or, Not

And 要把Rule对象中的子规则都执行一遍,才返回true

Or 只要Rule对象中子规则中有一个执行通过,就返回true

原子操作符是对直接对数据做判定的。其中左参数是变量,右参数是常量。右参数是小二设置的,左参数需要系统动态获取。这其中涉及到了左参数的数据来源问题。每一个左参数都需要有一个明确的数据来源,在报名系统中,定义在fact.xml中。每一个可用的左参数都对应一个factId,tmc_rule中left_param记录的就是这个factId。

在fact.xml中,定义了左参数的元数据。包括id,dataType, getMethod,parameters。

getMethod定义了数据获取方式,包括两个部分:接口变量名和方法名。在执行引擎的执行session中会持有外部接口的实例,getMethod的前半部分记录的就是这个实例的变量名,getMethod的另外一部分是方法名称。

parameters定义的是调用外部接口需要的参数。包括类型、来源和值。来源有三个:context,static, rightParam。

组合使用getMethod和parameters,根据变量名拿到变量实例,获取Class信息,通过反射拿到Method,通过Parameter从上下文、静态变量或者是右参数拿到方法的参数值,通过反射执行方法,拿到最终的左参数的变量值。反射的两个类为sellerPropertiesManager和itemPropertiesManager

3. 执行引擎

RuleExecutor是规则引擎对外的接口

ExecuteResult execute(Rule rule,ExecuteSession fact); 

这个接口可以执行单个的规则,也可以执行一组规则。

ExecuteSession对象来保存规则执行需要使用的上下文信息,包括上下文参数,以及需要使用的接口实例:

 

private RuleExecutor ruleExecutor; //规则执行入口

private RuleManager ruleManager; //规则获取入口,ibatis,获取几种操作符的规则数,有的组织关系,有的直接操作数据

private FactManager factManager; //用户元数据获取配置

private SellerPropertiesManager sellerPropertiesManager;//通过用户元数据获取时,反射method调用入口

private ItemPropertiesManager itemPropertiesManager;//通过商品元数据获取时,反射method调用入口

private ExecutorThreadPool executorThreadPool;//规则执行线程池

private static final Logger logger = LoggerFactory.getLogger(RuleExecuteServiceImpl.class);


itemPropertiesManager、sellerPropertiesManager、factManager。 

类图如下:

招商平台规则和规则树的对应关系

bm_qualification表中的规则为了前台规则展示用的,一条对应一行。

bm_qualification表中的ruleid 对应前台一条展示的规则树的根。

然后通过根可以在tmc_rule里面找到整个规则数

一般查询方式为:

    select * from  bm_qualification where baoming_config_id=9658

找到某一条rule_id为119100

在到taobao_heart库tmc_rule中找 select * from tmc_rule where rule_id= 119100
 select * from tmc_rule where group_id=119100得到整棵规则数

 

使用到的设计模式:

1.工厂模式,执行到规则的时候,获取操作符,通过操作符工厂生产

 

 

使用反射的地方

 

private  Object reflect(String className,String methodName,ExecuteSession session,List<Parameter> parameters)throws Exception{

Class<?> clazz = session.getPropertiesManager(className).getClass();

Class<?>[] parameterClass = new Class<?>[parameters.size()];

for (int i = 0; i < parameters.size(); i++) {

parameterClass[i] = parameters.get(i).getType();

}

Method method = clazz.getMethod(methodName, parameterClass);

Object[] objects = new Object[parameters.size()];

for (int i = 0; i < parameters.size(); i++) {

Parameter parameter = parameters.get(i);

Object value = getValue(parameter, session.getContext());

objects[i] = value;

}

Object result = method.invoke(session.getPropertiesManager(className), objects);

return result;

}

你可能感兴趣的:(规则引擎)