了解springmvc是如何进行参数绑定的,使用idea对springmvc源码进行逐步调试,源码版本4.3.2
从@RequestParam注解开始入手,搜索该注解在源码中使用的地方
可以看到RequestParam分别在HandlerMethodInvoker,RequestParamMapMethodArgumentResolver,RequestParamMethodArgumentResolver这三个类中进行了实例化
其中HandlerMethodInvoker是个过期类,已被RequestMappingHandlerAdapter替代
我们就从RequestMappingHandlerAdapter入手,打开该类的源码,从类名可以看出这是用来处理RequestMapping的,
在javadoc中可以看到
An {@link AbstractHandlerMethodAdapter} that supports {@link HandlerMethod}s
with their method argument and return type signature, as defined via {@code @RequestMapping}
Support for custom argument and return value types can be added via
{@link #setCustomArgumentResolvers} and {@link #setCustomReturnValueHandlers}.
Or alternatively, to re-configure all argument and return value types,
use {@link #setArgumentResolvers} and {@link #setReturnValueHandlers}
这里提到了setCustomArgumentResolvers,setCustomReturnValueHandlers方法,即添加自定义参数处理器和自定义返回值处理器
我们先进入setCustomArgumentResolvers方法
就是个HandlerMethodArgumentResolver集合,然后我们进入HandlerMethodArgumentResolver,这是一个接口,我们可以查看此接口的相关实现
进入type hierarchy
在这里我们看到了第一步搜索出现的RequestParamMethodArgumentResolver,现在可以基本确定@RequestParam是由此类负责处理
现在进入RequestParamMethodArgumentResolver类
该类所有方法
supportsParameter是用来判断是否存在RequestParam注解,是则处理,不是则不处理
resolveName是真正的处理参数的方法
下面是部分源码
可以看到从Request请求中获取参数值并返回
继续往上搜索,搜索调用resolveName方法的地方
进入AbstractNamedValueMethodArgumentResolver的resolveArgument方法
AbstractNamedValueMethodArgumentResolver是RequestParamMethodArgumentResolver的父类
resolveArgument主要处理了RequestParam相关参数,如默认参数,是否必传等
我们再往上搜索resolveArgument方法的调用方
HandlerMethodArgumentResolverComposite的resolveArgument方法
该方法调用了另一个关键方法getArgumentResolver
即通过参数注解筛选合适的参数处理器
继续向上搜索resolveArgument方法的调用类
进入InvocableHandlerMethod类的getMethodArgumentValues方法
这个方法里面是对方法所有参数进行遍历获取对应值
最后返回了方法所有的参数数组
继续向上搜索进入InvocableHandlerMethod类的invokeForRequest方法,这是真正调用RequestMapping注解方法的地方
doInvoke即使用反射调用方法并获取返回值
获取返回值后进入ServletInvocableHandlerMethod类的invokeAndHandle对返回值进行处理
调用HandlerMethodReturnValueHandlerComposite类的handleReturnValue方法
selectHandler获取合适的返回值处理器
默认有15个处理器
获取到合适处理器后运行该处理器的handleReturnValue方法对参数进行处理
我使用了@ResponseBody注解,所以进入RequestResponseBodyMethodProcessor类将实体类转换为json