文章目录
前言
学习 springmvc 处理请求流程前,有一些前置知识,在我的另一篇文章 《SpringMVC 启动原理》中,建议先阅读完,在来看本篇。
springmvc 处理请求流程 - 大白话描述
整理的 springmvc 处理请求的流程图:
图中步骤详解:
- Tomcat 会监听请求
- 当请求到达后,Tomcat 会调用 Servlet 的 service 方法,也就是 DispatcherServlet 的 service 方法
- service 方法最终会调用 DispatcherServlet 中的 doDispatch 方法。请求处理的核心流程都在这个方法里
- 在 doDispatch 方法中,首先会根据 请求的路径,在 handlerMappings 中查找对应的 Handler。一般研究的都是 RequestMappingHandlerMapping,所以后续都是基于 RequestMappingHandlerMapping 介绍。
- 找到 Handler 后,再查找和 RequestMappingHandlerMapping 相对应的 HandlerAdapter,也就是RequestMappingHandlerAdapter。
- 执行拦截器的前置方法 preHandle,如果验证通过,就继续执行。
- 调用 RequestMappingHandlerAdapter 的 handle 方法。
- 用 RequestMappingHandlerAdapter 中的 参数解析器,来构建 Handler 的参数。
- 把构建的参数传入 Handler,并执行 Handler,也就是进行真正的业务调用,调我们写的方法。
- Handler 执行完毕后,用 RequestMappingHandlerAdapter 中的 返回值解析器 来处理返回结果。这里会有两种常见的分支:
- 通过 @ResponseBody 修饰时:
这种情况对应的 返回值解析器是 RequestResponseBodyMethodProcessor,返回值解析器 会调用 messageConvert 来处理返回值,@ResponseBody 修饰的返回值是对象时,对应的 messageConvert 就是MappingJackson2HttpMessageConverter,这个 messageConvert 会将返回值对象转换成 Json 字符串。 - 返回 ModelAndView 的时:
这种情况对应的 返回值解析器是 ModelAndViewMethodReturnValueHandler,返回值解析器 中会设置一个 viewName
- 通过 @ResponseBody 修饰时:
- 执行拦截器的后置方法 postHandle
- 最后会根据 是否设置了 viewName 来决定向客户端返回的内容。
- 无 viewName 时,会直接把 Json 字符串返回给客户端。
- 有 viewName 时,会继续调用 RequestMappingHandlerAdapter 中的视图处理器来渲染页面,最后把页面返回给客户端。
springmvc 处理请求流程 - 关键源码
1. 对应图中的紫色部分
// 请求最终会转发到这里
public class DispatcherServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 根据请求路径找到对应的 Handler
mappedHandler = getHandler(processedRequest)
// 找到与 HandlerMapping 对应的 HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 拦截器前处理
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 调用 Adapter 的handle 方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
}
}
2. 对应图中的浅蓝色部分
public class RequestMappingHandlerAdapter {
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
// 执行业务逻辑
invocableMethod.invokeAndHandle(webRequest, mavContainer);
}
}
public class ServletInvocableHandlerMethod {
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 class InvocableHandlerMethod {
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 调用参数解析器
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
// 将参数传入 handler,并真正的执行业务逻辑
Object returnValue = doInvoke(args);
}
}
3. 对应图中的绿色部分
// @ResponseBody 修饰时的返回值处理器
public class RequestResponseBodyMethodProcessor {
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
// 通过 messageConvert 处理返回值
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,
ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
// 找到对应的 messageConvert
for (HttpMessageConverter converter : this.messageConverters) {
}
}
}
4. 对应图中的黄色部分
// 返回值是 ModelAndView 时的 返回值处理器
public class ModelAndViewMethodReturnValueHandler {
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 设置视图名字
mavContainer.setViewName(viewName);
}
}
5.对应图中的粉色部分
public class DispatcherServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 拦截器的后置处理器
mappedHandler.applyPostHandle(processedRequest, response, mv);
// 判断 handler 的返回值是否是视图
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
// 当返回值不是视图时这个 mv 是 null
if (mv != null && !mv.wasCleared()) {
render(mv, request, response);
}
}
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (viewName != null) {
// 调用视图解析器
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
}
}
}