zoukankan      html  css  js  c++  java
  • DispatcherServlet类的分析

    突然发现拿博客园来做笔记挺好的,不会弄丢。下面我把DispatcherServlet类的部分源代码复制到这里,然后阅读,把重要的地方翻译一下,该做笔记的地方做下笔记,蹩脚英语。

     =================下面是类定义以及类注释的一些翻译,还需要进行修改。=================

     /**

     * Central dispatcher for HTTP request handlers/controllers, e.g. for web UI controllers
     * or HTTP-based remote service exporters. Dispatches to registered handlers for processing
     * a web request, providing convenient mapping and exception handling facilities.
     * 上文大致意思:Dispather是将HTTP请求分配给handlers/controllers的主要中心。比如对于,,,,,。 分配器注册调用处理器到WEB请求中,为映射和异常处理提供方便。

    * <p>This servlet is very flexible: It can be used with just about any workflow, with the * installation of the appropriate adapter classes. It offers the following functionality * that distinguishes it from other request-driven web MVC frameworks: * 这个servlet非常的灵活。它安装上适当的适配器类后,可以用在任何工作流程中。它提供了一下功能来区分WEB MVC框架的其他请求驱动。^o^好像不太对^o^ * <ul> * <li>It is based around a JavaBeans configuration mechanism. * 他是基于JavaBean的配置原理。
    * * <li>It can use any {
    @link HandlerMapping} implementation - pre-built or provided as part * of an application - to control the routing of requests to handler objects. Default is * {@link org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping} and * {@link org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping}. * HandlerMapping objects can be defined as beans in the servlet's application context, * implementing the HandlerMapping interface, overriding the default HandlerMapping if * present. HandlerMappings can be given any bean name (they are tested by type). * * <li>It can use any {@link HandlerAdapter}; this allows for using any handler interface. * Default adapters are {@link org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter}, * {@link org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter}, for Spring's * {@link org.springframework.web.HttpRequestHandler} and * {@link org.springframework.web.servlet.mvc.Controller} interfaces, respectively. A default * {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter} * will be registered as well. HandlerAdapter objects can be added as beans in the * application context, overriding the default HandlerAdapters. Like HandlerMappings, * HandlerAdapters can be given any bean name (they are tested by type). * * <li>The dispatcher's exception resolution strategy can be specified via a * {@link HandlerExceptionResolver}, for example mapping certain exceptions to error pages. * Default are * {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver}, * {@link org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver}, and * {@link org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver}. * These HandlerExceptionResolvers can be overridden through the application context. * HandlerExceptionResolver can be given any bean name (they are tested by type). * * <li>Its view resolution strategy can be specified via a {@link ViewResolver} * implementation, resolving symbolic view names into View objects. Default is * {@link org.springframework.web.servlet.view.InternalResourceViewResolver}. * ViewResolver objects can be added as beans in the application context, overriding the * default ViewResolver. ViewResolvers can be given any bean name (they are tested by type). * * <li>If a {@link View} or view name is not supplied by the user, then the configured * {@link RequestToViewNameTranslator} will translate the current request into a view name. * The corresponding bean name is "viewNameTranslator"; the default is * {@link org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator}. * * <li>The dispatcher's strategy for resolving multipart requests is determined by a * {@link org.springframework.web.multipart.MultipartResolver} implementation. * Implementations for Apache Commons FileUpload and Servlet 3 are included; the typical * choice is {@link org.springframework.web.multipart.commons.CommonsMultipartResolver}. * The MultipartResolver bean name is "multipartResolver"; default is none. * * <li>Its locale resolution strategy is determined by a {@link LocaleResolver}. * Out-of-the-box implementations work via HTTP accept header, cookie, or session. * The LocaleResolver bean name is "localeResolver"; default is * {@link org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver}. * * <li>Its theme resolution strategy is determined by a {@link ThemeResolver}. * Implementations for a fixed theme and for cookie and session storage are included. * The ThemeResolver bean name is "themeResolver"; default is * {@link org.springframework.web.servlet.theme.FixedThemeResolver}. * </ul> *======================================新的开始======================================
    * * <p><b>NOTE: The {
    @code @RequestMapping} annotation will only be processed if a * corresponding {@code HandlerMapping} (for type-level annotations) and/or * {@code HandlerAdapter} (for method-level annotations) is present in the dispatcher.</b> * This is the case by default. However, if you are defining custom {@code HandlerMappings} * or {@code HandlerAdapters}, then you need to make sure that a corresponding custom * {@code DefaultAnnotationHandlerMapping} and/or {@code AnnotationMethodHandlerAdapter} * is defined as well - provided that you intend to use {@code @RequestMapping}. * @RequestMapping 注解将会,,,,,,。但是,你还可以自定义HandlerMapping注解或HandlerAdapter,接着你要确保有一个自定义DefaultAnnotationHandlerMapping
    * 或者是AnnotationMethodHandlerAdapter 也已经定义好了--这是为你想要使用@RequestMapping提供的。
    * * <p><b>A web application can define any number of DispatcherServlets.</b> * Each servlet will operate in its own namespace, loading its own application context * with mappings, handlers, etc. Only the root application context as loaded by * {
    @link org.springframework.web.context.ContextLoaderListener}, if any, will be shared. * 一个WEB应用可以定义任何数量的DispatcherServlet。每个DispatcherServlet都只会操作它们自己的命名空间,用映射、处理器等来加载应用上下文。
    * 如果有的话,只会有一个根应用上下文,它将被ContextLoaderListener监听器加载,它将会被共享。
    * * <p>As of Spring 3.1, {
    @code DispatcherServlet} may now be injected with a web * application context, rather than creating its own internally. This is useful in Servlet * 3.0+ environments, which support programmatic registration of servlet instances. * See the {@link #DispatcherServlet(WebApplicationContext)} javadoc for details. * * @author Rod Johnson * @author Juergen Hoeller * @author Rob Harrop * @author Chris Beams * @author Rossen Stoyanchev * @see org.springframework.web.HttpRequestHandler * @see org.springframework.web.servlet.mvc.Controller * @see org.springframework.web.context.ContextLoaderListener */ @SuppressWarnings("serial") public class DispatcherServlet extends FrameworkServlet {
    
    
    }

    ========================下面是这个类的部分比较重要的属性========================

        /** MultipartResolver used by this servlet */
        private MultipartResolver multipartResolver; 
    
        /** LocaleResolver used by this servlet */
        private LocaleResolver localeResolver;
    
        /** ThemeResolver used by this servlet */
        private ThemeResolver themeResolver;
    
        /** List of HandlerMappings used by this servlet */
        private List<HandlerMapping> handlerMappings;   //处理器映射列表
    
        /** List of HandlerAdapters used by this servlet */
        private List<HandlerAdapter> handlerAdapters;   //处理器适配器列表
    
        /** List of HandlerExceptionResolvers used by this servlet */
        private List<HandlerExceptionResolver> handlerExceptionResolvers; //处理器异常解析器列表
    
        /** RequestToViewNameTranslator used by this servlet */
        private RequestToViewNameTranslator viewNameTranslator;
    
        /** FlashMapManager used by this servlet */
        private FlashMapManager flashMapManager;
    
        /** List of ViewResolvers used by this servlet */
        private List<ViewResolver> viewResolvers; //视图解析器列表

    ============================下面是类的无参构造器============================

    /**
         * Create a new {@code DispatcherServlet} that will create its own internal web
         * application context based on defaults and values provided through servlet
         * init-params. Typically used in Servlet 2.5 or earlier environments, where the only
         * option for servlet registration is through {@code web.xml} which requires the use
         * of a no-arg constructor.
         * <p>Calling {@link #setContextConfigLocation} (init-param 'contextConfigLocation')
         * will dictate which XML files will be loaded by the
         * {@linkplain #DEFAULT_CONTEXT_CLASS default XmlWebApplicationContext}
         * <p>Calling {@link #setContextClass} (init-param 'contextClass') overrides the
         * default {@code XmlWebApplicationContext} and allows for specifying an alternative class,
         * such as {@code AnnotationConfigWebApplicationContext}.
         * <p>Calling {@link #setContextInitializerClasses} (init-param 'contextInitializerClasses')
         * indicates which {@code ApplicationContextInitializer} classes should be used to
         * further configure the internal application context prior to refresh().
         * @see #DispatcherServlet(WebApplicationContext)
    *
    */ public DispatcherServlet() { super(); setDispatchOptionsRequest(true); }

     =================下面是initStrategies(ApplicationContext context)方法=================

    主要是初始化上面提到的部分重要属性。

        //初始化这个DispatcherServlet使用到的策略对象。这个方法有可能会被子类覆盖。
        protected void initStrategies(ApplicationContext context) {
            initMultipartResolver(context);
            initLocaleResolver(context);
            initThemeResolver(context);
            /* 
          * 查找 ApplicationContext 中所有的 HandlerMapping,并按顺序存储到 handlerMappings 这个属性中。
    * 如果一个都没找到则将一个默认的HandlerMapping注册到handlerMappings 属性中。

    */
    initHandlerMappings(context);

    /*
    * 查找 ApplicationContext 中所有的 HandlerAdapter,并按一定的顺序存储到 handlerAdapters 这个属性中。
    * 如果一个都没有找到则将一个默认的 HandlerAdapter 注册到 handlerAdapters 属性中。
    */
    initHandlerAdapters(context);
            initHandlerExceptionResolvers(context);
            initRequestToViewNameTranslator(context);
            initViewResolvers(context);
            initFlashMapManager(context);
        }

     ========================下面是DispatherServlet的doService()方法==================

        /**
         * Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}
         * for the actual dispatching.
         */
      //这才是重要的地方。
    
        @Override
        protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
            if (logger.isDebugEnabled()) {
                String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
                logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
                        " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
            }
    
            // Keep a snapshot of the request attributes in case of an include,
            // to be able to restore the original attributes after the include.
         //将传进来的请求request属性以属性名为键,属性为值,放入到一个Map对象 attributesSnapshot 中。
    //因为接下来的处理会使request的属性放生以便下面的finally语句块中恢复request原来的属性。
    //这个map对象起到了暂时存储的作用。 因为接下来的处理会使request的属性发生改变。 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请求的属性中,提供给处理器对象和视图对象使用。^o^不知道对不对,暂时这么理解^o^ 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);//恢复request的属性。 } } } }

    =========================================================================

    /**
         * Process the actual dispatching to the handler.
         * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
         * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
         * to find the first that supports the handler class.
         * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
         * themselves to decide which methods are acceptable.
         * @param request current HTTP request
         * @param response current HTTP response
         * @throws Exception in case of any kind of processing failure
         */
        /*
        重中之重       
         */
        protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
            HttpServletRequest processedRequest = request;
            HandlerExecutionChain mappedHandler = null;
            boolean multipartRequestParsed = false;
         //从当前request请求获取一个WEB异步管理器,如果没有的话就根据request请求创建一个。
            WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
            try {
                ModelAndView mv = null;
                Exception dispatchException = null;
    
                try {
               //将request请求转换为一个multipart请求,并且使 multipart resolver 变为可用的。如果multipart resolver不存在,则直接使用存在的请求。
                    processedRequest = checkMultipart(request);
                    multipartRequestParsed = (processedRequest != request);
    
                    // Determine handler for the current request.
               //在 handlerMappings 中为请求查找对应的handler,没有就返回null。
                    mappedHandler = getHandler(processedRequest);
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        noHandlerFound(processedRequest, response);
                        return;
                    }
    
                    // Determine handler adapter for the current request.
              // 在handlerAdapters中为请求查找合适的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 (logger.isDebugEnabled()) {
                            logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                        }
                        if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }
              //执行HandlerExecutionChain中的拦截器的preHandler()方法。
                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
    
                    // Actually invoke the handler.这才是真正的调用handler
              // 使用指定的handler来处理请求。
              // 返回一个拥有视图名称和模型数据的ModelAndView对象,如果请求已经直接被调用了则返回null。
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
    
                    applyDefaultViewName(processedRequest, mv);
              //执行HandlerExecutionChain中的拦截器的postHandler()方法。
    mappedHandler.applyPostHandle(processedRequest, response, mv); }
    catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); }        //渲染视图,接着执行 HandlerExecutionChain 中的afterCompletion()方法。
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); }
    catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", 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); } } } }

    =========================================================================

      /**
         * Return the HandlerExecutionChain for this request.
         * <p>Tries all handler mappings in order.
         * @param request current HTTP request
         * @return the HandlerExecutionChain, or {@code null} if no handler could be found
         */
        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;
        }

    =========================================================================

     /**
         * Render the given ModelAndView.
         * <p>This is the last stage in handling a request. It may involve resolving the view by name.
         * @param mv the ModelAndView to render
         * @param request current HTTP servlet request
         * @param response current HTTP servlet response
         * @throws ServletException if view is missing or cannot be resolved
         * @throws Exception if there's a problem rendering the view
         */
        protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
            // Determine locale for request and apply it to the response.
            Locale locale = this.localeResolver.resolveLocale(request);
            response.setLocale(locale);
    
            View view;
            if (mv.isReference()) {
                // We need to resolve the view name.
                view = 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 '" + getServletName() + "'");
                }
            }
            else {
                // No need to lookup: the ModelAndView object contains the actual View object.
                view = mv.getView();
                if (view == null) {
                    throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
                            "View object in servlet with name '" + getServletName() + "'");
                }
            }
    
            // Delegate to the View object for rendering.
            if (logger.isDebugEnabled()) {
                logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
            }
            try {
                if (mv.getStatus() != null) {
                    response.setStatus(mv.getStatus().value());
                }
                view.render(mv.getModelInternal(), request, response);
            }
            catch (Exception ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
                            getServletName() + "'", ex);
                }
                throw ex;
            }
        }

    =========================================================================

     /**
         * Resolve the given view name into a View object (to be rendered).
         * <p>The default implementations asks all ViewResolvers of this dispatcher.
         * Can be overridden for custom resolution strategies, potentially based on
         * specific model attributes or request parameters.
         * @param viewName the name of the view to resolve
         * @param model the model to be passed to the view
         * @param locale the current locale
         * @param request current HTTP servlet request
         * @return the View object, or {@code null} if none found
         * @throws Exception if the view cannot be resolved
         * (typically in case of problems creating an actual View object)
         * @see ViewResolver#resolveViewName
         */
        protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
                HttpServletRequest request) throws Exception {
    
            for (ViewResolver viewResolver : this.viewResolvers) {
                View view = viewResolver.resolveViewName(viewName, locale);
                if (view != null) {
                    return view;
                }
            }
            return null;
        }

    =========================================================================

    =========================================================================

    =========================================================================

    =========================================================================

    =========================================================================

  • 相关阅读:
    HDU 5818 Joint Stacks
    HDU 5816 Hearthstone
    HDU 5812 Distance
    HDU 5807 Keep In Touch
    HDU 5798 Stabilization
    HDU 5543 Pick The Sticks
    Light OJ 1393 Crazy Calendar (尼姆博弈)
    NEFU 2016省赛演练一 I题 (模拟题)
    NEFU 2016省赛演练一 F题 (高精度加法)
    NEFU 2016省赛演练一 B题(递推)
  • 原文地址:https://www.cnblogs.com/GooPolaris/p/7110588.html
Copyright © 2011-2022 走看看