之前两篇springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)和 springMVC源码解析--HandlerMethodArgumentResolverComposite参数解析器集合(二)我们对参数解析器有一些了解了,接下来这篇博客我们选取一个HandlerMethodArgumentResolver的具体实现类RequestParamMethodArgumentResolver来简单介绍一下具体的参数解析过程。
RequestParamMethodArgumentResolver简单来说就是对一个请求参数值的解析,将请求中的参数值解析成为Controller函数中参数需要的具体数据类型。
@RequestMapping("/getdata")
@ResponseBody
public Object getData(String name,Integer age){
return name+""+age;
}
我们发起的请求链接
http://localhost/product/getdata.action?name=admini&age=10
接下来我们跟踪一下代码看看springMVC是如何将请求中的参数name=admini和age=10解析成为函数中需要的具体数据类型String和Integer。
首先参数解析会到AbstractNamedValueMethodArgumentResolver类的resolveArgument函数,如下图
首先会获取request中的参数name及值,接下来是在RequestParamMethodArgumentResolver类的resolveName函数中获取这个参数的值
public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver implements UriComponentsContributor {
......
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
HttpServletRequest servletRequest = (HttpServletRequest)request.getNativeRequest(HttpServletRequest.class);
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest)WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);
Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest);
if(mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {
return mpArg;
} else {
Object arg = null;
if(multipartRequest != null) {
List paramValues = multipartRequest.getFiles(name);
if(!paramValues.isEmpty()) {
arg = paramValues.size() == 1?paramValues.get(0):paramValues;
}
}
if(arg == null) {
String[] paramValues1 = request.getParameterValues(name);
if(paramValues1 != null) {
arg = paramValues1.length == 1?paramValues1[0]:paramValues1;
}
}
return arg;
}
}
}
上面代码的执行如下图:
这样就获取了name=admini这个值。
参数转换的过程主要是在AbstractNamedValueMethodArgumentResolver类的resolveArgument函数中,主要是获取参数值和将参数转换为Controller中函数需要的参数类型。
public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,WebDataBinderFactory binderFactory) throws Exception {
AbstractNamedValueMethodArgumentResolver.NamedValueInfo namedValueInfo = this.getNamedValueInfo(parameter);
MethodParameter nestedParameter = parameter.nestedIfOptional();
Object resolvedName = this.resolveStringValue(namedValueInfo.name);
if(resolvedName == null) {
throw new IllegalArgumentException("Specified name must not resolve to null: [" + namedValueInfo.name + "]");
} else {
//从request中获取参数值
Object arg = this.resolveName(resolvedName.toString(), nestedParameter, webRequest);
if(arg == null) {
if(namedValueInfo.defaultValue != null) {
arg = this.resolveStringValue(namedValueInfo.defaultValue);
} else if(namedValueInfo.required && !nestedParameter.isOptional()) {
this.handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
}
arg = this.handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
} else if("".equals(arg) && namedValueInfo.defaultValue != null) {
arg = this.resolveStringValue(namedValueInfo.defaultValue);
}
//将获取的参数值转换为Controller中函数需要的数据类型
if(binderFactory != null) {
WebDataBinder binder = binderFactory.createBinder(webRequest, (Object)null, namedValueInfo.name);
try {
arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
} catch (ConversionNotSupportedException var11) {
throw new MethodArgumentConversionNotSupportedException(arg, var11.getRequiredType(), namedValueInfo.name, parameter, var11.getCause());
} catch (TypeMismatchException var12) {
throw new MethodArgumentTypeMismatchException(arg, var12.getRequiredType(), namedValueInfo.name, parameter, var12.getCause());
}
}
this.handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
return arg;
}
}