Spring源码分析-SpringMVC核心功能DispatcherServlet
SpringMVC的核心功能是DispatcherServlet
1.用户发送请求,执行DispatchServlet 中的doService方法
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); // 2.去HandlerMapping中拿到 handler mappedHandler = getHandler(processedRequest); // 如果HandlerMapping没有这个请求映射,则直接返回。如静态资源的拦截 if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // 3.通过handler来拿到HandlerAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // 省略部分代码 // 4.通过 HandlerAdapter 来调用控制器Controller中的方法,返回ModelAndView 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) { // 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.视图解析,通过 ViewResolver 返回View对象 // 6.视图渲染,通过 view.render 方法将Model渲染成视图 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } // 省略部分代码 }
2.映射处理器,去HandlerMapping中拿到 handler
这一步是执行 mappedHandler = getHandler(processedRequest);
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 这里的handlerMappings 在执行 initStrategies()方法时已经初始化 for (HandlerMapping hm : this.handlerMappings) { // HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } return null; }
3.处理适配器,通过handler来拿到HandlerAdapter
这一步执行的是 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { // 这里的handlerMappings 在执行 initStrategies()方法时已经初始化 for (HandlerAdapter ha : this.handlerAdapters) { // if (ha.supports(handler)) { return ha; } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
4.调用处理器相应功能方法,通过 HandlerAdapter 来调用控制器Controller中的方法,返回ModelAndView
这里执行的是 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
@Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); // 省略部分代码... // Execute invokeHandlerMethod in synchronized block if required. if (this.synchronizeOnSession) { // } else { // 代码关键部分 mav = invokeHandlerMethod(request, response, handlerMethod); } // 省略部分代码... return mav; } protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); try { // 省略部分代码... // 代码关键部分:方法调用,执行Controller 中的方法 invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } }
下面这个方法就是 视图解析 + 视图渲染
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception { boolean errorView = false; // 异常视图解析 if (exception != null) { if (exception instanceof ModelAndViewDefiningException) { logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException) exception).getModelAndView(); } else { Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); mv = processHandlerException(request, response, handler, exception); errorView = (mv != null); } } // Did the handler return a view to render? if (mv != null && !mv.wasCleared()) { // 代码关键部分 render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else { if (logger.isDebugEnabled()) { logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() + "': assuming HandlerAdapter completed request handling"); } } // 省略部分代码... }
5.视图解析,通过 ViewResolver 返回View对象
这一步执行的是 view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine locale for request and apply it to the response. Locale locale = this.localeResolver.resolveLocale(request); response.setLocale(locale); View view; if (mv.isReference()) { // 代码关键部分:通过 ViewResolver 返回View对象 view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + getServletName() + "'"); } } else { // No need to lookup: the ModelAndView object contains the actual View object. view = mv.getView(); if (view == null) { throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + "View object in servlet with name '" + getServletName() + "'"); } } // 省略部分代码... }
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception { for (ViewResolver viewResolver : this.viewResolvers) { View view = viewResolver.resolveViewName(viewName, locale); if (view != null) { return view; } } return null; }
6.视图渲染,通过 view.render 方法将Model渲染成视图
这一步调用的是 view.render(mv.getModelInternal(), request, response);
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine locale for request and apply it to the response. Locale locale = this.localeResolver.resolveLocale(request); response.setLocale(locale); View view; // 省略部分代码... try { if (mv.getStatus() != null) { response.setStatus(mv.getStatus().value()); } // 通过 view.render 方法将Model渲染成视图,及将新的视图返回给页面 view.render(mv.getModelInternal(), request, response); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'", ex); } throw ex; } }
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { if (logger.isTraceEnabled()) { logger.trace("Rendering view with name '" + this.beanName + "' with model " + model + " and static attributes " + this.staticAttributes); } Map<String, Object> mergedModel = createMergedOutputModel(model, request, response); prepareResponse(request, response); // 将Model渲染成新的视图并响应请求 renderMergedOutputModel(mergedModel, getRequestToExpose(request), response); }