本文主要介绍在SpringMVC中,当一个URL请求发起后,SpringMVC如何根据URL将对应的请求分发到指定的Handler方法中(Controller中的指定方法)
前端请求发起时,会进入 HttpServlet 及继承了HttpServlet的类,进入对应的doGet,doPost方法;HttpServlet及其实现类中,只有FrameworkServlet类中实现了doGet及doPost,而在这两个方法中,实际调用的是doService这个方法,而FrameworkServlet中的doService是个抽象方法,其字子类DispatcherServlet 则实现了这个方法;在DispatcherServlet的doService方法中,调用了doDispatch(request, response) 真正处理请求,完成了SpringMVC处理的整个核心流程;
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 { // 1 检查是否是文件上传的请求 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. // 2 取得处理当前请求的Handler即处理器 HandlerExecutionChain 请求处理链对象 该对象封装了Handler和Inteceptor ==》controller mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { // 如果 handler 为空,则返回404 noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. // 3 获取处理请求的处理器适配器 HandlerAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. // 处理 last-modified 请求头 String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. // 4 实际处理器处理请求,返回结果视图对象 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } // 5. 结果视图对象的处理 如果没有配置返回页面,此方法将给赋一个默认页面 applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } //5. 视图渲染及跳转 方法最后也会调用triggerAfterCompletion() processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { //最终会调用HandlerInterceptor的afterCompletion 方法 triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { //最终会调用HandlerInterceptor的afterCompletion 方法 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); } } } }