SpringMVC源码之参数解析绑定原理 (3)

进入HandlerMethodArgumentResolverComposite的resolveArgument方法

public Object resolveArgument( MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { //首先获取参数解析器,这里获取的逻辑是首先从argumentResolverCache缓存中获取该MethodParameter匹配的HandlerMethodArgumentResolver。如果为空,遍历初始化定义的那24个。查找匹配的HandlerMethodArgumentResolver,然后添加至argumentResolverCache缓存中 HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); Assert.notNull(resolver, "Unknown parameter type [" + parameter.getParameterType().getName() + "]"); //解析参数 return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); }

然后进入HandlerMethodArgumentResolver的resolverArgument方法

public final Object resolveArgument( MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { //获取int的Class对象 Class<?> paramType = parameter.getParameterType(); //根据参数定义创建一个NamedValueInfo对象 NamedValueInfo namedValueInfo = getNamedValueInfo(parameter); //根据参数名解析出对象的值 Object arg = resolveName(namedValueInfo.name, parameter, webRequest); if (arg == null) { if (namedValueInfo.defaultValue != null) { arg = resolveDefaultValue(namedValueInfo.defaultValue); } else if (namedValueInfo.required) { handleMissingValue(namedValueInfo.name, parameter); } arg = handleNullValue(namedValueInfo.name, arg, paramType); } else if ("".equals(arg) && (namedValueInfo.defaultValue != null)) { arg = resolveDefaultValue(namedValueInfo.defaultValue); } //上面步骤获取的args是String类型,然后转换为方法参数所需要的类型(int) if (binderFactory != null) { WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name); arg = binder.convertIfNecessary(arg, paramType, parameter); } handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest); return arg; }

这个方法的职责是,首先获取paramType。也就是int对应的Class对象。然后根据parameter对象创建一个NamedValueInfo对象。这个对象存放的就是参数名、是否必须、参数默认值3个成员变量。然后进入resolverName方法解析参数,里面的逻辑其实很简单,就是根据方法的参数名来获取request中的参数。关键代码如下

String[] paramValues = webRequest.getParameterValues(name); if (paramValues != null) { arg = paramValues.length == 1 ? paramValues[0] : paramValues; }

所以这里返回的值就是9999,这里返回的值还是String类型的。而需要的参数是int类型的。然后通过binder.coverIfNecessary方法把String转换为int类型返回。

对象绑定

新加一个方法,代码如下

@ResponseBody @RequestMapping("/test2") public String test2(User u){ System.out.println(u.toString()); return "test1"; }

SpringMVC源码之参数解析绑定原理

这个请求的参数解析绑定便会交给ServletModelAttributeMethodProcessor这个类,在初始化argumentResolvers的时候。是会创建两个不同的ServletModelAttributeMethodProcessor对象的。

resolvers.add(new ServletModelAttributeMethodProcessor(false)); resolvers.add(new ServletModelAttributeMethodProcessor(true));

这两个有什么区别?进入supportsParameter方法看看

/** *带有@ModelAttribute注解返回true * parameter不是简单类型也返回true. */ public boolean supportsParameter(MethodParameter parameter) { if (parameter.hasParameterAnnotation(ModelAttribute.class)) { return true; } else if (this.annotationNotRequired) { return !BeanUtils.isSimpleProperty(parameter.getParameterType()); } else { return false; } }

虽然test2(User u)方法没有ModelAttribute注解,但是User.class不是简单类型。所以该MethodHandler的参数u还是会交给ServletModelAtttributeMethodProcessor处理。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspsgp.html