美文网首页
DispatcherServlet处理流程

DispatcherServlet处理流程

作者: aix91 | 来源:发表于2019-03-13 21:04 被阅读0次

    1. 请求流程

    DispatcherServlet继承了HttpServlet,在Http请求过来时,会先调用HttpServlet的service方法,将ServletRequest,ServletReponse 转换成HttpServletRequest,HttpServletResponse,再来调用子类的service的方法,也就是FramworkServlet的service方法

    @Override
        protected void service(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
            if (HttpMethod.PATCH == httpMethod || httpMethod == null) {
                processRequest(request, response);
            }
            else {
                super.service(request, response);
            }
        }
    

    当请求是GET类型时,会返回HttpServlet类调用service方法;HttpServlet中开放类doGet方法给子类实现。在FrameworkServlet中,我们找到了doGet的实现

        protected final void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            processRequest(request, response);
        }
    

    Debug来到DispatcherServlet的doService 方法

    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
            
            ...
            request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
            request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
            request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
            request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
    
            FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
            if (inputFlashMap != null) {
                request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
            }
            request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
            request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
    
            try {
                doDispatch(request, response);
            }
            finally {
                if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
                    // Restore the original attribute snapshot, in case of an include.
                    if (attributesSnapshot != null) {
                        restoreAttributesAfterInclude(request, attributesSnapshot);
                    }
                }
            }
        }
    

    可以看到在doService方法中将localeResolver,themeResolver等设置在Request中,真正的请求处理在doDispatch方法中。

    2. 请求处理

    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
                    mappedHandler = getHandler(processedRequest);
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        noHandlerFound(processedRequest, response);
                        return;
                    }
                    // 获取handlerAdapter
                    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
                    // Process last-modified header, if supported by the handler.
                    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.
                    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) {
                    dispatchException = new NestedServletException("Handler dispatch failed", err);
                }
                processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
            }
            ...
        }
    
    • 根据request找到HandlerExecutionChain
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            for (HandlerMapping hm : this.handlerMappings) {
                if (logger.isTraceEnabled()) {
                    logger.trace(
                            "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
                }
                HandlerExecutionChain handler = hm.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
            return null;
        }
    

    DispatcherServlet初始化中,可以知道,默认情况下,handlerMappings会加载BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping。
    一旦根据request找到类相应的handler,就返回。以DefaultAnnotationHandlerMapping来看看如何根据request取到HandlerExecutionChain。

        public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            Object handler = getHandlerInternal(request);
            if (handler == null) {
                handler = getDefaultHandler();
            }
            if (handler == null) {
                return null;
            }
            // Bean name or resolved handler?
            if (handler instanceof String) {
                String handlerName = (String) handler;
                handler = getApplicationContext().getBean(handlerName);
            }
    
            HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
            if (CorsUtils.isCorsRequest(request)) {
                CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
                CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
                CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
                executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
            }
            return executionChain;
        }
    

    这里我们不关心具体是如何取到handler的,我们看为什么要把handler转换成HandlerExecutionChain。

    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
            HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
                    (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
    
            String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
            for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
                if (interceptor instanceof MappedInterceptor) {
                    MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
                    if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                        chain.addInterceptor(mappedInterceptor.getInterceptor());
                    }
                }
                else {
                    chain.addInterceptor(interceptor);
                }
            }
            return chain;
        }
    

    在生成HandlerExecutionChain的时候,添加了拦截器,那么在真正执行handler的方法时,可以执行拦截器方法。

    • 根据handler找到HandlerAdapter
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
            for (HandlerAdapter ha : this.handlerAdapters) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Testing handler adapter [" + ha + "]");
                }
                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");
        }
    

    默认会加载三个HandlerAdapter到容器中 :HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、AnnotationMethodHandlerAdapter。
    DispatcherServlet会根据controller实现方式来选择相应的adapter来生成ModelAndView

    相关文章

      网友评论

          本文标题:DispatcherServlet处理流程

          本文链接:https://www.haomeiwen.com/subject/pnxxmqtx.html