文章目录
- 1. DispatcherServlet#doDispatch
- 2. AbstractHandlerMethodAdapter#handle
- 3. RequestMappingHandlerAdapter#handleInternal
- 4. RequestMappingHandlerAdapter#invokeHandlerMethod
- 5. ServletInvocableHandlerMethod#invokeAndHandle
- 6. InvocableHandlerMethod#invokeForRequest
- 7. InvocableHandlerMethod#getMethodArgumentValues
我们了解过常用参数注解(如@PathVariable、@RequestParam、@RequestHeader、@CookieValue、@RequestAttribute和@RequestBody)的使用,见常用参数注解这篇文章,想知道这些注解是怎么解析参数的,调试下跟着源码走一遍,体会会更加深刻一些。
1. DispatcherServlet#doDispatch
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
//...
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//...
}
可以看到处理器适配器有以下4种:
RequestMappingHandlerAdapter
HandlerFunctionAdapter
HttpRequestHandlerAdapter
SimpleControllerHandlerAdapter
2. AbstractHandlerMethodAdapter#handle
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return this.handleInternal(request, response, (HandlerMethod)handler);
}
3. RequestMappingHandlerAdapter#handleInternal
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
//...
ModelAndView mav;
if (this.synchronizeOnSession) {
//...
} else {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
//...
return mav;
}
4. RequestMappingHandlerAdapter#invokeHandlerMethod
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
//...
Object result;
try {
//...
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
//...
invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
//...
} finally {
//...
}
return (ModelAndView)result;
}
可以看到,参数解析器有如下27种,
返回值处理器有如下15种,
5. ServletInvocableHandlerMethod#invokeAndHandle
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);
}
6. InvocableHandlerMethod#invokeForRequest
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
logger.trace("Arguments: " + Arrays.toString(args));
}
return this.doInvoke(args);
}
7. InvocableHandlerMethod#getMethodArgumentValues
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
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);
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] == null) {
if (!this.resolvers.supportsParameter(parameter)) {
throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));
}
try {
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
} catch (Exception var10) {
if (logger.isDebugEnabled()) {
String exMsg = var10.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
logger.debug(formatArgumentError(parameter, exMsg));
}
}
throw var10;
}
}
}
return args;
}
}
首先,判断参数解析器是否支持解析该参数: this.resolvers.supportsParameter(parameter)
;
如果支持,接下来参数解析器会解析该参数:args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory)
。
7.1 HandlerMethodArgumentResolverComposite#supportsParameter
public boolean supportsParameter(MethodParameter parameter) {
return this.getArgumentResolver(parameter) != null;
}
7.1.1 HandlerMethodArgumentResolverComposite#getArgumentResolver
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
HandlerMethodArgumentResolver result = (HandlerMethodArgumentResolver)this.argumentResolverCache.get(parameter);
if (result == null) {
Iterator var3 = this.argumentResolvers.iterator();
while(var3.hasNext()) {
HandlerMethodArgumentResolver resolver = (HandlerMethodArgumentResolver)var3.next();
if (resolver.supportsParameter(parameter)) {
result = resolver;
this.argumentResolverCache.put(parameter, resolver);
break;
}
}
}
return result;
}
7.2 HandlerMethodArgumentResolverComposite#resolveArgument
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
HandlerMethodArgumentResolver resolver = this.getArgumentResolver(parameter);
if (resolver == null) {
throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
} else {
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}
}
7.2.1 AbstractNamedValueMethodArgumentResolver#resolveArgument
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
AbstractNamedValueMethodArgumentResolver.NamedValueInfo namedValueInfo = this.getNamedValueInfo(parameter);
MethodParameter nestedParameter = parameter.nestedIfOptional();
Object resolvedName = this.resolveEmbeddedValuesAndExpressions(namedValueInfo.name);
if (resolvedName == null) {
throw new IllegalArgumentException("Specified name must not resolve to null: [" + namedValueInfo.name + "]");
} else {
Object arg = this.resolveName(resolvedName.toString(), nestedParameter, webRequest);
//...
this.handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
return arg;
}
}