DispatcherServlet的请求处理流程

本文介绍DispatcherServlet对请求的处理流程。基于Spring 4.2.2。

向DispatcherServlet发起get或post请求时,会交给DispathcerServlet的doGet和doPost方法处理,这两个方法把请求又统一交给processRequest(继承自FrameworkServlet)方法处理。

processRequest方法的关键代码:

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

    long startTime = System.currentTimeMillis();
    Throwable failureCause = null;

    //获得和当前线程相关的LocaleContext,如果没有返回null
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();

    //为request创建一个LocaleContext实例,将request的primary locale作为当前的locale;
    LocaleContext localeContext = buildLocaleContext(request);

    //返回绑定到当前线程的RequestAttributes
    RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();

    //为当前request创建ServletRequestAttributes
    ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);

    //把根据当前request创建的LocaleContext和RequestAttributes绑定到当前线程;
    initContextHolders(request, localeContext, requestAttributes);

    try{
        doService(request, response);
    }finally {
        //请求处理结束后,恢复线程到原始状态,恢复LocaleContext和RequestAttributes;
        resetContextHolders(request, previousLocaleContext, previousAttributes);
        if (requestAttributes != null) {
            requestAttributes.requestCompleted();
        }

        //请求处理结束后,发布事件通知
        publishRequestHandledEvent(request, response, startTime, failureCause);
    }
}

接下来跟进doService方法。doService方法的关键代码:

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {

    //将框架级的Object放到request中,使得对于handler和view objects可见;
    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());

    //获取一个之前的request存储的且和当前request匹配的FlashMap,然后把它从存储中移除,并且移除其他已过期的FlashMap实例;
    FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
    if (inputFlashMap != null) {
        //将inputFlashMap的只读视图放置到request;
        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);

    doDispatch(request, response);
}

doService主要做了准备工作,把一些接下来要用到的实例放到了request中,比如,localeResolver、themeResolver、flashmap。

继续跟进doDispatch方法。

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;

    try {
        ModelAndView mv = null;
        Exception dispatchException = null;

        try {
            //如果request是multipart类型(request.getContentType()的值以multipart/开始的),就把request转换为MultipartHttpServletRequest类型的request;
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            // 为当前的request获取Handler
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null || mappedHandler.getHandler() == null) {
                //找不到对应的Handler,就像返回404错误;
                noHandlerFound(processedRequest, response);
                return;
            }

            // 为当前request找到匹配的HandlerAdapter
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

    //请求已注册interceptor的preHandle方法;
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            // 实际调用handler,返回ModelAndView
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

            //如果Handler没有返回View对象,需要借助ViewNameTranslator接口的getViewName方法来获取一个逻辑视图名;
            applyDefaultViewName(processedRequest, mv);

            //请求已注册interceptor的postHandle方法;
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        }
        catch (Exception ex) {
            dispatchException = ex;
        }

        //处理调用handler返回的结果:一个ModelAndView,或者是需要转化为一个ModelAndView的Exception
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    }
    catch (Exception ex) {
        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    }
    catch (Error err) {
        triggerAfterCompletionWithError(processedRequest, response, mappedHandler, 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);
            }
        }
    }
}

把这个方法中的关键点拿出来分析。

1)mappedHandler = getHandler(processedRequest);

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    //按顺序遍历已加载的实现了HandlerMapping接口的bean,如果某个handlerMapping可以用request返回Handler,遍历结束;
    for (HandlerMapping hm : this.handlerMappings) {
        HandlerExecutionChain handler = hm.getHandler(request);
        if (handler != null) {
            return handler;
        }
    }
    return null;
}

handlerMapping是如何根据request获取到对应的handler?Handler和HandlerExecutionChain又是什么关系?
以org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping为例,因为以@RequestMapping标注的方法主要使用这个handlerMapping来寻找handler。它的getHandler()方法继承自AbstractHandlerMapping(final修饰)。

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);
    }

    //为handler构建一个HandlerExectionChain实例,这个实例将加入可用的interceptor; HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

    return executionChain;
}

getHandlerInternal(request)方法在AbstractHandlerMapping定义为抽象方法,由RequestMappingHandlerMapping的父类AbstractHandlerMethodMapping负责实现。

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    this.mappingRegistry.acquireReadLock();
    try {
        HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
        return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
    }
    finally {
        this.mappingRegistry.releaseReadLock();
    }
}

跟进lookupHandlerMethod(lookupPath, request)方法:

//Look up the best-matching handler method for the current request.
//If multiple matches are found, the best match is selected.
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
    List<Match> matches = new ArrayList<Match>();

    //Return matches for the given URL path. Not thread-safe.
    List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
    if (directPathMatches != null) {
        addMatchingMappings(directPathMatches, matches, request);
    }

    if (matches.isEmpty()) {
        // No choice but to go through all mappings...
    addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
    }

    if (!matches.isEmpty()) {
        Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
        Collections.sort(matches, comparator);
        if (logger.isTraceEnabled()) {
            logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
                    lookupPath + "] : " + matches);
        }
        Match bestMatch = matches.get(0);
        if (matches.size() > 1) {
            if (CorsUtils.isPreFlightRequest(request)) {
                return PREFLIGHT_AMBIGUOUS_MATCH;
            }
            Match secondBestMatch = matches.get(1);
            if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                Method m1 = bestMatch.handlerMethod.getMethod();
                Method m2 = secondBestMatch.handlerMethod.getMethod();
                throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
                        request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
            }
        }
        handleMatch(bestMatch.mapping, lookupPath, request);
        return bestMatch.handlerMethod;
    }
    else {
        return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
    }
}

getMappingsByUrl方法:

public List<T> getMappingsByUrl(String urlPath) {
    return this.urlLookup.get(urlPath);
}

其中this.urlLookup是LinkedMultiValueMap< String, T>类型,里面存储的内容是key-value对(以下内容为示例)

{/admin/getUserName=[{[/admin/getUserName]}], /admin/{id}/getRightNavs=[{[/admin/{id}/getRightNavs]}]}

遍历所有映射:

private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
    for (T mapping : mappings) {
        T match = getMatchingMapping(mapping, request);
        if (match != null) {
            matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping)));
        }
    }
}

不再继续跟进了,总之根据url获取到要调用的某个类的某个方法,以后有时间再跟进。

2)HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    for (HandlerAdapter ha : this.handlerAdapters) {
        if (ha.supports(handler)) {
            return ha;
        }
    }
}

对已加载的实现了HandlerAdapter接口的bean遍历,直到某个handlerAdapter匹配。默认加载三个handlerAdapter:

RequestMappingHandlerAdapter;
HttpRequestHandlerAdapter;
SimpleControllerHandlerAdapter;

Debug跟进代码,发现排在第一位的RequestMappingHandlerAdapter就可以support,所以就返回了RequestMappingHandlerAdapter。

3)processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

参考: http://blog.csdn.net/u012006689/article/details/51183615

你可能感兴趣的:(DispatcherServlet的请求处理流程)