• SpringMVC源码解析


    HandlerMethodArgumentResolver主要负责执行handler前参数准备工作.

    看个例子,红色部分的id初始化,填充值就是它干的活:

    1     @RequestMapping(value = "/{id}")
    2     @ResponseBody
    3     public String getBook(@PathVariable("id") String id) {
    4         Hello helloProxy = new HelloProxy();
    5         helloProxy.say("Jack");
    6         
    7         return id;
    8     }

    分析目录:

      1. 接口定义(是否支持参数,处理参数)

      2. 代言人HandlerMethodArgumentResolverComposite,封装其他实现

      3. 具体实现

        composite除外,根据是否实现HandlerMethodReturnValueHandle分为XXXMethodArgumentResolver(不实现)和XXXMethodProssor(实现)

        HandlerMethodReturnValueHandle用于处理返回值.

        实现类实在太多,简单分析下各类的职责吧,具体内容看下面.

        

    1. 接口定义

     老规矩,上来先看接口,看似很简单,一个是否支持,一个处理.

     1 package org.springframework.web.method.support;
     2 public interface HandlerMethodArgumentResolver {
     3 
     4     /**
     5      * 解析器是否支持参数
     6      */
     7     boolean supportsParameter(MethodParameter parameter);
     8 
     9     /**
    10      * 解析参数,填充到参数值
    11      */
    12     Object resolveArgument(MethodParameter parameter,
    13                            ModelAndViewContainer mavContainer,
    14                            NativeWebRequest webRequest,
    15                            WebDataBinderFactory binderFactory) throws Exception;
    16 
    17 }

    2. 代言人HandlerMethodArgumentResolverComposite,封装其他实现

    通过封装其他的实现,对外统一提供解析服务,这样用户在使用时,根本不用关心参数在哪里怎么解析处理的,只需要调用supportsParameter,resolveArgument就可以了.

    而如果要扩充支持的类型也很简单,添加实现类,然后通过addResolver注册进来就可以了.

    看到这个怎么想起设计模式的开闭原则了.对扩展开放,对修改关闭.

    看点代码:

    封装其他实现,并提供注册功能

     1 package org.springframework.web.method.support;
     2 public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
     3     private final List<HandlerMethodArgumentResolver> argumentResolvers =
     4             new LinkedList<HandlerMethodArgumentResolver>();
     5     public HandlerMethodArgumentResolverComposite addResolver(HandlerMethodArgumentResolver argumentResolver) {
     6         this.argumentResolvers.add(argumentResolver);
     7         return this;
     8     }
     9 
    10     public HandlerMethodArgumentResolverComposite addResolvers(
    11             List<? extends HandlerMethodArgumentResolver> argumentResolvers) {
    12         if (argumentResolvers != null) {
    13             for (HandlerMethodArgumentResolver resolver : argumentResolvers) {
    14                 this.argumentResolvers.add(resolver); // 难得没调addResolver
    15             }
    16         }
    17         return this;
    18     }

    在来看看具体是如何处理请求的:

    都是都通过private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter)查找resolver实现的.

      先用parameter当key去缓存中取

      如果取不到迭代所有的reoslevers,一个个执行supportsParameter,直到有一个true.

      跟GOF的责任链设计模式定义一致.

     1 package org.springframework.web.method.support;
     2 public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
     3     public boolean supportsParameter(MethodParameter parameter) {
     4         return getArgumentResolver(parameter) != null;
     5     }
     6     public Object resolveArgument(
     7             MethodParameter parameter, ModelAndViewContainer mavContainer,
     8             NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
     9             throws Exception {
    10 
    11         HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
    12         return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
    13     }
    14     private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
    15         HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
    16         if (result == null) {
    17             for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
    18                 if (methodArgumentResolver.supportsParameter(parameter)) {
    19                     result = methodArgumentResolver;
    20                     this.argumentResolverCache.put(parameter, result);
    21                     break;
    22                 }
    23             }
    24         }
    25         return result;
    26     }
    27 }

    3. 具体实现

    实在太多了,先凑合看下各个类的职责吧,具体的分析后续在debug中做.

    AbstractMessageConverterMethodArgumentResolver 使用HttpMessageConverter解析来自request body参数值的基类.

    --AbstractMessageConverterMethodProcessor 添加返回值处理,所以改名了

    ----HttpEntityMethodProcessor 解析参数时,只处理HttpEntity;处理返回值时支持HttpEntity和ResponseEntity.

    ----RequestResponseBodyMethodProcessor 使用HttpMessageConverter解析@RequestBody参数;处理使用@ResponseBody的返回值

    --RequestPartMethodArgumentResolver 解析使用@RequestPart,@RequestParam注解的参数;MultipartFile和Part的子类参数

    AbstractNamedValueMethodArgumentResolver 解析named vlaue类型参数(其实就是键值对).

    --AbstractCookieValueMethodArgumentResolver 解析使用@CookieValue注解的参数

    ----ServletCookieValueMethodArgumentResolver 从HttpServletRequest中解析出cookie值

    --ExpressionValueMethodArgumentResolver 解析@Value注解的参数

    --MatrixVariableMethodArgumentResolver 解析@MatrixVariable注解的参数,不包括map类型

    --PathVariableMethodArgumentResolver 解析使用@PathVariable注解的参数,从uri中解析参数

    --RequestHeaderMethodArgumentResolver 解析使用@RequestHeader注解的参数,不包括map类型

    --RequestParamMethodArgumentResolver 解析从request流中获取值的参数,如@RequestParam,MultipartFile,Part,默认使用时解析基本参数.

    AbstractWebArgumentResolverAdapter 使用@WebArgumentResolver的基类,用于向后兼容.适配WebArgumentResolver

    --ServletWebArgumentResolverAdapter 新建NativeWebRequest--

    ErrorsMethodArgumentResolver 处理Errors子类参数

    MapMethodProcessor 处理map类型参数

    MatrixVariableMapMethodArgumentResolver 使用@MatrixVariable注解的map类型参数

    ModelAttributeMethodProcessor 解析使用@ModelAttribute注解参数

    --ServletModelAttributeMethodProcessor 使用ServletRequestDataBinder解析参数

    ModelMethodProcessor 处理model类型参数

    PathVariableMapMethodArgumentResolver 处理使用@PathVariable注解的map参数

    RedirectAttributesMethodArgumentResolver 处理RedirectAttributes类型参数

    RequestHeaderMapMethodArgumentResolver 处理使用@RequestHeader注解的map参数

    RequestParamMapMethodArgumentResolver 处理使用@RequestParam注解的map参数

    ServletRequestMethodArgumentResolver 处理request相关的参数:WebRequest,ServletRequest,MultipartRequest,HttpSession,Principal,Locale,InputStream,Reader

    ServletResponseMethodArgumentResolver 解析response相关的参数:ServletResponse,OutputStream,Writer

    SessionStatusMethodArgumentResolver 处理SessionStatus类型参数

    UriComponentsBuilderMethodArgumentResolver 处理UriComponentsBuilder类型参数

  • 相关阅读:
    POST、GET请求中文参数乱码问题
    表的复制——sql语句
    mysql之limit m,n
    nullpointerxception——处理思路
    public-private-protected-默认缺省 的区别
    final关键字的作用
    使用注解来构造IOC容器
    成功的背后!(给所有IT人)
    jQuery对象复制
    键盘录入, if语句
  • 原文地址:https://www.cnblogs.com/leftthen/p/5227722.html
Copyright © 2020-2023  润新知