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

 

posted @ 2020-01-16 18:02  意犹未尽  阅读(455)  评论(0编辑  收藏  举报