springMVC 请求处理流程
因为 DispatcherServlet 是一个 servlet,所以初始化的时候是入口是 init()
方法
处理请求也是一样的,Servlet 处理请求的方法是 service()
,所以入口也是这里,开始找子类,看哪个类复写了 service()
,发现是 HttpServlet ,从这里开始分析
注意不要找到 FrameworkServlet 类了,这个类的参数和 Servlet 的参数不一致,一个是 ServletRequest 和 HttpServletRequest
-
javax.servlet.http.HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) { HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)res; // 强转 HttpServletRequest 调用 service this.service(request, response); } else { throw new ServletException("non-HTTP request or response"); } }
-
javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); long lastModified; if (method.equals("GET")) { // 巴拉巴拉,主要是调用这个方法 this.doGet(req, resp); } else if (method.equals("HEAD")) { lastModified = this.getLastModified(req); this.maybeSetLastModified(resp, lastModified); this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } else if (method.equals("PUT")) { this.doPut(req, resp); } else if (method.equals("DELETE")) { this.doDelete(req, resp); } else if (method.equals("OPTIONS")) { this.doOptions(req, resp); } else if (method.equals("TRACE")) { this.doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } }
这个方法作用是根据请求方式调用不同的方法,比如如果是 get 调用
doGet()
,如果是 delete 调用doDelete()
点进每个 doXXX 方法,这时要注意,这个虽然不是模板方法(有具体实现),但是有子类复写,根据面向对象,所以不管自己的实现,要去找子类的实现
子类是 FrameworkServlet,每个方法调用了的同一个方法
processRequest()
-
org.springframework.web.servlet.FrameworkServlet#processRequest
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ... try { // 这里调用了 doService this.doService(request, response); } catch (IOException | ServletException var16) { ... } finally { ... this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause); } }
doService()
是个模板方法,又找子类,就到了 DispatcherServlet 了,doService()
又调用了doDispatch()
方法至此,可以知道,每个请求过来都会到 DispatcherServlet 的 doDispatch 方法,开始分析这个方法
-
org.springframework.web.servlet.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(注意是处理器执行链,不仅仅是 handler) mappedHandler = getHandler(processedRequest); ... // 这里找 handler 的适配器(目前有个 handler 执行链,不会直接执行,而是要用适配器去执行) HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); ... // 这里通过是配置执行处理器执行链(其实只是执行 handler,拦截器不在这里执行) mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); // 这里执行拦截器 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { ... } catch (Throwable err) { ... } // 处理异常、视图渲染、生成模型数据、完成请求处理(释放资源啥的)。因为现在都是 json 异步交互,视图这块没必要看,后面专门说参数转换 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { ... } catch (Throwable err) { ... } finally { ... } }
-
怎么得到处理器执行链
// org.springframework.web.servlet.DispatcherServlet#getHandler @Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 这里直接遍历所有的处理器映射器(初始化完成的,具体是根据 mvc 注解驱动完成,初始化过程在上一篇文章中) if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { // 得到了 handler(处理器执行链) HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; } // org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler @Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 这里拿到 handler(handler其实就是 controller 里方法的抽象,一个 controller 的方法就是一个 handler) // 具体就不贴源码了,不然篇幅太多了。大致原理是:初始化的时候再 RequestMappingHandlerMapping 维护了一堆属性,根据 url 去匹配得到 Object handler = getHandlerInternal(request); ... // 这里得到了处理器执行链,源码也不翻了,代码很少,并且也很清晰,就是遍历所有拦截器包装原始的处理器得到处理器执行链 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); ... return executionChain; }
-
怎么得到处理器适配器
// org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { // 同处理器映射器,初始化时就准备好了 if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { // 当前适配器是否能处理 handler if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); } // org.springframework.web.servlet.handler.SimpleServletHandlerAdapter#supports @Override public boolean supports(Object handler) { // 如果当前 handler 是 Servlet,SimpleServletHandlerAdapter 就能处理 return (handler instanceof Servlet); } // org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#supports @Override public boolean supports(Object handler) { // 如果当前 handler 是 Controller,SimpleControllerHandlerAdapter 就能处理 return (handler instanceof Controller); } // org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#supports @Override public final boolean supports(Object handler) { return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)); } // org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#supportsInternal @Override protected boolean supportsInternal(HandlerMethod handlerMethod) { return true; }
-
怎么执行处理器,源码就不贴了,流程中真正执行的方法在这里
// org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest @Nullable public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 这是请求参数,这里会把参数封装到 controller 的参数上,具体怎么解析也是一门大学问,包括 @ResponseBody 怎么把对象转成 json 的,放在后面的文章中 Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs); if (this.logger.isTraceEnabled()) { this.logger.trace("Arguments: " + Arrays.toString(args)); } // 把参数传到 doInvoke,这里真正执行 return this.doInvoke(args); } // org.springframework.web.method.support.InvocableHandlerMethod#doInvoke @Nullable protected Object doInvoke(Object... args) throws Exception { ReflectionUtils.makeAccessible(getBridgedMethod()); try { // getBridgedMethod() 是一个 java.lang.reflect.Method(jdk 的,也就是 handler 那个方法),就是 java 的反射执行方法而已 return getBridgedMethod().invoke(getBean(), args); } ... }
问题:已经找到了 handler(具体 controller 的方法),底层已经知道了是反射执行,为什么要用适配器去执行?为什么不直接反射执行?
因为还要处理参数,请求参数响应参数都要根据具体的类型去处理,所以抽象到一个对象中统一处理,所以每一个适配器中会有对应的参数解析器