十九、一套规则限制的校验

来源:互联网 发布:内核参数优化 编辑:程序博客网 时间:2024/06/05 10:52

首先在spring容器启动时加载所有规则校验类。

在SpringObjectCheckManagerFactory类的afterPropertiesSet()方法中进行加载。所有规则校验类都实现自ObjectCheck接口。


 

package com.taobao.member.prop.ao.check;import com.alibaba.common.logging.Logger;import com.alibaba.common.logging.LoggerFactory;import com.taobao.member.prop.ao.check.concreteObjectCheck.CheckForReceiveTime;import com.taobao.member.prop.ao.check.concreteObjectCheck.CheckForUseTime;import com.taobao.member.prop.ao.check.impl.ObjectCheckManagerImpl;import com.taobao.member.prop.timetask.PropTimerTask;import org.springframework.beans.BeansException;import org.springframework.beans.factory.FactoryBean;import org.springframework.beans.factory.InitializingBean;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;import java.util.Map;/** *  * @author zirou * */@Component("objectCheckManager")public class SpringObjectCheckManagerFactory implements InitializingBean, FactoryBean, ApplicationContextAware {private Logger logger = LoggerFactory.getLogger(SpringObjectCheckManagerFactory.class);private ApplicationContext context;public void setApplicationContext(ApplicationContext applicationContext)throws BeansException {this.context = applicationContext;}@Autowiredprivate ObjectCheckManagerImpl objectCheckManager;@Autowiredprivate PropTimerTask propTimerTask;public Object getObject() throws Exception {return objectCheckManager;}public Class<ObjectCheckManager> getObjectType() {return ObjectCheckManager.class;}public boolean isSingleton() {return true;}public void afterPropertiesSet() throws Exception {propTimerTask.start();Map<String, ObjectCheck> objectCheckListMap = objectCheckManager.getObjectCheckListMap();String[] objectCheckNames = context.getBeanNamesForType(ObjectCheck.class, true, false);//String[] getBeanNamesForType(Class type, boolean includePrototypes, boolean includeFactoryBeans);  if ((objectCheckNames != null) && (objectCheckNames.length > 0)) {            for (String objectCheckName : objectCheckNames) {                ObjectCheck objectCheck = (ObjectCheck) context.getBean(objectCheckName, ObjectCheck.class);                ObjectCheck objectCheckInMap = objectCheckListMap.get(objectCheck.getCheckName());                if (objectCheckInMap == null) {                    objectCheckListMap.put(objectCheck.getCheckName(), objectCheck);                }            }} else {logger.warn("No ObjectCheck is defined in the spring container");}objectCheckManager.setObjectCheckListMap(objectCheckListMap);//领取时间ObjectCheck checkForReceiveTime= objectCheckListMap.get("com.taobao.member.prop.ao.check.concreteObjectCheck.CheckForReceiveTime");Map<String, ConditionValue> receiveMap = ((CheckForReceiveTime) checkForReceiveTime).getConditionValueMap();String[] conditionValueNames = context.getBeanNamesForType(ConditionValue.class, true, false);  if ((conditionValueNames != null) && (conditionValueNames.length > 0)) {            for (String conditionValueName : conditionValueNames) {                ConditionValue conditionValue = (ConditionValue) context.getBean(conditionValueName, ConditionValue.class);                ConditionValue conditionValueInMap = receiveMap.get(conditionValue.getConditionValueName());                if (conditionValueInMap == null) {                    receiveMap.put(conditionValue.getConditionValueName(), conditionValue);                }            }} else {logger.warn("No ObjectCheck is defined in the spring container");}((CheckForReceiveTime) checkForReceiveTime).setConditionValueMap(receiveMap);//使用时间ObjectCheck checkForUseTime= objectCheckListMap.get("com.taobao.member.prop.ao.check.concreteObjectCheck.CheckForUseTime");Map<String, ConditionValue> useMap = ((CheckForUseTime) checkForUseTime).getConditionValueMap();if ((conditionValueNames != null) && (conditionValueNames.length > 0)) {            for (String conditionValueName : conditionValueNames) {                ConditionValue conditionValue = (ConditionValue) context.getBean(conditionValueName, ConditionValue.class);                ConditionValue conditionValueInMap = useMap.get(conditionValue.getConditionValueName());                if (conditionValueInMap == null) {                    useMap.put(conditionValue.getConditionValueName(), conditionValue);                }            }} else {logger.warn("No ObjectCheck is defined in the spring container");}((CheckForUseTime) checkForUseTime).setConditionValueMap(useMap);}}


 

    SpringObjectCheckManagerFactory类的afterPropertiesSet()方法首先通过String[] objectCheckNames = context.getBeanNamesForType(ObjectCheck.class, true, false);从applicationContext中取所有继承了ObjectCheck的校验类的名称,通过ObjectCheck objectCheck = (ObjectCheck) context.getBean(objectCheckName, ObjectCheck.class);取名称对应的类实例。然后将类名称和实例分别作为key和value,put到ObjectCheckManagerImpl的objectCheckListMap中。
    下面是ObjectCheck的一个实现类,特意选这个对使用时间进行校验的例子,是为了跟SpringObjectCheckManagerFactory中“使用时间”部分联系起来看,看看是如何仅在数据库中配置了类名却通过这个类的实例来进行使用时间的校验的。从上面已经put好的objectCheckListMap中取“使用时间”的类实例,再取它的conditionValueMap,将所有实现了ConditionValue接口的类都put进conditionValueMap,set回去。通过这样的方式,我们开发一个类,在数据库中一条记录里配置上全类名,就可以用其实例来进行校验了。

import com.taobao.member.domain.prop.TmallPropRuleConfineDO;import com.taobao.member.prop.ao.check.ConditionValue;import com.taobao.member.prop.ao.check.ObjectCheck;import com.taobao.member.prop.ao.check.ObjectCheckCodeConstant;import com.taobao.member.prop.ao.check.QueryRuleConfine;import com.taobao.member.prop.ao.ruleConfine.Branch;import com.taobao.member.prop.ao.ruleConfine.Node;import com.taobao.member.prop.ao.ruleConfine.RuleOperate;import com.taobao.member.service.prop.PropConstants;import org.springframework.stereotype.Component;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/** *  * @author zirou * */@Componentpublic class CheckForUseTime implements ObjectCheck<QueryRuleConfine>{Map<String,ConditionValue> conditionValueMap= new HashMap<String,ConditionValue>();public Map<String, ConditionValue> getConditionValueMap() {return conditionValueMap;}public void setConditionValueMap(Map<String, ConditionValue> conditionValueMap) {this.conditionValueMap = conditionValueMap;}@Overridepublic String check(QueryRuleConfine queryRuleConfine) {String result = ObjectCheckCodeConstant.OBJECT_CHECK_TRUE_CODE+":"+this.getCheckName();TmallPropRuleConfineDO memberPropRuleConfineDO = this.buildMemberCorrespondRule(queryRuleConfine);List<TmallPropRuleConfineDO> memberRuleTypeList = new ArrayList<TmallPropRuleConfineDO>();List<TmallPropRuleConfineDO> thisRuleTypeList = new ArrayList<TmallPropRuleConfineDO>();for(TmallPropRuleConfineDO tmallPropRuleConfineDO:queryRuleConfine.getUsePropRuleConfineList()){if(tmallPropRuleConfineDO.getRuleType()==PropConstants.PROP_RULE_CONFINE_RULE_TYPE_USE_TIME){if(tmallPropRuleConfineDO.getMemberLevel()==Integer.MIN_VALUE){//同一个propItemId的同一个rule_type下面,不可能同时存在有会员等级的和无等级的tmallPropRuleConfineDO.setMemberLevel(queryRuleConfine.getMemberLevel());}thisRuleTypeList.add(tmallPropRuleConfineDO);}}if(thisRuleTypeList.size()>0){Branch root = RuleOperate.createRuleTree(thisRuleTypeList);Node matchNode = RuleOperate.findContainsNode(root,memberPropRuleConfineDO);if(matchNode.getPosition()==2){ArrayList<Node> leafNodes = ((Branch)matchNode).getChildren();Map existPart = (Map) leafNodes.get(0).getValue();if(existPart.containsKey(PropConstants.PROP_RULE_CONFINE_CONDITION_KEY_TIME)){                    if(memberPropRuleConfineDO.getConditionValue()!=null && !"".equals(memberPropRuleConfineDO.getConditionValue())){ConditionValue conditionValue = conditionValueMap.get(memberPropRuleConfineDO.getConditionValue());boolean isSatisfy = conditionValue.isSatisfyTimeConfine(queryRuleConfine);if(isSatisfy){memberPropRuleConfineDO.setConditionKey(PropConstants.PROP_RULE_CONFINE_CONDITION_KEY_TIME);memberPropRuleConfineDO.setConditionValue(memberPropRuleConfineDO.getConditionValue());memberRuleTypeList.add(memberPropRuleConfineDO);}else{return "不满足使用的时间条件限制:"+this.getCheckName();}}}}else{return ObjectCheckCodeConstant.OBJECT_CHECK_FALSE_CODE+":"+this.getCheckName();}Branch rootDeleted = RuleOperate.deleteTree(root, memberRuleTypeList);boolean boo = RuleOperate.isAllEmptyLeaves(rootDeleted);if(!boo) {return ObjectCheckCodeConstant.OBJECT_CHECK_FALSE_CODE+":"+this.getCheckName();}}return result;}protected TmallPropRuleConfineDO buildMemberCorrespondRule(QueryRuleConfine queryRuleConfine) {TmallPropRuleConfineDO tmallPropRuleConfineDO = new TmallPropRuleConfineDO();tmallPropRuleConfineDO.setPropId(queryRuleConfine.getPropId());tmallPropRuleConfineDO.setPropItemId(queryRuleConfine.getPropItemId());tmallPropRuleConfineDO.setMemberLevel(queryRuleConfine.getMemberLevel());tmallPropRuleConfineDO.setRuleType(PropConstants.PROP_RULE_CONFINE_RULE_TYPE_USE_TIME);tmallPropRuleConfineDO.setConditionValue(queryRuleConfine.getUseTimeProcessorClassName());return tmallPropRuleConfineDO;}@Overridepublic int getBizType() {return PropConstants.PROP_RULE_CONFINE_RULE_TYPE_USE_TIME;}@Overridepublic String getCheckName() {return CheckForUseTime.class.getName();}} 

        到此时,我们已经将所有校验的规则加载起来了,在使用时通过调用propManager的isSatisfyRuleConfine(queryRuleConfine, PropConstants.BIZ_TYPE_RECEIVE);方法进行校验。propManager调用objectCheckService的check(queryRuleConfine, bizType);方法。

import com.alibaba.common.logging.Logger;import com.alibaba.common.logging.LoggerFactory;import com.taobao.member.exception.MemberException;import com.taobao.member.prop.ao.check.ObjectCheck;import com.taobao.member.prop.ao.check.ObjectCheckCodeConstant;import com.taobao.member.prop.ao.check.ObjectCheckManager;import com.taobao.member.prop.ao.check.ObjectCheckService;import com.taobao.member.service.prop.PropConstants;import org.springframework.beans.factory.InitializingBean;import org.springframework.stereotype.Component;import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** *  * @author zirou * */@Component("objectCheckServiceImpl")public class ObjectCheckServiceImpl implements ObjectCheckService,InitializingBean {private Logger logger = LoggerFactory.getLogger(ObjectCheckServiceImpl.class);private ObjectCheckManager objectCheckManager;public void setObjectCheckManager(ObjectCheckManager objectCheckManager) {this.objectCheckManager = objectCheckManager;}private ExecutorService executorService;public void afterPropertiesSet() throws Exception {init();}public void init() {executorService = Executors.newCachedThreadPool();}@Overridepublic List<String> check(Object obj, int bizType) {List<String> featureResult = Collections.synchronizedList(new ArrayList<String>());List<ObjectCheck> objCheckList = objectCheckManager.getObjectCheckListByObject(obj);// 组装需要工作的对象检查器List<ObjectCheck> objCheckWorkList = new ArrayList<ObjectCheck>();if (objCheckList != null && objCheckList.size()>0) {if(PropConstants.ALL_BIZ_TYPE == bizType){objCheckWorkList = objCheckList;}else if(PropConstants.BIZ_TYPE_RECEIVE == bizType){for (ObjectCheck objectCheck : objCheckList) {if (PropConstants.ALL_BIZ_TYPE<=objectCheck.getBizType() && objectCheck.getBizType()<=PropConstants.BIZ_TYPE_RECEIVE) {objCheckWorkList.add(objectCheck);}}}else if(PropConstants.BIZ_TYPE_USE == bizType){for (ObjectCheck objectCheck : objCheckList) {if (PropConstants.ALL_BIZ_TYPE>=objectCheck.getBizType() && objectCheck.getBizType()>=PropConstants.BIZ_TYPE_USE) {objCheckWorkList.add(objectCheck);}}}else{for (ObjectCheck objectCheck : objCheckList) {if (bizType == objectCheck.getBizType() || PropConstants.ALL_BIZ_TYPE == bizType || PropConstants.ALL_BIZ_TYPE == objectCheck.getBizType()) {objCheckWorkList.add(objectCheck);}}}}if (objCheckWorkList.size() > 0) {CountDownLatch doneSignal = new CountDownLatch(objCheckWorkList.size());for (ObjectCheck objCheck : objCheckWorkList){executorService.execute(new WorkerRunnable(doneSignal, objCheck, featureResult, obj));// create and start threads}try {doneSignal.await();} catch (InterruptedException e) {logger.error("object_check_time_out_error,the obj className is {"+ obj.getClass().getName() + "}");featureResult.add(ObjectCheckCodeConstant.OBJECT_CHECK_TIME_OUT_ERROR_CODE);throw new MemberException(e);}}return featureResult;}class WorkerRunnable implements Runnable {private final CountDownLatch doneSignal;private final ObjectCheck objectCheck;private final List<String> featureResult;private final Object obj;WorkerRunnable(CountDownLatch doneSignal, ObjectCheck objectCheck,List<String> featureResult, Object obj) {this.doneSignal = doneSignal;this.objectCheck = objectCheck;this.featureResult = featureResult;this.obj = obj;}public void run() {String result = doWork(objectCheck);featureResult.add(result);doneSignal.countDown();}String doWork(ObjectCheck objectCheck) {String result = ObjectCheckCodeConstant.NONE_DEFINED_OBJECT_CHECK_ERROR_CODE;try {result = objectCheck.check(obj);} catch (Exception e) {logger.error("objCheck throw Exception ,the obj's className is {"+ obj.getClass().getName() + "} and "+ "the objectCheck class is {"+ objectCheck.getClass().getName() + "}", e);}return result;}}}

        check方法首先取已经初始化好的objectCheckManagerImpl的objectCheckListMap,根据是领取还是使用,从这个objectCheckListMap过滤出校验的规则限制列表,对其中的每条规则校验通过从线程池中取到的某线程进行校验。