SpringMVC源码阅读-一个请求主要处理流程DispatcherServlet(四)
流程图
摘自:https://www.tianxiaobo.com/2018/06/29/Spring-MVC-原理探秘-一个请求的旅行过程/
继承关系图
1.GenericServlet 只是一个抽象类提供一些基础的模板 具体实现由以下子类实现
2.HTTPServlet提供了对service的实现
HttppServlet
service
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 HttpServletRequest request = (HttpServletRequest)req; //转为HttpServletResponse HttpServletResponse response = (HttpServletResponse)res; //<1>交给当前类的service方法处理 这里不是调用当前类的 而是调用子类FrameworkServlet的 重写了 子类会反向回调 this.service(request, response); } else { throw new ServletException("non-HTTP request or response"); } }
<2>service
javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
/** * 根据请求方式路由到对应的方法处理 * @param req * @param resp * @throws ServletException * @throws IOException */ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取请求协议头的请求方式 如:Request Method: GET String method = req.getMethod(); long lastModified; if (method.equals("GET")) { //-1则表示缓存绝对更新了 默认子类没有实现 直接返回的-1 lastModified = this.getLastModified(req); if (lastModified == -1L) { //<3>根据协议版本 返回400 405空实现 由子类实现 this.doGet(req, resp); } else { /** * <2>如果上一次请求客户端Last-Modified 如:Last-Modified: Thu, 20 Feb 2014 09:02:52 GMT * 一般静态文件会默认带上 * 浏览器会将数据缓存本地 * 后续浏览器都会带上 每次跟服务器数据更新时间来做比较 如果没更新返回304 空响应 * 浏览器直接使用过本地数据 */ long ifModifiedSince = req.getDateHeader("If-Modified-Since"); //比较缓存是否过期 if (ifModifiedSince < lastModified) { this.maybeSetLastModified(resp, lastModified); //<3>根据协议版本 返回400 405空实现 由子类实现 this.doGet(req, resp); } else { //返回304 resp.setStatus(304); } } } 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); } }
<3>doGet
路由的方法都在HettpServlet都是返回405或者400的空实现 会被子类重写
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String protocol = req.getProtocol(); String msg = lStrings.getString("http.method_get_not_supported"); if (protocol.endsWith("1.1")) { resp.sendError(405, msg); } else { resp.sendError(400, msg); } }
org.springframework.web.servlet.FrameworkServlet的重写
protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//<22>。 this.processRequest(request, response); } protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//<22>。 this.processRequest(request, response); } protected final void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//<22>。 this.processRequest(request, response); } protected final void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//<22>。 this.processRequest(request, response); }
FrameworkServlet
<1>service
org.springframework.web.servlet.FrameworkServlet#service
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //如果请求方式是PATCH 则直接调用 if (HttpMethod.PATCH.matches(request.getMethod())) {
//<22> this.processRequest(request, response); } else { /** * 否则调用父类的路由方法 最终也是调用processRequest * <2>作用是是 比如父类的304缓存策略 以及路由的不同方法 处理方式 有所差异 如 option处理方式 */ super.service(request, response); } }
<22>processRequest
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null; /** * <31>获取当前线程 国际化上下文 从里面会从2个ThreadLocal获取 * org.springframework.web.filter.RequestContextFilter#initContextHolders * 如果配置了这个filter这里每次请求已经初始化 spring boot 验证 */ LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); //构建当前线程当本次请求的国际化上下文 LocaleContext localeContext = this.buildLocaleContext(request); /** * <32>获取当前线程请求的RequestAttribute 里面会从2个ThreadLocal获取 * org.springframework.web.filter.RequestContextFilter#initContextHolders已经初始化 spring boot验证 */ RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); //<4>如果线程缓存没有构建过,表示之前没初始化过 内部封装了requset和response ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes); /** *会从requsetAttribute里面获取获取不到初始化一个再set进去 key=WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE * 表示我们后去都可以根据reqeust.getAttribute(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE)获取 * 用于给管理异步请求 */ WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor()); /** * <5>这里面会存入根据当前对象成语变量区分放到哪个线程缓存里面threadContextInheritable 默认为false * 我们可以利用前面的BeanWapper进行修改 * 表示我们后续都可以根据LocaleContextHolder和RequestContextHolder获取requestAttribute 内部封装了当前请求的requset和response * */ this.initContextHolders(request, localeContext, requestAttributes); try { //<6>DispatcherServlet实现 this.doService(request, response); } catch (ServletException var17) { failureCause = var17; throw var17; } catch (IOException var18) { failureCause = var18; throw var18; } catch (Throwable var19) { failureCause = var19; throw new NestedServletException("Request processing failed", var19); } finally { /** * <7>默认previousLocaleContext previousAttributes 是null * 这里主要是为了将线程缓存的previousLocaleContext previousAttributes清空 */ this.resetContextHolders(request, previousLocaleContext, previousAttributes); if (requestAttributes != null) { requestAttributes.requestCompleted(); } if (this.logger.isDebugEnabled()) { if (failureCause != null) { this.logger.debug("Could not complete request", (Throwable)failureCause); } else if (asyncManager.isConcurrentHandlingStarted()) { this.logger.debug("Leaving response open for concurrent processing"); } else { this.logger.debug("Successfully completed request"); } } //spring事件机制 发布ServletRequestHandlerEvent消息,这个请求是否执行成功都会发布消息的 this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause); } }
<5>initContextHolders
private void initContextHolders(HttpServletRequest request, @Nullable LocaleContext localeContext, @Nullable RequestAttributes requestAttributes) { if (localeContext != null) { LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable); } if (requestAttributes != null) { RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable); } }
<31>getLocaleContext
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
->
org.springframework.context.i18n.LocaleContextHolder#getLocaleContext
//继承ThreadLocal private static final ThreadLocal<LocaleContext> localeContextHolder = new NamedThreadLocal("Locale context"); //继承inheritableThreadLocal 继承父线程的变量 但是子线程修改对父线程不可见(待测试) private static final ThreadLocal<LocaleContext> inheritableLocaleContextHolder = new NamedInheritableThreadLocal("Locale context"); public static LocaleContext getLocaleContext() { //先从先从ThreadLocal里面获取哦 LocaleContext localeContext = (LocaleContext)localeContextHolder.get(); if (localeContext == null) { //获取不到从inheritableThreadLocal 获取 localeContext = (LocaleContext)inheritableLocaleContextHolder.get(); } return localeContext; }
<32>getRequestAttributes
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
->
org.springframework.web.context.request.RequestContextHolder#getRequestAttributes
//继承ThreadLocal private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal("Request attributes"); //继承InheritableThreadLocal private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal("Request context"); public static RequestAttributes getRequestAttributes() { RequestAttributes attributes = (RequestAttributes)requestAttributesHolder.get(); if (attributes == null) { attributes = (RequestAttributes)inheritableRequestAttributesHolder.get(); } return attributes; }
<4>buildRequestAttributes
//如果之前没初始化过则构建一个新的 protected ServletRequestAttributes buildRequestAttributes(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable RequestAttributes previousAttributes) { return previousAttributes != null && !(previousAttributes instanceof ServletRequestAttributes) ? null : new ServletRequestAttributes(request, response); }
DispatcherServlet
<6>doService
org.springframework.web.servlet.FrameworkServlet#service
->
org.springframework.web.servlet.FrameworkServlet#processRequest
->
org.springframework.web.servlet.DispatcherServlet#doService
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { if (this.logger.isDebugEnabled()) { String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : ""; this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]"); } //如果是include请求,保存request attribute快照数据,并在finally中进行还原 Map<String, Object> attributesSnapshot = null; /** * request.getAttribute("javax.servlet.include.request_uri")!=null * <jsp:incluede page="xxx.jsp"/> * jsp里面嵌套上面这个标签 编译器后也是一个servlet来调用 通过这个属性判断是否是include标签 */ if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap(); Enumeration attrNames = request.getAttributeNames(); label108: while(true) { String attrName; do { if (!attrNames.hasMoreElements()) { break label108; } attrName = (String)attrNames.nextElement(); } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet")); attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } //保存ApplicationContext 到request request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext()); //保存localeResolver 到request request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); //保存themeResolver 到request request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); //保存gThemeSource 到request request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource()); //貌似是为了解决重定向302 带参数 长度问题 先保存到服务器 然后302重定向只需要带过来一个对应的key FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if (inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } //保存一个空的FlashMap request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); //保存flashMapManager request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); try { //<7>执行处理请求 this.doDispatch(request, response); } finally { //还原快照数据 if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) { this.restoreAttributesAfterInclude(request, attributesSnapshot); } } }
<7>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 { try { ModelAndView mv = null; Exception dispatchException = null; try { /** *<8> 如果配置了MultipartResolver 会调用 isMultipart() 方法判断请求中是否包含文件。 * 如果请求数据中包含文件,则调用 MultipartResolver 的 resolveMultipart() * 方法对请求的数据进行解析,然后将文件数据解析成 MultipartFile * 并封装在 MultipartHttpServletRequest (继承了 HttpServletRequest) 对象中并返回 */ processedRequest = this.checkMultipart(request); //是否被解析 multipartRequestParsed = processedRequest != request; //<9>通过HandlerMapping获得 HandlerExecutionChanin如:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping //org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMappin mappedHandler = this.getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { //<10>没获取到抛出404异常 this.noHandlerFound(processedRequest, response); return; } //<11>返回对应能处理的HandlerAdapter HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (this.logger.isDebugEnabled()) { this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { return; } } //<12>前置处理 拦截器 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } //<13>真正的处理方法 返回视图 没有视图则返回null mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //是否开启异步管理器 if (asyncManager.isConcurrentHandlingStarted()) { return; } //<14>设置默认的viewName this.applyDefaultViewName(processedRequest, mv); //<15>后置处理 拦截器 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception var19) { dispatchException = var19; } //<16> 处理正常和异常的请求调用结果。 this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception var20) { //<17>触发异常拦截器的AfterCompletion实现 this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20); } catch (Error var21) { //<17>触发异常拦截器的AfterCompletion实现 this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var21); } } finally { if (asyncManager.isConcurrentHandlingStarted()) { if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else if (multipartRequestParsed) { this.cleanupMultipart(processedRequest); } } }
<8>checkMultipart
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException { //是否配置了multipartResolver 并且是否能处理 if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) { if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) { this.logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, this typically results from an additional MultipartFilter in web.xml"); } else { if (!(request.getAttribute("javax.servlet.error.exception") instanceof MultipartException)) { //交给multipartResolver处理 并返回MultipartHttpServletRequest return this.multipartResolver.resolveMultipart(request); } this.logger.debug("Multipart resolution failed for current request before - skipping re-resolution for undisturbed error rendering"); } } return request; }
<9>getHandler
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //获得配置的handlerMapping Iterator var2 = this.handlerMappings.iterator(); HandlerExecutionChain handler; do { if (!var2.hasNext()) { return null; } HandlerMapping hm = (HandlerMapping)var2.next(); if (this.logger.isTraceEnabled()) { this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'"); } //适配 可参考org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler handler = hm.getHandler(request); } while(handler == null); return handler; }
<10>noHandlerFound
protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws Exception { if (pageNotFoundLogger.isWarnEnabled()) { pageNotFoundLogger.warn("No mapping found for HTTP request with URI [" + getRequestUri(request) + "] in DispatcherServlet with name '" + this.getServletName() + "'"); } if (this.throwExceptionIfNoHandlerFound) { throw new NoHandlerFoundException(request.getMethod(), getRequestUri(request), (new ServletServerHttpRequest(request)).getHeaders()); } else { response.sendError(404); } }
<11>getHandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { //获得所有的handlerAdapters Iterator var2 = this.handlerAdapters.iterator(); HandlerAdapter ha; do { if (!var2.hasNext()) { throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); } ha = (HandlerAdapter)var2.next(); if (this.logger.isTraceEnabled()) { this.logger.trace("Testing handler adapter [" + ha + "]"); } //每次调用 handlerAdapters 对supports 判断是否能处理这个Handler } while(!ha.supports(handler)); return ha; }
<12>applyPreHandle
org.springframework.web.servlet.HandlerExecutionChain#applyPreHandle
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { //获得所有拦截器 HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) { HandlerInterceptor interceptor = interceptors[i]; //执行前置拦截 if (!interceptor.preHandle(request, response, this.handler)) { //如果被拦截则触发拦截器的 完成后调用 this.triggerAfterCompletion(request, response, (Exception)null); return false; } } } return true; }
<14>applyDefaultViewName
org.springframework.web.servlet.DispatcherServlet#applyDefaultViewName
private void applyDefaultViewName(HttpServletRequest request, ModelAndView mv) throws Exception { //如果没有视图则设置默认视图 if (mv != null && !mv.hasView()) { // mv.setViewName(this.getDefaultViewName(request)); } } protected String getDefaultViewName(HttpServletRequest request) throws Exception { //通过viewNameTranslator 获得 我们可以自定义配置 return this.viewNameTranslator.getViewName(request); }
<15>applyPostHandle
org.springframework.web.servlet.HandlerExecutionChain#applyPostHandle
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception { //获得所有的拦截器 HandlerInterceptor[] interceptors = this.getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { //遍历执行后置拦截器 for(int i = interceptors.length - 1; i >= 0; --i) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(request, response, this.handler, mv); } } }
<16> processDispatchResult
org.springframework.web.servlet.DispatcherServlet#processDispatchResult
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception { boolean errorView = false; //是否发生了异常 if (exception != null) { //是否Controller正常处理返回ModelAndViewDefiningException if (exception instanceof ModelAndViewDefiningException) { this.logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException)exception).getModelAndView(); } else { Object handler = mappedHandler != null ? mappedHandler.getHandler() : null; //<18>触发异常拦截器 dispatcher init初始化 mv = this.processHandlerException(request, response, handler, exception); errorView = mv != null; } } if (mv != null && !mv.wasCleared()) { //<20>交给viewResolvers 查找视图 dispatcher init初始化 this.render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else if (this.logger.isDebugEnabled()) { this.logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + this.getServletName() + "': assuming HandlerAdapter completed request handling"); } if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { if (mappedHandler != null) { //<17>触发拦截器的AfterCompletion mappedHandler.triggerAfterCompletion(request, response, (Exception)null); } } }
<17>triggerAfterCompletion
private void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, Exception ex) throws Exception { if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, ex); } throw ex; } private void triggerAfterCompletionWithError(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, Error error) throws Exception { ServletException ex = new NestedServletException("Handler processing failed", error); if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, ex); } throw ex; } }
<18>processHandlerException
org.springframework.web.servlet.DispatcherServlet#processHandlerException
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { ModelAndView exMv = null; //获得所有的handlerExceptionResolver Iterator var6 = this.handlerExceptionResolvers.iterator(); while (var6.hasNext()) { HandlerExceptionResolver handlerExceptionResolver = (HandlerExceptionResolver) var6.next(); //执行官resolveException exMv = handlerExceptionResolver.resolveException(request, response, handler, ex); if (exMv != null) { break; } } //是否返回了异常view 比如404 view if (exMv != null) { if (exMv.isEmpty()) { request.setAttribute(EXCEPTION_ATTRIBUTE, ex); return null; } else { if (!exMv.hasView()) { exMv.setViewName(this.getDefaultViewName(request)); } if (this.logger.isDebugEnabled()) { this.logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex); } WebUtils.exposeErrorRequestAttributes(request, ex, this.getServletName()); return exMv; } } else { //抛出异常 throw ex; } }
<20>render
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { //调用localeResolver Locale locale = this.localeResolver.resolveLocale(request); response.setLocale(locale); View view; if (mv.isReference()) {
//<21>根据viewResolver获得view view = this.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 '" + this.getServletName() + "'"); } } else { //获得view view = mv.getView(); if (view == null) { throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + "View object in servlet with name '" + this.getServletName() + "'"); } } if (this.logger.isDebugEnabled()) { this.logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + this.getServletName() + "'"); } try { //解析 view.render(mv.getModelInternal(), request, response); } catch (Exception var7) { if (this.logger.isDebugEnabled()) { this.logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" + this.getServletName() + "'", var7); } throw var7; } }
<21>resolveViewName
org.springframework.web.servlet.DispatcherServlet#resolveViewName
protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale, HttpServletRequest request) throws Exception { //viewResolvers dispatcher init初始化 Iterator var5 = this.viewResolvers.iterator(); View view; do { if (!var5.hasNext()) { return null; } ViewResolver viewResolver = (ViewResolver)var5.next(); //调用viewResolver 传入viewname查找视图 view = viewResolver.resolveViewName(viewName, locale); } while(view == null); return view; }
总结
1.当一个请求来到FrameworkServlet最先收到请求
2.交给父类httpServlet 父类根据请求方法做分发到FrameworkServlet的对应doGet doPost等方法
3.doGet doPost 对应方法做一些特殊处理之后最终调用FrameworkServlet.processRequest 处理如:初始化requset域
4.然后调用doService 由DispatcherServlet实现
1.根据request获得对应的Handler
2.根据Handler获取对应的HandlerAdapter
3.执行前置拦截器
4.执行请求返回ModelView
5.执行后置请求
6.根据modelView进行处理 如果是视图则根据viewResolvers 查找对应的view