报文消息校验

来源:互联网 发布:淘宝客服常遇到的问题 编辑:程序博客网 时间:2024/06/05 10:04

1、web.xml中配置校验文件、校验监听器等信息:

    <!-- 加载spring配置文件的路径 -->
    <context-param>
        <param-name>dhm-system-name</param-name>
        <param-value>portalMS</param-value>
    </context-param>
    <context-param>
        <param-name>system.config-path-name</param-name>
        <param-value>conf</param-value>
    </context-param>


    <listener>
        <listener-class>com.xxxx.miss.util.linstener.InitSerListener</listener-class>
    </listener>

2、启动tomcat容器时 进入InitSerListener读取校验文件信息放到Map中,报文中的字段与map中信息进行校验完成校验任务:

package com.xxxxxx.miss.util.linstener;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.xxxxxx.dhm.aaa.commons.util.Utility;
import com.xxxxxx.miss.util.config.CheckField;
import com.xxxxxx.miss.util.config.CheckRulerConfig;
import com.xxxxxx.miss.util.config.FieldRuler;
import com.xxxxxx.miss.util.config.InterRulerConfig;
import com.xxxxxx.miss.util.config.JoinFiledRuler;
import com.xxxxxx.miss.util.config.SerFactory;

/**
 * service层的初始化listener
 * SerListener.java
 * <p>Copyright: Copyright (c) 2009 <p>
 * <p>Company: xxxxxx</p>
 *  @author   
 *  @version   1.0
 */
public class InitSerListener implements ServletContextListener
{
    Logger logger = Logger.getLogger(InitSerListener.class);

    public void contextDestroyed(ServletContextEvent context)
    {
    }

    public void contextInitialized(ServletContextEvent context)
    {
        // 初始化参数校验配置
        this.initParaCheckConfig(context);
    }

    // 使用dom4j进行xml的解析
    @SuppressWarnings( { "unchecked", "unchecked" })
    private void initParaCheckConfig(ServletContextEvent context)
    {
        SAXReader saxReader = new SAXReader();
        String checkConfigPath = context.getServletContext().getInitParameter("checkConfigFilePath");
        String aaa_system_name = context.getServletContext().getInitParameter("dhm-system-name");
        String path = Utility.getConfigFullPath(checkConfigPath, aaa_system_name);
        try
        {
            Document document = saxReader.read(new File(path));
            Element root = document.getRootElement();
            Iterator iter = root.elementIterator();
            CheckRulerConfig crc = new CheckRulerConfig();
            Map mc = crc.getIRuleMap();
            while (iter.hasNext())
            {
                Element ie = (Element) iter.next();
                Iterator it = ie.elementIterator();
                InterRulerConfig irc = new InterRulerConfig();
               
                // 如果存在ref项就取出来
                if (ie.attributeValue("ref") != null)
                {
                    irc.setRef(ie.attributeValue("ref"));
                }

                Map mi = irc.getFRuleMap();
                while (it.hasNext())
                {
                    Element fe = (Element) it.next();
                    FieldRuler fr = new FieldRuler();

                    fr.setId(fe.attributeValue("id").toLowerCase());
                    fr.setRegex(fe.attributeValue("regex"));
                    fr.setNeed(fe.attributeValue("need"));
                    fr.setType(fe.attributeValue("type"));
                    fr.setMaxLength(fe.attributeValue("maxLength"));
                    Iterator it1 = fe.elementIterator();
                    while (it1.hasNext())
                    {
                        JoinFiledRuler joinRule = new JoinFiledRuler();
                        Map<String, CheckField> resultMap = new HashMap<String, CheckField>();
                        Element fe1 = (Element) it1.next();
                        buildJoinFiledFuler(fe1, resultMap);
                        joinRule.setJoinCheck(resultMap);
                        fr.setJoinCheckFiled(joinRule);
                    }
                    mi.put(fr.getId().toLowerCase(), fr);
                    logger.debug(fr);

                }
                mc.put(ie.attributeValue("id"), irc);
            }
            SerFactory.setCheckConfig(crc);
        }
        catch (Exception e)
        {
            logger.error("load check ruler file failed!", e);
        }

    }

    /**
     * 解析joinCheck元素下值
     * @param fe1
     * @return
     */
    @SuppressWarnings("unchecked")
    private static void buildJoinFiledFuler(Element fe1, Map<String, CheckField> resultMap)
    {

        Iterator it1 = fe1.elementIterator();
        while (it1.hasNext())
        {

            Element fe3 = (Element) it1.next();
            Iterator it2 = fe3.elementIterator();
            while (it2.hasNext())
            {
                CheckField checkField = new CheckField();
                Element fe4 = (Element) it2.next();
                checkField.setRefField(fe4.attributeValue("refField"));
                checkField.setRegex(fe4.attributeValue("regex"));
                checkField.setMaxLength(fe4.attributeValue("maxLength"));
                resultMap.put(fe3.attributeValue("value"), checkField);
            }
        }

    }

}

4、配置文件para_check_config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ruleConfig>

        <!-- SP状态变更信息同步 -->
    <interface id="interRuler.SyncProviderStatusServiceImpl">
        <field id="spid" regex="^[0-9]{1,13}" need="no" maxLength="10"/>
        <field id="spcode" regex="^[a-zA-Z0-9_]*$" need="yes" maxLength="16"/>
        <field id="status" regex="^[0-9]{1,13}$" need="yes" maxLength="2"/>
        <field id="CityCode" regex="^[0-9]{1,13}" need="no" maxLength="10"/>        
    </interface>

</ruleConfig>

5、报文:

<?xml version="1.0" encoding="UTF-8"?>
<message><header>
  <TransactionID>17</TransactionID>
  <Timestamp>2013-09-02 13:42:31</Timestamp>
  <OpCode>SME_UPDATE_SP_STATUS</OpCode>
  <MsgType>REQ</MsgType>
  <Version>1.0</Version>
</header><body>
  <SP>
    <SPCode>test_SP01</SPCode>
    <Status>0</Status>
    <CityCode>100000</CityCode>
  </SP>
</body></message>

6、httpclient-6.0 发送报文被 ServiceParaCheckInterceptor拦截进行校验:

applicationcontext-datasource.xml:

<bean id="serviceParaCheckInterceptor"
        class="com.xxxxxx.miss.util.intercaptor.ServiceParaCheckInterceptor">
    </bean>
    
    <bean id="RegexAdvisor"
        class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <property name="advice">
            <ref local="serviceParaCheckInterceptor" />
        </property>
        <property name="patterns">
            <list>
                <value>com.xxxxxx.dhm.portalMS.sync.portalms.service.*\.execute</value>
                <value>com.xxxxxx.dhm.portalMS.sync.service.*\.execute</value>
                <value>com.xxxxxx.dhm.portalMS.sync.action.*\.execute</value>
                <value>com.xxxxxx.dhm.portalMS.sync.cms.*\.execute</value>
                <value>com.xxxxxx.dhm.portalMS.sync.sme.*\.execute</value>
            </list>
        </property>
    </bean>
    
    <bean id="paraCheckAop"
        class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
            <list>
                
                <value>SyncProviderStatusServiceImpl</value>
            </list>
        </property>
        <property name="interceptorNames">
            <list>
                <value>serviceParaCheckInterceptor</value>
            </list>
        </property>
    </bean>


package com.xxxxxx.miss.util.intercaptor;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;

import com.xxxxxx.dhm.aaa.commons.constant.CommonConst;
import com.xxxxxx.dhm.aaa.commons.constant.SerErrorCommonCode;
import com.xxxxxx.dhm.aaa.commons.util.StringUtil;
import com.xxxxxx.miss.util.config.CheckField;
import com.xxxxxx.miss.util.config.CheckRulerConfig;
import com.xxxxxx.miss.util.config.FieldRuler;
import com.xxxxxx.miss.util.config.InterRulerConfig;
import com.xxxxxx.miss.util.config.JoinFiledRuler;
import com.xxxxxx.miss.util.config.SerFactory;
import com.xxxxxx.dhm.common.config.impl.PropertiesFactory;
import com.xxxxxx.dhm.common.uif.vo.IRequestMessageBody;
import com.xxxxxx.dhm.common.uif.vo.MessageBody;
import com.xxxxxx.dhm.common.uif.vo.ReturnMessage;
import com.xxxxxx.dhm.common.uif.vo.cms.CMSMessage;
import com.xxxxxx.dhm.common.uif.vo.cms.cms2iepg.body.IepgAssetRequestBody;

/**
 * 参数较验拦截器 ServiceParaCheckInterceptor.java
 * <p>
 * Copyright: Copyright (c) 2009
 * <p>
 * <p>
 * Company: xxxxxx
 * </p>
 *
 * @author
 * @version 1.0
 */
public class ServiceParaCheckInterceptor implements MethodInterceptor
{
    private final static Logger log = Logger.getLogger(ServiceParaCheckInterceptor.class);

    @SuppressWarnings("unchecked")
    public Object invoke(MethodInvocation invocation) throws Throwable
    {
        try
        {
            // 取出被拦截方法的参数集
            Object[] args = invocation.getArguments();
            Object o = null;
            if (args[0] instanceof IRequestMessageBody)
            {
                IRequestMessageBody dr = (IRequestMessageBody) args[0];
                // 取出要校验的对象
                o = dr.getReqMsg();
            }
            else if (args[0] instanceof MessageBody)
            {
                o = args[0];
            }
            
            
//            if (o == null && args[0] instanceof IepgAssetRequestBody)
//            {
//                IepgAssetRequestBody dr = (IepgAssetRequestBody) args[0];
//                o = dr.getResourcePackage();
//                if(o == null)
//                {
//                    o= dr.getPackageCode();
//                }
//                if(o == null)
//                {
//                    o= dr.getIepgAssetMessage();
//                }
//            }
            else
            {// 对象格式有误
                log.error(" object format error ");
                ReturnMessage rm = new ReturnMessage();
                rm.setReturnCode(SerErrorCommonCode.UNKNOWN_ERROR);
                return rm;
            }

            Class c = o.getClass();
            
            // 取出接口参数的字段集
            Field[] fa = c.getDeclaredFields();
            
            // 由接口ID取出此接口对应的InterRulerConfig对象
            CheckRulerConfig crc = SerFactory.getCheckConfig();
           
            // 取出接口规则Map
            Map<String, InterRulerConfig> iRuleMap = crc.getIRuleMap();
           
            // 取出被拦截的类名
            Class clazz = invocation.getThis().getClass();
            String rulerName = clazz.getSimpleName();
            String interID = CommonConst.INTER_RULER_PREFIX + rulerName;
           
            // 由接口ID取出接口的校验规则
            InterRulerConfig ir = iRuleMap.get(interID);

            // 如果此接口没有定义校验规则,则不对此接口进行校验
            if (ir == null)
            {
                return invocation.proceed();
            }
           
            // 如果此接口规则引用其他接口的规则进行校验,就取出引用的接口规则
            if (!ir.getRef().equals(""))
            {
                ir = iRuleMap.get(ir.getRef());
            }
           
            // 取出字段校验规则的map
            Map<String, FieldRuler> rulerMap = ir.getFRuleMap();
            for (int i = 0; i < fa.length; i++)
            {
                // 取校验规则
                FieldRuler fr = rulerMap.get(fa[i].getName().toLowerCase());
              
                // 如果此字段没有给出校验规则,则不对此字段进行校验
                if (fr == null)
                {
                    continue;
                }
                Method method = c.getMethod(getMethodName(fa[i].getName()), new Class[0]);
                Object fo = method.invoke(o, new Object[0]);// get方法无参\
               
                // 类里的属性是否为ArrayList类型
                if (fr.getType() != null && fr.getType().equals("list") && null != fo)
                {
                    List tempList = (ArrayList) fo;
                   
                    // 验证List下的元素属性
                    for (int temp = 0; temp < tempList.size(); temp++)
                    {
                        ReturnMessage validataResult = validataChildFiled(tempList.get(temp), rulerMap, o);
                      
                        // 验证失败
                        if (!SerErrorCommonCode.SUCCEED.equals(validataResult.getReturnCode()))
                        {
                            return validataResult;
                        }
                    }
                }
               
                // 验证属性
                ReturnMessage rm = checkField(fa[i].getName().toLowerCase(), rulerMap, fo, o);
                if (!SerErrorCommonCode.SUCCEED.equals(rm.getReturnCode()))
                {
                    return rm;
                }

            }

        }
        catch (Exception e)
        {
            log.error("parameter check failed!", e);
            ReturnMessage rm = new ReturnMessage();
            rm.setReturnCode(SerErrorCommonCode.PARA_CHECK_FAILED);
            rm.setErrorMessage(PropertiesFactory.getValueString(SerErrorCommonCode.PARA_CHECK_FAILED));
            return rm;
        }
        // 如果参数校验通过,则调用被拦截的方法
        return invocation.proceed();

    }

    /**
     * 根据校验规则对属性值进行检查
     *
     * @param lowerCaseValue
     * @param rulerMap
     * @param fo
     * @return
     * @throws NoSuchMethodException
     * @throws SecurityException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     */
    private ReturnMessage checkField(String lowerCaseValue, Map<String, FieldRuler> rulerMap, Object fo, Object o)
            throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException,
            InvocationTargetException
    {
        ReturnMessage rm = new ReturnMessage();
        rm.setReturnCode(SerErrorCommonCode.SUCCEED);
        FieldRuler fr = rulerMap.get(lowerCaseValue);
        // 如果此字段没有给出校验规则,则不对此字段进行校验
        if (fr == null)
        {
            return rm;
        }
        // 如果要校验的字段值为空,而校验规则规定其是必选项,则返回校验失败
        if (fo == null || fo.toString().equals(""))
        {
            if (fr.getNeed().equalsIgnoreCase(CommonConst.YES))
            {

                rm.setReturnCode(SerErrorCommonCode.PARA_CHECK_FAILED);
                rm.setErrorMessage(PropertiesFactory.getValueString(SerErrorCommonCode.PARA_CHECK_FAILED)
                        + CommonConst.ERROR_DESC + fr.getId());
                return rm;
            }
            else
            {
                return rm;
            }

        }
        rm = null;
        return this.checkValidate(fr, fo, o);

    }

    /**
     * 迭代验证ArrayList元素属性
     *
     * @param object
     * @param rulerMap
     * @return
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    @SuppressWarnings("unchecked")
    private ReturnMessage validataChildFiled(Object object, Map<String, FieldRuler> rulerMap, Object o)
            throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException,
            InvocationTargetException
    {
        ReturnMessage rm = new ReturnMessage();
        rm.setReturnCode(SerErrorCommonCode.SUCCEED);
        Object tempObj = object;
        Field[] fields = object.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++)
        {
            // 取校验规则
            FieldRuler fr = rulerMap.get(fields[i].getName().toLowerCase());
            // 如果此字段没有给出校验规则,则不对此字段进行校验
            if (fr == null)
            {
                continue;
            }
            Method method = object.getClass().getMethod(getMethodName(fields[i].getName()), new Class[0]);
            // 通过get方法,获取属性值
            Object fo = method.invoke(tempObj, new Object[0]);
            // 如果子元素属性是集合类型,则继续验证集合中的数据
            if (fr.getType() != null && fr.getType().equals("list") && null != fo)
            {
                List tempList = (ArrayList) fo;
                object = null;
                tempObj = null;
                // 递归进行验证
                for (int temp = 0; temp < tempList.size(); temp++)
                {
                    rm = null;
                    validataChildFiled(tempList.get(temp), rulerMap, tempObj);

                }

            }
            // 验证属性
            rm = checkField(fields[i].getName().toLowerCase(), rulerMap, fo, tempObj);
            if (!SerErrorCommonCode.SUCCEED.equals(rm.getReturnCode()))
            {
                return rm;
            }

        }

        return rm;

    }

    /**
     * 对特定字段的值进行校验
     *
     * @param fr
     * @param value
     * @return
     * @throws NoSuchMethodException
     * @throws SecurityException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     */
    @SuppressWarnings("unchecked")
    private ReturnMessage checkValidate(FieldRuler fr, Object value, Object o) throws SecurityException,
            NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException
    {
        ReturnMessage rm = new ReturnMessage();

        if (fr.getType() != null && fr.getType().equals("list") && null != value)
        {
            List tempList = (ArrayList) value;
            if (tempList.isEmpty() && fr.getNeed().equals("yes"))
            {
                rm.setReturnCode(SerErrorCommonCode.PARA_CHECK_FAILED);
                rm.setErrorMessage(PropertiesFactory.getValueString(SerErrorCommonCode.PARA_CHECK_FAILED)
                        + " ,field name is :" + fr.getId());
            }
            else
            {
                rm.setReturnCode(SerErrorCommonCode.SUCCEED);
            }
            return rm;
        }
        Pattern p = Pattern.compile(fr.getRegex());
        Matcher m = p.matcher(value.toString());
        // 规则校验 长度校验
        if (!m.matches() || !validateDBAllowMaxLength(fr.getMaxLength(), value.toString()))
        {
            rm.setReturnCode(SerErrorCommonCode.PARA_CHECK_FAILED);
            rm.setErrorMessage(PropertiesFactory.getValueString(SerErrorCommonCode.PARA_CHECK_FAILED)
                    + " ,filed name is :" + fr.getId());
            return rm;

        }
        return validataJoinFiledRuler(rm, fr, value, o);
    }

    /**
     *  级联校验
     *  举例说明:
     *  <field id="ProdOfferingCode" regex="^\w{1,20}$" need="yes">
     *  <joinCheck>
     *    <attribute  value="1" >
     *         <checkFile refField="region"  regex="^\w{1,20}$"/>
     *    </attribute>    
     *  </joinCheck>    
     *          当ProdOfferingCode的值为1时,    region的值必须满足regex 的校验规则
     *        
     * @param rm
     * @param fr
     * @param value
     * @param o
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    @SuppressWarnings("unchecked")
    private ReturnMessage validataJoinFiledRuler(ReturnMessage rm, FieldRuler fr, Object value, Object o)
            throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException,
            InvocationTargetException
    {
        // 默认返回成功
        rm.setReturnCode(SerErrorCommonCode.SUCCEED);
        // 级联校验(基于本属性对其他属性进行校验)
        if (fr.getJoinCheckFiled() == null)
        {

            return rm;
        }
        Map<String, CheckField> checkMAp = fr.getJoinCheckFiled().getJoinCheck();
        if (checkMAp == null || !checkMAp.containsKey(value))
        {
            return rm;
        }
        JoinFiledRuler joinFiledRuler = fr.getJoinCheckFiled();
        Map<String, CheckField> map = joinFiledRuler.getJoinCheck();
        CheckField checkField = map.get(value);
        Class c = o.getClass();
        Method method = c.getMethod(getMethodName(checkField.getRefField()), new Class[0]);
        Object fo = method.invoke(o, new Object[0]);// get方法无参\
        String checkStr = "";
        if (fo != null)
        {
            checkStr =fo.toString();
        }
        Pattern p = Pattern.compile(checkField.getRegex());
        Matcher m = p.matcher(checkStr);
        // 规则校验 长度校验
        if (!m.matches() || !validateDBAllowMaxLength(checkField.getMaxLength(), checkStr))
        {
            rm.setReturnCode(SerErrorCommonCode.PARA_CHECK_FAILED);
            rm.setErrorMessage(PropertiesFactory.getValueString(SerErrorCommonCode.PARA_CHECK_FAILED)
                    + " ,filed name is :" + checkField.getRefField());

        }
        return rm;

    }

    /**
     * 验证DB允许的长度值
     *
     * @param length
     * @param value
     * @return
     */
    private boolean validateDBAllowMaxLength(String length, String value)
    {
        // length为null,则不需要验证
        if (null == length)
        {
            return true;
        }
        // 值的长度大于DB允许的长度时
        if (Integer.parseInt(length) < StringUtil.getLengthInOracle(value))
        {
            return false;
        }
        return true;
    }

    public static String getMethodName(String name)
    {
        return "get" + firstLetterToUpperCase(name);
    }

    /**
     * 首字母小写变大写
     */
    public static String firstLetterToUpperCase(String name)
    {
        if (name == null || name.length() == 0)
        {
            return name;
        }
        char[] chars = name.toCharArray();
        chars[0] = Character.toUpperCase(chars[0]);
        return new String(chars);
    }

}


原创粉丝点击