美文网首页
SpringMvc如何实现参数填充HandlerMethodAr

SpringMvc如何实现参数填充HandlerMethodAr

作者: 昨日已逝去 | 来源:发表于2019-05-24 10:27 被阅读0次

    github原文链接 https://github.com/DespairYoke/java-advance。创作不易,请给个免费的star,已表支持。

    示例

    @Controller
    public class HelloController {
    
        @GetMapping(value = "hello")
        public String index(String name) {
            System.out.println(name);
            return "index";
        }
    
    }
    

    请求示例: http://localhost:8080/spring-mvc/hello?name=zwd

    我们知道当浏览器发来请求时,我们会去HandlerMapping中找到对应的请求地址,获得响应的处理方法如hello,封装在HandlerExecutionChain中,而HandlerExecutionChain中有个HandlerMethod,是需要处理的对象。再根据HandlerMethod找到对应的HandlerAdapter去处理请求。经过一系列处理,最后请求转发到ServletInvocableHandlerMethod中。可以从RequestMappingHandlerAdapter看到下面这段代码。

    ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
    

    下面我们跳过其他,转到ServletInvocableHandlerMethod。ServletInvocableHandlerMethod应该同时负责处理返回值的工作。再往下看可以发现,是通过

    invocableMethod.invokeAndHandle(webRequest, mavContainer);
    

    这个方法对HandlerMethod进行处理的,再跟踪下去,发现了下面的方法:

    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    

    至此,已经完成了对hello方法的调用,毫无疑问,参数赋值应该就是在invokeForRequest方法中了,再看下该方法的代码,终于发现了获取参数值的方法:

    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    

    进入getMethodArgumentValues

    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("Failed to resolve", i), ex);
            }
            throw ex;
        }
    }
    

    发现里面有个argumentResolvers,根据名字也可以看出是对参数的处理集合,而supportsParameter方法则是检测改参数类型parameter该由去处理。
    值得一提的是springMvc中用到了一个类做为所有的参数处理实现类的集合HandlerMethodArgumentResolverComposite。循环判断是否支持和进行处理,也放在此类中。所有的实现类,是在初始化adaper进行填充的。代码可以在RequestMappingHandlerAdpter中看到

    public void afterPropertiesSet() {
    // Do this first, it may add ResponseBody advice beans
    
    if (this.argumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
        this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    }       
    

    使用debug方式,发现最终处理的实现类是RequestParamMethodArgumentResolver中的resolveArgument方法

    public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
    
        NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
        MethodParameter nestedParameter = parameter.nestedIfOptional();
    
        Object resolvedName = resolveStringValue(namedValueInfo.name);
        if (resolvedName == null) {
            throw new IllegalArgumentException(
                    "Specified name must not resolve to null: [" + namedValueInfo.name + "]");
        }
    
        Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
        //...
    }   
    
    • resolvedName 是参数名称,示例中的name参数.
    • arg是参数名称对应的值,根据示例浏览器请求可知是zwd.

    相关文章

      网友评论

          本文标题:SpringMvc如何实现参数填充HandlerMethodAr

          本文链接:https://www.haomeiwen.com/subject/hogwzqtx.html