1.回顾
SpringMVC的核心是DispatcherServlet. 而DispatcherServlet的本质还是一个Servlet 。
说到Servlet 就得讲讲web服务器Tomcat。
文接Tomcat原理系列之三:请求链上的那些类 与 Tomcat原理系列之七:详解socket如何封装成request(下)
2.请求从Tomcat到SpringMVC
请求通过Socket 开启应用之旅,在Tomcat原理系列之三:请求链上的那些类 中讲过,请求来到Tomcat的最后一个valve,StandardWrapperValve时。执行其invoke方法
StandardWrapperValve
请求来到StandardWrapperValve#invoke方法
final class StandardWrapperValve extends ValveBase { public final void invoke(Request request, Response response) throws IOException, ServletException { // 1.Allocate a servlet instance to process this request //分配一个servet 去处理请求 servlet = wrapper.allocate(); // 2.Create the filter chain for this request //封装servlet, 为当前请求创建一个过滤器链 ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet); //3.执行过滤器链的doFilter方法,(链式执行各种Filter ,末端执行servlet's service() method) filterChain.doFilter(request.getRequest(), response.getResponse()); } }
ApplicationFilterChain
之后来到 ApplicationFilterChain#doFilter方法
public final class ApplicationFilterChain implements FilterChain { @Override public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { internalDoFilter(request,response);//调用内部internalDoFilter方法 } private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // Call the next filter if there is one // 4.链式调用每个Filter的doFilter方法 if (pos < n) { filter.doFilter(request, response, this); } //5.调用servlet的service方法 servlet.service(request, response); } }
在Filter的末端,开始准备进入Servlet执行方法。
HttpServlet
我们来看看DispatcherServlet 的继承图
从图中我们可以看出,DispatcherServlet 通过几层父类间接实现Servlet。
ApplicationFilterChain中 调用servlet.service(request, response);传递的参数是(ServletRequest request, ServletResponse response)。所以执行的是HttpServlet 中的service方法.可以看出此方法的目的是将ServletRequest,ServletResponse 转换为我们熟悉的HttpServletRequest ,HttpServletResponse
public abstract class HttpServlet extends GenericServlet { //6.执行HttpServlet.service()方法,做req,res 的强制转换 public void service(ServletRequest req, ServletResponse res){ HttpServletRequest request; HttpServletResponse response; try { //转为 HttpServletRequest,HttpServletResponse request = (HttpServletRequest) req; response = (HttpServletResponse) res; } catch (ClassCastException e) { throw new ServletException("non-HTTP request or response"); } service(request, response); } //8.执行HttpServlet.service此时的参数已经是HttpServletRequest,HttpServletResponse //并根据请求方法类型。调用不同的处理方法。子类FrameworkServlet 类中重写了一些方法,所以转去执行子类的doGet方法 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (method.equals(METHOD_GET)) { doGet(req, resp); } } }
FrameworkServlet
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { //7.兼容PATCH方法,非PATCH方法最终还是交给HttpServlet.service() protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpMethod httpMethod = HttpMethod.resolve(request.getMethod()); if (httpMethod == HttpMethod.PATCH || httpMethod == null) { processRequest(request, response); } else { super.service(request, response); } } //9.get代理方法,转到processRequset去处理 protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } //10.模板方法,请求的处理交给子类的doService方法去处理 protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doService(request, response); } }
DispatcherServlet
最终请求来到了DispatcherServlet的doService方法,开始DispatcherServlet的工作内容
//最终来到了DispatcherServlet public class DispatcherServlet extends FrameworkServlet { //11.做请求分发前的准备工作,主要是设置一些请求的相关属性 protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { doDispatch(request, response); } //12 开启请求的分发。 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { //开启DispatcherServlet的分发功能 } }
最终请求到了DispatcherServlet的doDispatch开启DispatcherServlet 请求分发处理功能。
3.DispatcherServlet的工作原理
请求到达doDispatch 方法后,DispatcherServlet对其做了什么呢?这就引出了DispatcherServlet的工作原理这个话题。
处理流程
借用网上张图:
- 请求来到DispatcherServlet
- DispatcherServlet根据请求信息,从HandlerMapping 找能处理当前请求的Handler并封装成一个HandlerExecutionChain
- 根据解析到的Handler ,获取一个适配器。
- HandlerAdapter会根据Handler来调用真正的处理器开处理请求,列如我们写的controller类中的业务方法
- 处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是个逻辑上的View
- ViewResolver会根据逻辑View查找实际的View。
- 视图渲染完成后,DispatcherServlet返回。
这些流程反映在代码中,就是doDispatch 方法内的相关调用了.
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { //检查是否是上传文件请求 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // 获取能处理当前请求的Handler 链 mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // 获取能处理当前请求的的handler的适配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } //拦截器前置处理 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } //适配器handle方法处理请求。 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); //拦截器后置处理 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { dispatchException = new NestedServletException("Handler dispatch failed", err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
4.总结
我们可以看出,DispatcherServlet采用了“中心化”的思想。请求统一过DispatcherServlet,这样的好处就是统一管理。DispatcherServlet就有点路由的意思了。
本文衔接Tomcat原理系列之七:详解socket如何封装成request(下) 终于粗略的过了一遍,请求如何从socket经Tomcat到达DispatcherServlet,变成我们常用的HttpServletRequest 。对于web 的工作原理有了更深的理解