Spring MVC原理(二)请求处理流程源码分析

来源:互联网 发布:网络管理书籍推荐 编辑:程序博客网 时间:2024/06/05 20:56

请求的大概处理流程请参考这篇文章,这里摘来一张图。
http://www.jianshu.com/p/85a30095245e

这里写图片描述

DispatcherServlet作为流程控制的中心,整个请求的处理都是围绕这个servlet来进行。由名称可以看出这是一个servlet,具备普通servlet的所有的性质,既然是servlet肯定要在web.xml中配置,具体配置参考上面的文章。下面直接分析源码:

一个请求过来,只要是符合DispatcherServlet的拦截规则,web容器就会调用其doGet/doPost方法。

DispatcherServlet的继承体系和处理时序如下图所示:
这里写图片描述

DispatcherServlet的doGet/doPost方法的实现在其父类FrameworkServlet里面,

    /**     * Delegate GET requests to processRequest/doService.     * <p>Will also be invoked by HttpServlet's default implementation of {@code doHead},     * with a {@code NoBodyResponse} that just captures the content length.     * @see #doService     * @see #doHead     */    @Override    protected final void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        processRequest(request, response);    }    /**     * Delegate POST requests to {@link #processRequest}.     * @see #doService     */    @Override    protected final void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        processRequest(request, response);    }

这里以Get方法为例分析整个处理过程:
(源码中省略了一些注释或者不重要的片段)

    protected final void processRequest(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        long startTime = System.currentTimeMillis();        Throwable failureCause = null;        LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();        LocaleContext localeContext = buildLocaleContext(request);        RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();        ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);        asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());        initContextHolders(request, localeContext, requestAttributes);        try {            //doService的实现在DispatchServlet中            doService(request, response);        }        catch (ServletException ex) {            failureCause = ex;            throw ex;        }        catch (IOException ex) {            failureCause = ex;            throw ex;        }        catch (Throwable ex) {            failureCause = ex;            throw new NestedServletException("Request processing failed", ex);        }        finally {            resetContextHolders(request, previousLocaleContext, previousAttributes);            if (requestAttributes != null) {                requestAttributes.requestCompleted();            }            publishRequestHandledEvent(request, response, startTime, failureCause);        }    }
    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {        // Keep a snapshot of the request attributes in case of an include,        // to be able to restore the original attributes after the include.        Map<String, Object> attributesSnapshot = null;        if (WebUtils.isIncludeRequest(request)) {            attributesSnapshot = new HashMap<String, Object>();            Enumeration<?> attrNames = request.getAttributeNames();            while (attrNames.hasMoreElements()) {                String attrName = (String) attrNames.nextElement();                if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {                    attributesSnapshot.put(attrName, request.getAttribute(attrName));                }            }        }        // Make framework objects available to handlers and 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());        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);                }            }        }    }
    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);                // Determine handler for the current request.                // 根据当前请求查找合适的处理器Handler                mappedHandler = getHandler(processedRequest);                if (mappedHandler == null || mappedHandler.getHandler() == null) {                    noHandlerFound(processedRequest, response);                    return;                }                // Determine handler adapter for the current request.                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 (logger.isDebugEnabled()) {                        logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);                    }                    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(request, mv);                mappedHandler.applyPostHandle(processedRequest, response, mv);            }            catch (Exception ex) {                dispatchException = ex;            }            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);                }            }        }    }
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {        /*         * HandlerMapping的作用是找到URL匹配的Handler对象,这里注册的HandlerMapping(handlerMappings中的元素)有三个:         * 1)BeanNameUrlHandlerMapping: bean的name和url匹配         *   要求任何有可能处理请求的Bean都要起一个以反斜杠(/)字符开头的名称或者别名,这个名称或者别名可以是符合URL Path匹配原则中的任何名字。         *   它不能影射一个Prototype的Bean.换句话说,当使用 BeanNameUrlHandlerMapping时,所有的请求处理类只能是单例的(singletons) . 一般来              *   说,Controllers 都是按照单例建立的,所以这个并不是一个很严重的问题。         * 2)SimpleUrlHandlerMapping :直接匹配url和对应的bean(在mvc配置文件中配置,url和bean一一对应)         *   由于BeanNameUrlHandlerMapping机制中URL和Handler是绑定在一起的,所以无法配置更为复杂的Mapping关系,SimpleUrlHandlerMapping          *   可以看做是其的高级版,能够配置复杂的路径匹配关系,可以配置多组映射关系,把不同的URL映射到同一个handler对象。         * 3)RequestMappingHandlerMapping:专门处理注解@RequestMapping配置的类,和RequestMappingHandlerAdapter 对应起来使用         */        for (HandlerMapping hm : this.handlerMappings) {             /*              * 遍历所有的HandlerMapping,找到能够处理当前request的一个              */            HandlerExecutionChain handler = hm.getHandler(request);            if (handler != null) {                return handler;            }        }        return null;    }
    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);        }        return getHandlerExecutionChain(handler, request);    }
    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {        //拿到请求的url        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);        if (logger.isDebugEnabled()) {            logger.debug("Looking up handler method for path " + lookupPath);        }        //根据请求的路径URL找到对应的处理方法(controller里的方法)        HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);        if (logger.isDebugEnabled()) {            if (handlerMethod != null) {                logger.debug("Returning handler method [" + handlerMethod + "]");            }            else {                logger.debug("Did not find handler method for [" + lookupPath + "]");            }        }        return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);    }
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {        List<Match> matches = new ArrayList<Match>();        /*         * this.urlMap放的是当前这个HandlerMapping对象类型处理的URL和handler         * 在Spring容器启动阶段,就已经把mvc配置文件或者controller类注解的映射关系添加到了         * urlMap里面,以匹配的URL作为键值。         */        List<T> directPathMatches = this.urlMap.get(lookupPath);        if (directPathMatches != null) {            addMatchingMappings(directPathMatches, matches, request);        }        if (matches.isEmpty()) {            // No choice but to go through all mappings...            addMatchingMappings(this.handlerMethods.keySet(), matches, request);        }        if (!matches.isEmpty()) {            Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));            Collections.sort(matches, comparator);            Match bestMatch = matches.get(0);            if (matches.size() > 1) {                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(handlerMethods.keySet(), lookupPath, request);        }    }
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {         /*          * HandlerAdapter的作用是确定Handler对象中的哪个方法来处理当前URL,这里注册的HandlerAdapter有三种:          * 1)HttpRequestHandlerAdapter:要求handler(controller)实现HttpRequestHandler接口          * 2)SimpleControllerHandlerAdapter:要求handler实现Controller接口          * 3)RequestMappingHandlerAdapter:和RequestMappingHandlerMapping配对使用,专门处理@RequestMapping 注解的类和方法          */        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");    }
1 0
原创粉丝点击