springmvc 参数解析绑定原理
DispatcherServlet#doDispatch -> ha.handle
RequestMappingHandlerAdapter#handleInternal -> invokeHandlerMethod()->
ServletInvocableHandlerMethod#invokeAndHandle() -> invokeForRequest() ->getMethodArgumentValues()
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {//获取当前handler所声明的所有参数,主要包括参数名,参数类型,参数位置,所标注的注解等等属性MethodParameter[] parameters = this.getMethodParameters();if (ObjectUtils.isEmpty(parameters)) {return EMPTY_ARGS;} else {Object[] args = new Object[parameters.length];for(int i = 0; i < parameters.length; ++i) {MethodParameter parameter = parameters[i];parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);// providedArgs是调用方提供的参数,这里主要是判断这些参数中是否有当前类型// 或其子类型的参数,如果有,则直接使用调用方提供的参数,对于请求处理而言,默认情况下,// 调用方提供的参数都是长度为0的数组args[i] = findProvidedArgument(parameter, providedArgs);if (args[i] == null) {if (!this.resolvers.supportsParameter(parameter)) {throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));}try {// 如果能够找到对当前参数进行处理的ArgumentResolver,则调用其// resolveArgument()方法从request中获取对应的参数值,并且进行转换args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);} catch (Exception var10) {if (this.logger.isDebugEnabled()) {String exMsg = var10.getMessage();if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {this.logger.debug(formatArgumentError(parameter, exMsg));}}throw var10;}}}return args;}}
基础类型的绑定
自定义类型的绑定
ServletModelAttributeMethodProcessor
参数解析绑定总结
- SpringMVC初始化时,RequestMappingHandlerAdapter类会把一些默认的参数解析器添加到argumentResolvers中。当SpringMVC接收到请求后首先根据url查找对应的HandlerMethod。
- 遍历HandlerMethod的MethodParameter数组
- 根据MethodParameter的类型来查找确认使用哪个HandlerMethodArgumentResolver,遍历所有的argumentResolvers的supportsParameter(MethodParameter parameter)方法。。如果返回true,则表示查找成功,当前MethodParameter,使用该HandlerMethodArgumentResolver。这里确认大多都是根据参数的注解已经参数的Type来确认。
- 解析参数,从request中解析出MethodParameter对应的参数,这里解析出来的结果都是String类型。
- 转换参数,把对应String转换成具体方法所需要的类型,这里就包括了基本类型、对象、List、Set、Map。
