SpringMVC数据转换,数据绑定,数据验证流程分析

SpringMVC的入口DispatcherServlet

SpringMVC调用时序图

这里写图片描述

1.真正的调用handler的方法是在HandlerAdapter中进行的

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
            /**
            * ~~设置request中的属性啊,判断文件下载啊啥的,
            **/

                // 调用Handler
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            /**
            * ~~异步请求啊,错误处理啊,视图映射啊啥的。。。。。。
            **/

        }
    }

RequestMappingHandlerAdapter

1、invokeHandler方法

        //创建请求对象
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        try {
            //创建WebDataBinder工厂
            WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);

            //创建Model工厂
            ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

            //创建InvocableHandlerMethod,handler方法调用对象
            ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);    

            //设置argumentResolvers用于处理请求参数,实际上是一个组件模式
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);

            //HandlerMethodReturnValueHandler,用于处理同步或者异步返回结果
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
            //设置数据绑定工厂
invocableMethod.setDataBinderFactory(binderFactory);
            //设置参数名发现器
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);   

            //模型和视图容器
            ModelAndViewContainer mavContainer = new ModelAndViewContainer();
            //设置FlashMap中的值
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));               
            //初始化模型
            modelFactory.initModel(webRequest, mavContainer, invocableMethod);
            /**
            *异步处理
            **/

            //真正的调用
            invocableMethod.invokeAndHandle(webRequest, mavContainer);

            return getModelAndView(mavContainer, modelFactory, webRequest);
        }
    }

2、 getDataBinderFactory方法

1、收集目标Controller中的initBinder注解的方法
2、收集所有ControllerAdvice类型中的有InitBinder的方法
3、调用createDataBinderFactory 并传入收集的initBinder方法
4、初始化Binder顺序initializer.initBinder(dataBinder, webRequest) - > ControllerAdvice注解ControllerinitBinderMethods->该ControllerinitBinderMethods

    private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {

        //收集Controller中的有InitBinder注解的方法
        Set<Method> methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);

        //收集ControllerAdvice类型中的有InitBinder的方法
        for (Entry<ControllerAdviceBean, Set<Method>> entry : this.initBinderAdviceCache.entrySet()) {
            if (entry.getKey().isApplicableToBeanType(handlerType)) {
                Object bean = entry.getKey().resolveBean();
                for (Method method : entry.getValue()) {
                    initBinderMethods.add(createInitBinderMethod(bean, method));
                }
            }
        }
        /**
        *放入InitMethods集合中,并创建DataBinderFactory
        **/
    }

3、创建初始化binder方法,这些方法将在DataBinderFactory的createDataBinder方法中,生成Databinder之前被调用

initBinderArgumentResolvers方法用于处理InitBinder所注解的方法中可能存在的请求参数转换。例如在initBinder注解的方法中传入Type等来设置使用的类型

    private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) {
        InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method);

    //设置参数处理,initBinder方法中是可以传入request中包含的参数的       binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);
        binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer));
        binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
        return binderMethod;
    }

4、创建数据绑定对象工厂,传入WebBindingInitializer对象,该对象将在初始化DataBinder之前调用initBinder方法。顺序高于之前收集的InitBinder方法

    protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods)
            throws Exception {

        return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());
    }

5、获得模型工厂

private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
        SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
        Class<?> handlerType = handlerMethod.getBeanType();
        Set<Method> methods = this.modelAttributeCache.get(handlerType);
        if (methods == null) {
            methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
            this.modelAttributeCache.put(handlerType, methods);
        }
        List<InvocableHandlerMethod> attrMethods = new ArrayList<InvocableHandlerMethod>();
        // Global methods first
        for (Entry<ControllerAdviceBean, Set<Method>> entry : this.modelAttributeAdviceCache.entrySet()) {
            if (entry.getKey().isApplicableToBeanType(handlerType)) {
                Object bean = entry.getKey().resolveBean();
                for (Method method : entry.getValue()) {
                    attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
                }
            }
        }
        for (Method method : methods) {
            Object bean = handlerMethod.getBean();
            attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
        }
        return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);
    }
    private InvocableHandlerMethod createModelAttributeMethod(WebDataBinderFactory factory, Object bean, Method method) {
        InvocableHandlerMethod attrMethod = new InvocableHandlerMethod(bean, method);
        attrMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
        attrMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
        attrMethod.setDataBinderFactory(factory);
        return attrMethod;
    }

6、initModel方法

public void initModel(NativeWebRequest request, ModelAndViewContainer container,
            HandlerMethod handlerMethod) throws Exception {

        Map<String, ?> sessionAttributes = this.sessionAttributesHandler.retrieveAttributes(request);
        container.mergeAttributes(sessionAttributes);
        invokeModelAttributeMethods(request, container);

        for (String name : findSessionAttributeArguments(handlerMethod)) {
            if (!container.containsAttribute(name)) {
                Object value = this.sessionAttributesHandler.retrieveAttribute(request, name);
                if (value == null) {
                    throw new HttpSessionRequiredException("Expected session attribute '" + name + "'", name);
                }
                container.addAttribute(name, value);
            }
        }
    }

getMethodArgumentValues获取方法所需要的参数

private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
            Object... providedArgs) throws Exception {

        MethodParameter[] parameters = getMethodParameters();
        Object[] args = new Object[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            MethodParameter parameter = parameters[i];
            parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
            GenericTypeResolver.resolveParameterType(parameter, getBean().getClass());
            args[i] = resolveProvidedArgument(parameter, providedArgs);
            if (args[i] != null) {
                continue;
            }
            if (this.argumentResolvers.supportsParameter(parameter)) {
                try {
                    args[i] = this.argumentResolvers.resolveArgument(
                            parameter, mavContainer, request, this.dataBinderFactory);
                    continue;
                }
                catch (Exception ex) {
                    if (logger.isDebugEnabled()) {
                        logger.debug(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
                    }
                    throw ex;
                }
            }
            if (args[i] == null) {
                String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i);
                throw new IllegalStateException(msg);
            }
        }
        return args;
    }

HandlerMethodArgumentResolver类结构图以及抽象类功能分析

--暂时没图,后面补图

HandlerMethodArgumentResolver处理参数并返回,adapter中默认注册的argumentResolver

1、RequestParamMethodArgumentResolver

1、resolve types(默认模式下处理所有简单对象)
- @RequestParam-annotated method arguments.
- This excludes Map params where the annotation doesn’t specify a name.
- instead for such params.
- Arguments of type MultipartFile unless annotated with @RequestPart
- Arguments of type javax.servlet.http.Part unless annotated with @ RequestPart
- In default resolution mode, simple type arguments even if not with @ RequestParam
2、how it works
  If the method parameter type is Map, the name specified in the annotation is used to resolve the request parameter String value. The value is then converted to a Map via type conversion assuming a suitable Converter or PropertyEditor has been registered. Or if a request parameter name is not specified the RequestParamMapMethodArgumentResolver is used instead to provide access to all request parameters in the form of a map.
  A WebDataBinder is invoked to apply type conversion to resolved request header values that don’t yet match the method parameter type.

3、parent Class :AbstractNamedValueMethodArgumentResolver
,通过实现父类resolveName方法来处理Name对应的参数

protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
        HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
        MultipartHttpServletRequest multipartRequest =
                WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);

        Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest);
        if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {
            return mpArg;
        }

        Object arg = null;
        if (multipartRequest != null) {
            List<MultipartFile> files = multipartRequest.getFiles(name);
            if (!files.isEmpty()) {
                arg = (files.size() == 1 ? files.get(0) : files);
            }
        }
        if (arg == null) {
            String[] paramValues = request.getParameterValues(name);
            if (paramValues != null) {
                arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
            }
        }
        return arg;
    }

2、RequestParamMapMethodArgumentResolver

1、处理类型
- Resolves Map method arguments annotated with an @RequestParam where the annotation does not specify a request parameter name.
2、how it works
  The created Map contains all request parameter name/value pairs. If the method parameter type is MultiValueMap instead, the created map contains all request parameters and all there values for cases where request parameters have multiple values.


3、parent Class :HandlerMethodArgumentResolver
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        Class<?> paramType = parameter.getParameterType();

        Map<String, String[]> parameterMap = webRequest.getParameterMap();
        if (MultiValueMap.class.isAssignableFrom(paramType)) {
            MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>(parameterMap.size());
            for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                for (String value : entry.getValue()) {
                    result.add(entry.getKey(), value);
                }
            }
            return result;
        }
        else {
            Map<String, String> result = new LinkedHashMap<String, String>(parameterMap.size());
            for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                if (entry.getValue().length > 0) {
                    result.put(entry.getKey(), entry.getValue()[0]);
                }
            }
            return result;
        }
    }

3、PathVariableMethodArgumentResolver

1、resolve types
- Resolves method arguments annotated with an @PathVariable. If the method parameter type is Map, the name specified in the annotation is used to resolve the URI variable String value. The value is then converted to a Map via type conversion, assuming a suitable Converter or PropertyEditor has been registered.
2、how it works
-An @PathVariable is a named value that gets resolved from a URI template variable. It is always required and does not have a default value to fall back on. See the base class org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver for more information on how named values are processed.
-If the method parameter type is Map, the name specified in the annotation is used to resolve the URI variable String value. The value is then converted to a Map via type conversion, assuming a suitable Converter or PropertyEditor has been registered.

A WebDataBinder is invoked to apply type conversion to resolved path variable values that don’t yet match the method parameter type.
3、parent Class :AbstractNamedValueMethodArgumentResolver

protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
        Map<String, String> uriTemplateVars = (Map<String, String>) request.getAttribute(
                HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
        return (uriTemplateVars != null ? uriTemplateVars.get(name) : null);
    }

4、PathVariableMapMethodArgumentResolver

1、处理类型
- Resolves Map method arguments annotated with an @PathVariable where the annotation does not specify a path variable name. The created Map contains all URI template name/value pairs.
2、how it works
resolveMap from uriTemplateVars
3、parent Class :HandlerMethodArgumentResolver

public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        @SuppressWarnings("unchecked")
        Map<String, String> uriTemplateVars =
                (Map<String, String>) webRequest.getAttribute(
                        HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);

        if (!CollectionUtils.isEmpty(uriTemplateVars)) {
            return new LinkedHashMap<String, String>(uriTemplateVars);
        }
        else {
            return Collections.emptyMap();
        }
    }

5、 MatrixVariableMethodArgumentResolver

1、处理类型
- Resolves method arguments annotated with @MatrixVariable.
2、how it works
3、 parent Class : AbstractNamedValueMethodArgumentResolver

protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
        Map<String, MultiValueMap<String, String>> pathParameters = (Map<String, MultiValueMap<String, String>>)
                request.getAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
        if (CollectionUtils.isEmpty(pathParameters)) {
            return null;
        }

        String pathVar = parameter.getParameterAnnotation(MatrixVariable.class).pathVar();
        List<String> paramValues = null;

        if (!pathVar.equals(ValueConstants.DEFAULT_NONE)) {
            if (pathParameters.containsKey(pathVar)) {
                paramValues = pathParameters.get(pathVar).get(name);
            }
        }
        else {
            boolean found = false;
            paramValues = new ArrayList<String>();
            for (MultiValueMap<String, String> params : pathParameters.values()) {
                if (params.containsKey(name)) {
                    if (found) {
                        String paramType = parameter.getNestedParameterType().getName();
                        throw new ServletRequestBindingException(
                                "Found more than one match for URI path parameter '" + name +
                                "' for parameter type [" + paramType + "]. Use 'pathVar' attribute to disambiguate.");
                    }
                    paramValues.addAll(params.get(name));
                    found = true;
                }
            }
        }

        if (CollectionUtils.isEmpty(paramValues)) {
            return null;
        }
        else if (paramValues.size() == 1) {
            return paramValues.get(0);
        }
        else {
            return paramValues;
        }
    }

6、MatrixVariableMapMethodArgumentResolver

1、处理类型
- Resolves method arguments of type Map annotated with
2、how it works
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest request, WebDataBinderFactory binderFactory) throws Exception {

    @SuppressWarnings("unchecked")
    Map<String, MultiValueMap<String, String>> matrixVariables =
            (Map<String, MultiValueMap<String, String>>) request.getAttribute(
                    HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);

    if (CollectionUtils.isEmpty(matrixVariables)) {
        return Collections.emptyMap();
    }

    MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
    String pathVariable = parameter.getParameterAnnotation(MatrixVariable.class).pathVar();

    if (!pathVariable.equals(ValueConstants.DEFAULT_NONE)) {
        MultiValueMap<String, String> mapForPathVariable = matrixVariables.get(pathVariable);
        if (mapForPathVariable == null) {
            return Collections.emptyMap();
        }
        map.putAll(mapForPathVariable);
    }
    else {
        for (MultiValueMap<String, String> vars : matrixVariables.values()) {
            for (String name : vars.keySet()) {
                for (String value : vars.get(name)) {
                    map.add(name, value);
                }
            }
        }
    }

    return (isSingleValueMap(parameter) ? map.toSingleValueMap() : map);
}

3、 parent Class : HandlerMethodArgumentResolver

7、ServletModelAttributeMethodProcessor

1、处理类型,默认模式下处理所有级联对象
- Returns true if the parameter is annotated with ModelAttribute or, if in default resolution mode, for any method parameter that is not a simple type.
2、how it works
Model attributes are obtained from the model or created with a default constructor (and then added to the model). Once created the attribute is populated via data binding to Servlet request parameters. Validation may be applied if the argument is annotated with @javax.validation.Valid. or Spring’s own @org.springframework.validation.annotation.Validated.

When this handler is created with annotationNotRequired=true any non-simple type argument and return value is regarded as a model attribute with or without the presence of an @ModelAttribute.
3、parent Class : ModelAttributeMethodProcessor
该父类有另一个子类型ProxyingHandlerMethodArgumentResolver 用于处理被ModelAttribute注解所注解的接口类型。
以下为父类如何处理参数

public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        String name = ModelFactory.getNameForParameter(parameter);
        Object attribute = (mavContainer.containsAttribute(name) ? mavContainer.getModel().get(name) :
                createAttribute(name, parameter, binderFactory, webRequest));

        if (!mavContainer.isBindingDisabled(name)) {
            ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class);
            if (ann != null && !ann.binding()) {
                mavContainer.setBindingDisabled(name);
            }
        }

        WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
        if (binder.getTarget() != null) {
            if (!mavContainer.isBindingDisabled(name)) {
                bindRequestParameters(binder, webRequest);
            }
            validateIfApplicable(binder, parameter);
            if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
                throw new BindException(binder.getBindingResult());
            }
        }

        // Add resolved attribute and BindingResult at the end of the model
        Map<String, Object> bindingResultModel = binder.getBindingResult().getModel();
        mavContainer.removeAttributes(bindingResultModel);
        mavContainer.addAllAttributes(bindingResultModel);

        return binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter);
    }

8、RequestResponseBodyMethodProcessor

1、处理类型(处理RequestBody请求参数,ResponseBody响应结果)
- Resolves method arguments annotated with @RequestBody and handles return values from methods annotated with @ResponseBody by reading and writing to the body of the request or response with an HttpMessageConverter.
2、how it works

public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        Object arg = readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType());
        String name = Conventions.getVariableNameForParameter(parameter);

        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());
            }
        }
        mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());

        return arg;
    }

3、parent Class : AbstractMessageConverterMethodProcessor

9、RequestPartMethodArgumentResolver

1、处理类型

  • annotated with @RequestPart
  • of type MultipartFile unless annotated with @RequestParam
  • of type javax.servlet.http.Part unless annotated with @RequestParam

2、how it works

public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest request, WebDataBinderFactory binderFactory) throws Exception {

        HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
        RequestPart requestPart = parameter.getParameterAnnotation(RequestPart.class);
        boolean isRequired = ((requestPart == null || requestPart.required()) && !parameter.isOptional());

        String name = getPartName(parameter, requestPart);
        parameter = parameter.nestedIfOptional();
        Object arg = null;

        Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest);
        if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {
            arg = mpArg;
        }
        else {
            try {
                HttpInputMessage inputMessage = new RequestPartServletServerHttpRequest(servletRequest, name);
                arg = readWithMessageConverters(inputMessage, parameter, parameter.getNestedGenericParameterType());
                WebDataBinder binder = binderFactory.createBinder(request, arg, name);
                if (arg != null) {
                    validateIfApplicable(binder, parameter);
                    if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
                        throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
                    }
                }
                mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
            }
            catch (MissingServletRequestPartException ex) {
                if (isRequired) {
                    throw ex;
                }
            }
            catch (MultipartException ex) {
                if (isRequired) {
                    throw ex;
                }
            }
        }

        if (arg == null && isRequired) {
            if (!MultipartResolutionDelegate.isMultipartRequest(servletRequest)) {
                throw new MultipartException("Current request is not a multipart request");
            }
            else {
                throw new MissingServletRequestPartException(name);
            }
        }
        if (parameter.isOptional()) {
            arg = OptionalResolver.resolveValue(arg);
        }

        return arg;
    }

3、parent Class :AbstractMessageConverterMethodArgumentResolver

10、RequestHeaderMethodArgumentResolver

1、处理类型
- Resolves method arguments annotated with @RequestHeader except for Map arguments. See RequestHeaderMapMethodArgumentResolver for details on Map arguments annotated with @RequestHeader.

11、RequestHeaderMapMethodArgumentResolver

1、处理类型
- Resolves Map method arguments annotated with @RequestHeader. For individual header values annotated with @RequestHeader see RequestHeaderMethodArgumentResolver instead.

12、ServletCookieValueMethodArgumentResolver

1、处理类型
- org.springframework.web.method.annotation.AbstractCookieValueMethodArgumentResolver that resolves cookie values from an HttpServletRequest.

13、ExpressionValueMethodArgumentResolver

1、处理类型
- Resolves method arguments annotated with @Value.
- An @Value does not have a name but gets resolved from the default value string, which may contain ${…} placeholder or Spring Expression Language #{…} expressions.

14、SessionAttributeMethodArgumentResolver

1、处理类型
- SessionAttributeMethodArgumentResolver

15、RequestAttributeMethodArgumentResolver

1、处理类型
- Resolves method arguments annotated with an @RequestAttribute.

16、ServletRequestMethodArgumentResolver

1、处理类型
Resolves request-related method argument values of the following types:
WebRequest
ServletRequest
MultipartRequest
HttpSession
Principal
Locale
TimeZone (as of Spring 4.0)
java.time.ZoneId (as of Spring 4.0 and Java 8)
InputStream
Reader
org.springframework.http.HttpMethod (as of Spring 4.0)

17、ServletResponseMethodArgumentResolver

1、处理类型
- Resolves response-related method argument values of types:
ServletResponse
OutputStream
Writer

18、HttpEntityMethodProcessor

1、处理类型
- Resolves HttpEntity and RequestEntity method argument values and also handles HttpEntity and ResponseEntity return values.

19、RedirectAttributesMethodArgumentResolver

1、处理类型
- Resolves method arguments of type RedirectAttributes.

20、ModelMethodProcessor

1、处理类型
- Resolves Model arguments and handles Model return values.

21、MapMethodProcessor

1、处理类型
- Resolves Map method arguments and handles Map return values.

22、ErrorsMethodArgumentResolver

1、处理类型
- Resolves Errors method arguments.

23、SessionStatusMethodArgumentResolver

1、处理类型
- Resolves a SessionStatus argument by obtaining it from the ModelAndViewContainer.

24、UriComponentsBuilderMethodArgumentResolver

1、处理类型
- Resolvers argument values of type UriComponentsBuilder.

WebDataBinder类型结构图与时序图

WebDataBinder与包含的对象的类型结构图

三角箭头代表继承关系,菱形箭头代表包含关系
这里写图片描述

WebDataBinder处理数据绑定时序图

这里写图片描述

WebDataBinder处理类型转换时序图

这里写图片描述

WebDataBinder实现数据绑定与数据验证,数据转换。

1、数据绑定
bind(PropertyValues pvs)方法,通过HandlerMethodResolver传入属性信息,然后通过AbstractNestablePropertyAccessor处理级联对象,并设置值到 target 中,如此完成数据绑定功能。
2、数据转换。
数据转换实际上都是通过TypeConverterDelegate 委托类型来处理的,该委托类型持有一个PropertyEditorRegistrySupport的引用(BeanWrapperImpl或者SimpleTypeConverter) 通过PropertyEditorRegistrySupport获得CustomEditor和ConversionService和DefaultEditor,
生效顺序:
1、CustomEditor,使用者注册的PropertyEditor。
2、ConversionService
3、DefaultEditor。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值