整体处理流程
1. 接收请求
org.springframework.web.servlet.FrameworkServlet#initContextHoldersRequestContextHolder就是利用ThreadLocal,将request放到线程关联的ThreadLocal中
RequestContextHolder,是springmvc的工具类,持有上下文request的容器,从而使得可以在任何java代码处获取request对象
2. 寻找HandlerMapping,关联HandlerMethod(@Controller)
确定这个请求需要被哪个@Controller的哪个方法处理
3. 生成处理器执行链
org.springframework.web.servlet.DispatcherServlet#doDispatch
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
获得到mappedHandler
位于处理器链末端的是一个HandlerMethod,DispatcherServlet通过handlerAdapter适配器对Interceptor List和HandlerMethod进行封装,并按照统一的适配器接口对HandlerAdapter处理方法进行调用
4. 处理器适配
根据HandlerMethod寻找HandlerAdapter
HandlerAdatper作用:帮助DispatcherServlet调用请求处理器(HandlerMethod),无需关注其中实际的调用细节。比如,调用注解实现的@Controller需要解析其关联的注解,比如请求参数绑定,类型转换,校验等,HandlerAdapter的主要目的是为了屏蔽与DispatcherServlet之间的诸多细节,下面的5-7步都是其作用的体现
5. handlerMethod转换
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
implements BeanFactoryAware, InitializingBean {
// 其使用一个Composite组合对象来装载多个HandlerMethodArgumentResolver
private HandlerMethodArgumentResolverComposite argumentResolvers;
}
其使用一个Composite组合对象来装载多个HandlerMethodArgumentResolver
方法参数解析器:HandlerMethodArgumentResolver
将请求参数映射到比如@RequestParam、@PathVariable以及@RequestBody
其也是有多个,哪个支持就处理
public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
private final List<HandlerMethodArgumentResolver> argumentResolvers = new LinkedList<>();
}
线程栈
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod
这是第一次进入到invokeHandlerMethod
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.invokeAndHandle(webRequest, mavContainer);
其同时也会装载多个HandlerMethodReturnValueHandlers
调用RequestMappingHandlerAdapter#invokeHandlerMethod
6. 处理请求
7. 通过HandlerMethodArgumentResolver来解析方法参数
8. 执行到具体的Controller中,执行方法
回到doDispatcher方法,线程栈弹出
// Apply preHandle methods of registered interceptors.
// 执行interceptor preHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// Actually invoke the handler.
// 调用目标controller的目标method
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// Apply postHandle methods of registered interceptors.
// 执行interceptor postHandle方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
再一次执行invokeHandlerMethod方法
HandlerExecutionChain#applyPreHandle方法中循环执行各个interceptor,最后通过反射调用方法
/**
* Invoke the handler method with the given argument values.
* 真实调用controller中的方法
*/
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(getBridgedMethod());
try {
// 通过反射调用方法
return getBridgedMethod().invoke(getBean(), args);
}
}
获取到返回值
9. 处理HandlerMethod执行结果
接上面的源码分析
->
返回到org.springframework.web.servlet.DispatcherServlet#doDispatch
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
->
org.springframework.web.servlet.DispatcherServlet#processDispatchResult
mv = processHandlerException(request, response, handler, exception);
->
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod#invokeAndHandle方法
try {
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor#writeWithMessageConverters
for (HttpMessageConverter<?> converter : this.messageConverters) {
// if canWrite 。。。
if(converter.canWrite(valueType, selectedMediaType)){
genericConverter.write(outputValue, declaredType, selectedMediaType, outputMessage);
}
}
注意:
- RequestResponseBodyMethodProcessor这个HandlerMethodReturnValueHandler包含多个HttpMessageConverter
- RequestResponseBodyMethodProcessor,其既是请求参数的解析器,又是执行结果的处理器。
- 可以自定义实现HandlerMethodArgumentResolver以及HandlerMethodReturnValueHandler但是要注意其顺序
10. 转化Http消息。Render the given ModelAndView。这里涉及到视图内容协商。
内容协商处理流程
前面的5步已经在前面已经做了
从上图的第6步:解析@ResponseBody HandlerMethod返回值开始分析
处理Accept Header,解析MediaType,对前端请求需要的(请求的媒体类型),与后端可以生成的(可生成的媒体类型),进行Compatible兼容处理,获得到协商好的MediaType
注意:当不包含Accept请求头的时候,其会返回*/*,即所有的媒体类型,与所有的producible media types兼容,这也就是为什么我们一般在发送http请求的时候不需要设置accept header的原因
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor#handleReturnValue
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
->
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor#writeWithMessageConverters
List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(request);
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(request, valueType, declaredType);
->
private List<MediaType> getAcceptableMediaTypes(HttpServletRequest request)
throws HttpMediaTypeNotAcceptableException {
return this.contentNegotiationManager.resolveMediaTypes(new ServletWebRequest(request));
}
HeaderContentNegotiationStrategy就是会处理Accept Header
第7步:匹配HttpMessageConverter支持的媒体类型
如果@RequestMapping.produces()存在,返回指定MediaType列表否则,返回已注册的HttpMessageConverter列表中支持的MediaType列表
返回到writeWithMessageConverters方法
for (MediaType requestedType : requestedMediaTypes) {
for (MediaType producibleType : producibleMediaTypes) {
// 需要的 与 可以生成的 Compatible
if (requestedType.isCompatibleWith(producibleType)) {
mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType));
}
}
}
这里就获得到了协商好的媒体类型了
for (HttpMessageConverter<?> converter : this.messageConverters) {
// 如果能写
genericConverter.write(outputValue, declaredType, selectedMediaType, outputMessage);
}
11. 返回REST HTTP
/**
* This implementation sets the default headers by calling {@link #addDefaultHeaders},
* and then calls {@link #writeInternal}.
*/
public final void write(final T t, @Nullable final Type type, @Nullable MediaType contentType,
HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
// 把响应里面的头加上去 会得到一个响应头中的Content-Type: application/json
final HttpHeaders headers = outputMessage.getHeaders();
addDefaultHeaders(headers, t, contentType);
writeInternal(t, type, outputMessage);
outputMessage.getBody().flush();
}
->
org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#writeInternal
MediaType contentType = outputMessage.getHeaders().getContentType();
JsonEncoding encoding = getJsonEncoding(contentType);
JsonGenerator generator = this.objectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding);
// object就是返回的pojo
Object value = object;
objectWriter.writeValue(generator, value);
这一步已经处理完成response了
->
最后回到org.springframework.web.servlet.DispatcherServlet#processDispatchResult,调用interceptor.afterCompletion方法
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
}
// 返回json 其mv = null
// 会调用interceptor.afterCompletion方法
mappedHandler.triggerAfterCompletion(request, response, null);
在整个过程中,注意到HandlerInterceptor的三个方法,preHandle,postHandle以及afterComplete的调用时机