• spring 参数校验


    1.了解下资源文件加载

      MessageSource   需要国际化处理时使用这个类 (在需要处理国际化的地方使用messageSource.getMessage(this.getResponseCode(),this.getArgs(),"", locale))

        ResourceBundleMessageSource        不能定时刷新资源文件

        ReloadableResourceBundleMessageSource  可以定时刷新资源文件

          PropertyPlaceholderConfigurer   应用程序内部占位符替换(将占位符替换为具体的值)

    2.spring  BeanPropertyBindingResult 的用法,

            HelloParams params=new HelloParams();
            Errors errors=new BeanPropertyBindingResult(params,HelloParams.class.getName());
            errors.rejectValue("clientId", "NOTNULL", null);
            System.out.println(errors);

    3.了解一下springmvc处理流程

    dispatcherServlet--->

    handlerMappings-->根据request---》HandlerExecutionChain (包括了拦截器和 handler)
    [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@1effc30a,
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping@1a544088,
    org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@463d761b,
    org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping@19b6e142,
    org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@793186ed,
    org.springframework.boot.autoconfigure.web.servlet.WelcomePageHandlerMapping@41d9c943]
    ---》根据handler 获取对应的handlerAdapter-->
    [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter@150afe2,
    org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter@6cf9e2cd,
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter@426bb2e1]
    --->handlerAdapter调用handler处理request
    --->handler 调用 HandlerMethodArgumentResolver
    [org.springframework.web.method.annotation.RequestParamMethodArgumentResolver@5acedd4b,
    org.springframework.web.method.annotation.RequestParamMapMethodArgumentResolver@4c91253d,
    org.springframework.web.servlet.mvc.method.annotation.PathVariableMethodArgumentResolver@76da1b10,
    org.springframework.web.servlet.mvc.method.annotation.PathVariableMapMethodArgumentResolver@24bc9d2a,
    org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMethodArgumentResolver@8342873,
    org.springframework.web.servlet.mvc.method.annotation.MatrixVariableMapMethodArgumentResolver@4d495c85,
    org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor@6beddca7,
    org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor@4412d4dd,
    org.springframework.web.servlet.mvc.method.annotation.RequestPartMethodArgumentResolver@2bf8493d,
    org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver@2268b81,
    org.springframework.web.method.annotation.RequestHeaderMapMethodArgumentResolver@50c4234,
    org.springframework.web.servlet.mvc.method.annotation.ServletCookieValueMethodArgumentResolver@1aed6,
    org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver@6959be4a,
    org.springframework.web.servlet.mvc.method.annotation.SessionAttributeMethodArgumentResolver@5f955a63,
    org.springframework.web.servlet.mvc.method.annotation.RequestAttributeMethodArgumentResolver@38efae47,
    org.springframework.web.servlet.mvc.method.annotation.ServletRequestMethodArgumentResolver@3595c092,
    org.springframework.web.servlet.mvc.method.annotation.ServletResponseMethodArgumentResolver@111a8384,
    org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor@64a98586,
    org.springframework.web.servlet.mvc.method.annotation.RedirectAttributesMethodArgumentResolver@217192c2,
    org.springframework.web.method.annotation.ModelMethodProcessor@3a7b472e,
    org.springframework.web.method.annotation.MapMethodProcessor@7fb8e546,
    org.springframework.web.method.annotation.ErrorsMethodArgumentResolver@5795ca82,
    org.springframework.web.method.annotation.SessionStatusMethodArgumentResolver@7a5fa530,
    org.springframework.web.servlet.mvc.method.annotation.UriComponentsBuilderMethodArgumentResolver@1afddf62,
    org.springframework.web.method.annotation.RequestParamMethodArgumentResolver@22578bae,
    org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor@5b6f84bc]
    --->HttpMessageConverter

    普通的读取form里的参数
    ServletModelAttributeMethodProcessor

    没有convert

    有@requestbody
    RequestResponseBodyMethodProcessor
    [org.springframework.http.converter.ByteArrayHttpMessageConverter@3d37203b,
    org.springframework.http.converter.StringHttpMessageConverter@45bb2aa1,
    org.springframework.http.converter.StringHttpMessageConverter@7fd26ad8,
    org.springframework.http.converter.ResourceHttpMessageConverter@1894593a,
    org.springframework.http.converter.ResourceRegionHttpMessageConverter@14b0e127,
    org.springframework.http.converter.xml.SourceHttpMessageConverter@10823d72,
    org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter@7cea0110,
    org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@3e84111a,
    org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@468dda3e,
    org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter@5527b211]

    一、HandlerMethodArgumentResolver

    RequestResponseBodyMethodProcessor

    bject arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
            String name = Conventions.getVariableNameForParameter(parameter);
    
            if (binderFactory != null) {
                WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
                if (arg != null) {
                    validateIfApplicable(binder, parameter);
                    if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
                        throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
                    }
                }
                if (mavContainer != null) {
                    mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
                }
            }

    ServletModelAttributeMethodProcessor
    //主要操作,绑定参数和校验参数

                            bindRequestParameters(binder, webRequest);
                    }
                    validateIfApplicable(binder, parameter);

    读取form里的参数

    public static Map<String, Object> getParametersStartingWith(ServletRequest request, @Nullable String prefix) {
            Assert.notNull(request, "Request must not be null");
            Enumeration<String> paramNames = request.getParameterNames();
            Map<String, Object> params = new TreeMap<>();
            if (prefix == null) {
                prefix = "";
            }
            while (paramNames != null && paramNames.hasMoreElements()) {
                String paramName = paramNames.nextElement();
                if ("".equals(prefix) || paramName.startsWith(prefix)) {
                    String unprefixed = paramName.substring(prefix.length());
                    String[] values = request.getParameterValues(paramName);
                    if (values == null || values.length == 0) {
                        // Do nothing, no values found at all.
                    }
                    else if (values.length > 1) {
                        params.put(unprefixed, values);
                    }
                    else {
                        params.put(unprefixed, values[0]);
                    }
                }
            }
            return params;
        }

    二 、HandlerMethodReturnValueHandler

    RequestResponseBodyMethodProcessor


    三、介绍HttpMessageConverter
    @requestbody 和 @responsebody
    Jaxb2RootElementHttpMessageConverter

    @requestbody 和 @responsebody 加上的同时,要在类上加@XmlRootElement 同时使用application/xml contentType和accept
    MappingJackson2HttpMessageConverter

    //hibernate 使用那些文件的国际化配置
    1.使用jsr303对应的国际化文件 default "ValidationMessages.properties"
    Validation.byDefaultProvider().configure()
    .getDefaultMessageInterpolator()
    2.使用spring对应的国际化文件
    public void setValidationMessageSource(MessageSource messageSource) {
    this.messageInterpolator = HibernateValidatorDelegate.buildMessageInterpolator(messageSource);
    }

    //获取local

    @Override
    public String interpolate(String message, Context context) {
    return this.targetInterpolator.interpolate(message, context, LocaleContextHolder.getLocale());
    }

    3.使用校验注解标注在属性上(dto)

     

    4.使用方法

    参照: https://www.cnblogs.com/mr-yang-localhost/p/7812038.html

    @GroupSequence也可以定义在po类上,定义找个类那些组先执行,那些组后执行。

              

    5.自定义校验:

      1.解析对象,缓存对线的校验对象

        public void checkConfigLoaded(Class<?> dtoClass){
            Boolean isloaded=annotationFlag.get(dtoClass);
            if(isloaded==null){
                synchronized(annotationFlag){
                    checkAnotation(dtoClass);
                    checkClazzAnotation(dtoClass);
                    annotationFlag.put(dtoClass, Boolean.TRUE);
                }
            }
        }

      2.根据类初始化它的校验对象  

    VNumber vn=ReflectUtils.getAnnotation(pd,VNumber.class);
                if(vn!=null){
                    this.addValidator(new NumberValidator(vn),dtoClass,pd.getName());
                }
                VLength vl=ReflectUtils.getAnnotation(pd,VLength.class);
                if(vl!=null){
                    this.addValidator(new LengthValidator(vl),dtoClass,pd.getName());
                }
                VRegex vr=ReflectUtils.getAnnotation(pd,VRegex.class);
                if(vr!=null){
                    this.addValidator(new RegexValidator(vr),dtoClass,pd.getName());
                }

      3.执行过程中 

        1.当前对象循环,2.子对象循环,3.校验过滤器覆盖

        public void _validate(Object dto,String parentPath,int idx) throws Throwable{
            
            PropertyDescriptor[] pds=Introspector.getBeanInfo(dto.getClass()).getPropertyDescriptors();
            String realParentPath=parentPath;
            if(idx>-1 && parentPath!=null){
                realParentPath=(parentPath+"["+idx+"]");
            }
            ValidateContext context=new DefaultValidateContext(this.bean,realParentPath,dto,errors);
            //
            ConfigLoader configLoader=validateSupport.getConfigLoader();
            configLoader.checkConfigLoaded(dto.getClass());
            //----------------------------
            for(int i=0;i<pds.length;i++){
                PropertyDescriptor pd=pds[i];
                if(pd.getReadMethod()==null)continue;
                Object value=pd.getReadMethod().invoke(dto);
                //---------------------------------------------------------------------
                //根据参数名取得验证器集合
                String realPath=null;
                String idxPath=(parentPath==null?pd.getName():(parentPath+"."+pd.getName()));;
                if(idx>-1 && realParentPath!=null){
                    realPath=realParentPath+"."+pd.getName();
                }else{
                    realPath=idxPath;
                }
                boolean isArray=pd.getPropertyType().isArray();
                int isBaseArray=0;//0未知,1是,2否
                if(isArray){
                    if(isBaseType(pd.getPropertyType().getComponentType())){
                        isBaseArray=1;
                    }else{
                        isBaseArray=2;
                    }
                }
                ValidatorsSet validators=null;
                //--------------------------------------------------------------------
                ValidatorsSet temp=configLoader.getValidators(dto.getClass(),pd.getName());
                if(temp!=null){//如果未绑定任何验证器
                    if(validators==null){
                        validators=new ValidatorsSet();
                    }
                    validators.addAll(temp);
                }
                
                if(pathValidators!=null && idx>-1 && parentPath!=null){
                    temp=pathValidators.get(idxPath);
                    if(temp!=null){
                        if(validators==null){
                            validators=new ValidatorsSet();
                        }
                        validators.addAll(temp);
                    }
                }else if(pathValidators!=null){
                    temp=pathValidators.get(realPath);
                    if(temp!=null){
                        if(validators==null){
                            validators=new FieldValidators();
                        }
                        validators.addAll(temp);
                    }
                }
                if(isArray && isBaseArray==1){
                    if(validators !=null){
                        if(value==null){
                            validators.validate(context,pd,null,realPath,log);
                        }else{
                            int arrLen=Array.getLength(value);
                            if(arrLen==0){
                                validators.validate(context,pd,null,realPath,log);
                            }else{
                                for(int m=0;m<arrLen;m++){
                                    Object arrItem=Array.get(value,m);
                                    if(arrItem!=null ){
                                        validators.validate(context,pd,arrItem,realPath+"["+m+"]",log);
                                    }
                                }
                            }
                        }
                    }
                }else{
                    if(validators!=null){
                        //进行验证
                        validators.validate(context,pd,value,realPath,log);
                    }
                }
                //---------------------------------------------------------------------
                if(value!=null){
                    if(validateSupport.supports(pd.getPropertyType())){
                        _validate(value,idxPath,-1);
                    }
                    else if(isArray && isBaseArray==2){
                        int arrLen=Array.getLength(value);
                        for(int m=0;m<arrLen;m++){
                            Object arrItem=Array.get(value,m);
                            if(arrItem!=null ){
                                if(validateSupport.supports(arrItem.getClass())){
                                    _validate(arrItem,idxPath,m);
                                }
                            }
                        }
                    }else if(value instanceof Collection){
                        Collection<?> list=(Collection<?>)value;
                        int tempInt=-1;
                        for(Object obj:list){
                            tempInt++;
                            if(obj!=null && validateSupport.supports(obj.getClass())){
                                _validate(obj,idxPath,tempInt);
                            }
                            
                        }
                    }else if(value instanceof Map){
                        Map<?,?> map=(Map<?,?>)value;
                        Set<?> list=map.entrySet();
                        for(Object entryObj:list){
                            Map.Entry<?,?> entry=(Map.Entry<?,?>)entryObj;
                            Object vv=entry.getValue();
                            if(vv!=null && validateSupport.supports(vv.getClass())){
                                _validate(vv,idxPath+"."+entry.getKey(),-1);
                            }
                        }
                    }
                }
            }
        } 
    View Code
  • 相关阅读:
    c# 深拷贝与浅拷贝
    SQLServer性能优化 .net开发菜鸟总结
    Ajax自定义无刷新控件实现
    APScheduler库的详细用法
    catkin在centos中的安装
    第五次任务实现与项目总结第六组
    Javascript教程:获取当前地址栏url
    窗口处理问题
    HTML中area标签
    Asp.net中Frameset的使用小结
  • 原文地址:https://www.cnblogs.com/z-test/p/9989306.html
Copyright © 2020-2023  润新知