springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三)

时间:2021-12-10 15:33:20

之前两篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)springMVC源码解析--HandlerMethodArgumentResolverComposite参数解析器集合(二)我们对参数解析器有一些了解了,接下来这篇博客我们选取一个HandlerMethodArgumentResolver的具体实现类RequestParamMethodArgumentResolver来简单介绍一下具体的参数解析过程。RequestParamMethodArgumentResolver简单来说就是对一个请求参数值的解析,将请求中的参数值解析成为Controller函数中参数需要的具体数据类型。

Controller中函数需要的参数

    @RequestMapping("/getdata")
    @ResponseBody
    public Object getData(String name,Integer age){
    	return name+""+age;
    }

我们发起的请求链接

http://localhost/product/getdata.action?name=admin&age=10

接下来我们跟踪一下代码看看springMVC是如何将请求中的参数name=admin和age=10解析成为函数中需要的具体数据类型String和Integer。

首先参数解析会到AbstractNamedValueMethodArgumentResolver类的resolveArgument函数,如下图

springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三)

首先会获取request中的参数name及值,接下来是在RequestParamMethodArgumentResolver类的resolveName函数中获取这个参数的值

protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest) throws Exception {
	......
	if (arg == null) {
		String[] paramValues = webRequest.getParameterValues(name);
		if (paramValues != null) {
			arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
		}
	}

	return arg;
}

上面代码的执行如下图:

springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三)

这样就获取了name=admini这个值。

参数转换的过程主要是在AbstractNamedValueMethodArgumentResolver类的resolveArgument函数中,主要是获取参数值和将参数转换为Controller中函数需要的参数类型。

@Override
	public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

		Class<?> paramType = parameter.getParameterType();
		NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
		//从request中获取参数值
		Object arg = resolveName(namedValueInfo.name, parameter, webRequest);
		if (arg == null) {
			if (namedValueInfo.defaultValue != null) {
				arg = resolveDefaultValue(namedValueInfo.defaultValue);
			}
			else if (namedValueInfo.required && !parameter.getParameterType().getName().equals("java.util.Optional")) {
				handleMissingValue(namedValueInfo.name, parameter);
			}
			arg = handleNullValue(namedValueInfo.name, arg, paramType);
		}
		else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
			arg = resolveDefaultValue(namedValueInfo.defaultValue);
		}
		//将获取的参数值转换为Controller中函数需要的数据类型
		if (binderFactory != null) {
			WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
			try {
				arg = binder.convertIfNecessary(arg, paramType, parameter);
			}
			catch (ConversionNotSupportedException ex) {
				throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
						namedValueInfo.name, parameter, ex.getCause());
			}
			catch (TypeMismatchException ex) {
				throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
						namedValueInfo.name, parameter, ex.getCause());

			}
		}

		handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);

		return arg;
	}