纵观全局
我们先进入DIspatchServlet.doDispatch(),我们分析其调用过程的主要方法如下:
// 根据请求拿到具体的处理器方法HandlerMethod并获取拦截器包装成HandlerExecutionChain
mappedHandler = getHandler(processedRequest);
// 根据HandlerMethod得到对应的HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// HandlerAdapter调用HandlerMethod,这里会发生参数的自动转换
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
获取HandlerExecutionChain

如上图所示,SpringMVC中内置了8个handlerMappings处理器,用于不同类型的映射处理,使用迭代的方式一个个的去处理,不支持的实现在解析时会返回null
我们使用的是@RequestMapping因此对应的是RequestMappingHandlerMapping这个实现,这个实现的getHandler方法使用的是父类的方法,以下删除了部分代码,仅保留核心相关实现
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
return executionChain;
}
getHandlerInternal()用于根据请求路径查找匹配的HandlerMethod,SpringMVC启动时会解析所有RequestMapping的请求路径注册到mappingRegistry中

getHandlerExecutionChain()用于根据请求路径查找符合条件的拦截器
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
构建包装了HandlerMethod的HandlerExecutionChain,遍历注册的拦截器并进行匹配,如果匹配将加入到HandlerExecutionChain中
最后将HandlerExecutionChain返回
获取HandlerAdapter
我们知道SpringMVC通过HandlerAdapter来调用具体的处理器,从而实现与具体处理器的解耦,因此需要根据处理器类型来拿到类型匹配的HandlerAdapter

同样是进行一个迭代的匹配,这里使用的是RequestMappingHandlerAdapter这个实现,它的support方法为
public final boolean supports(Object handler) {
//即判断handler是否是一个HandlerMethod类型,后面的supportsInternal固定返回True
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
调用HandlerMethod
根据调用链一路来到invokeHandlerMethod,删除了其他代码
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
invocableMethod.invokeAndHandle(webRequest, mavContainer);
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
我们注意到这里有四个方法
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
他们就是负责处理参数和结果类型转换的,SpringMVC内置了多种参数类型转换和结果类型转换的处理器



这里将处理器设置进去后,进入invocableMethod.invokeAndHandle(webRequest, mavContainer);开始调用
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 这里会进行入参类型转换
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// 这里会进行返回类型转换
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
- 入参转换
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
Object returnValue = doInvoke(args);
return returnValue;
}
private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
args[i] = resolveProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
if (this.argumentResolvers.supportsParameter(parameter)) {
try {
args[i] = this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.dataBinderFactory);
continue;
}
}
}
return args;
}
argumentResolvers是HandlerMethodArgumentResolverComposite类型,内部封装了37个具体的参数解析器,属于设计模式中的组合模式。
这里同样使用组合模式对所有的解析器进行迭代,如果支持参数解析则进行解析并返回解析后的参数值。
2. 返回值转换
与入参转换流程基本一致,组合模式遍历选择处理器并进行处理
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
private HandlerMethodReturnValueHandler selectHandler(Object value, MethodParameter returnType) {
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
continue;
}
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
return null;
}
由于是Rest模式,因此这里的类型处理器为RequestResponseBodyMethodProcessor,其实现为
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// Try even with null return value. ResponseBodyAdvice could get involved.
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
注意这里的writeWithMessageConverters,这里会进行HttpMessageConverter的转换将返回值再转换为对应的格式

迭代所有消息转换器,判断是否支持请求的媒体类型来进行转换处理


拦截器调用

如图在DIspatcherServlet.doService方法中,通过
mappedHandler.applyPreHandle(processedRequest, response)
mappedHandler.applyPostHandle(processedRequest, response, mv);
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); --> mappedHandler.triggerAfterCompletion(request, response, null);
三个方法来调用三中拦截器
总结
至此,一个大概的请求流程就走完了,这里对视图等没有讲解,仅针对最基本的Rest流程进行讲解
本文详细解析了SpringMVC框架处理Restful API请求的全过程,从DispatcherServlet开始,介绍了如何获取处理器方法、拦截器、适配器,以及参数和返回值的转换机制。

470

被折叠的 条评论
为什么被折叠?



