Spring MVC中DispatcherServlet理解总结(1)

260 阅读4分钟

DispatcherServlet在web.xml中的配置

<context-param>
    <!--默认配置文件为/WEB-INF/[servlet名字]-servlet.xml-->
    <param-name>contextConfigLocation</param-name>
    <param-value>WebApplicationContext的上下文配置</param-value>
</context-param>
<!--在启动Web 容器时,自动装配Spring的配置信息-->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
    <servlet-name>SpringMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--此处没有配置contextConfigLocation,默认用WebApplicationContext的上下文配置-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/spring/spring-mvc.xml</param-value>
    </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>请求映射</url-pattern>
</servlet-mapping>
  • context-param中contextConfigLocation参数,指定用于加载Bean的配置文件,比如加载除Web层的DAO、Service等
  • servlet的init-param中contextConfigLocation参数,指定用于初始化Spring Web MVC框架上下文的配置文件。如果没有配置,默认用context-param中contextConfigLocation参数配置文件
  • ContextLoaderListener作用:在启动Web 容器时,自动装配Spring的配置信息。
    • ContextLoaderListener初始化的上下文加载的Bean是对于整个应用程序共享的;
    • DispatcherServlet初始化的上下文只加载Web相关组件,如Controller、HandlerMapping、HandlerAdapter等等

DispatcherServlet初始化顺序

继承体系:DispatcherServlet->FrameworkServlet->HttpServletBean->HttpServlet

  • 第一步:调用HttpServletBean的init()方法,将始化参数设置到该组件上
public abstract class HttpServletBean extends HttpServlet implements EnvironmentAware{
    @Override
    public final void init() throws ServletException {
       //......
       //1、将配置文件中的contextConfigLocation初始化参数等设置到该组件,如设置FrameworkServlet的contextConfigLocation属性
       try {
           PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
           // 扩展阅读BeanWrapper
           BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
           ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
           bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
           initBeanWrapper(bw);
           bw.setPropertyValues(pvs, true);
       }
       catch (BeansException ex) {
           //…………省略其他代码
       }
       //2、提供给子类初始化的扩展点,该方法由FrameworkServlet覆盖
       initServletBean();
       if (logger.isDebugEnabled()) {
           logger.debug("Servlet '" + getServletName() + "' configured successfully");
       }
    }
    //…………省略其他代码
    private static class ServletConfigPropertyValues extends MutablePropertyValues {
        public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties) throws ServletException {
            Set<String> missingProps = requiredProperties != null && !requiredProperties.isEmpty() ? new HashSet(requiredProperties) : null;
            // 读取servlet的init-param中contextConfigLocation参数
            Enumeration en = config.getInitParameterNames();
    
            while(en.hasMoreElements()) {
                String property = (String)en.nextElement();
                Object value = config.getInitParameter(property);
                this.addPropertyValue(new PropertyValue(property, value));
                if (missingProps != null) {
                    missingProps.remove(property);
                }
            }
        }
    }
}

扩展阅读BeanWrapper:[blog.csdn.net/u012410733/…]

  • 第二步:FrameworkServlet通过initServletBean()进行Web上下文初始化
public abstract class FrameworkServlet extends HttpServletBean {
    
    private String contextConfigLocation;// servlet的init-param中contextConfigLocation参数

    @Override
    protected final void initServletBean() throws ServletException {
       ......
       try {
             //1、初始化Web上下文
           this.webApplicationContext = initWebApplicationContext();
             //2、提供给子类初始化的扩展点
           initFrameworkServlet();
       }
        ......
    }
    
    protected WebApplicationContext initWebApplicationContext() {
        //ROOT上下文(ContextLoaderListener加载的)
       WebApplicationContext rootContext =  WebApplicationContextUtils.getWebApplicationContext(getServletContext());
       WebApplicationContext wac = null;
       if (this.webApplicationContext != null) {
           // 1、在创建该Servlet注入的上下文
           wac = this.webApplicationContext;
           if (wac instanceof ConfigurableWebApplicationContext) {
              ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
              if (!cwac.isActive()) {
                  if (cwac.getParent() == null) {
                      cwac.setParent(rootContext);
                  }
                  configureAndRefreshWebApplicationContext(cwac);
              }
           }
       }
       if (wac == null) {
             //2、查找已经绑定的上下文
           wac = findWebApplicationContext();
       }
       if (wac == null) {
            //3、如果没有找到相应的上下文,并指定父亲为ContextLoaderListener
           wac = createWebApplicationContext(rootContext);
       }
       if (!this.refreshEventReceived) {
             //4、刷新上下文(执行一些初始化)
           onRefresh(wac);
       }
       if (this.publishContext) {
           // Publish the context as a servlet context attribute.
           String attrName = getServletContextAttributeName();
           getServletContext().setAttribute(attrName, wac);
           //省略部分代码
       }
       return wac;
    }
}
  • 第三步:FrameworkServlet通过onRefresh()方法配置前端控制器
public class DispatcherServlet extends FrameworkServlet {
    
    private static final Properties defaultStrategies;// 默认策略,具体见DispatcherServlet.properties
    private MultipartResolver multipartResolver;
    private LocaleResolver localeResolver;
    private ThemeResolver themeResolver;
    private List<HandlerMapping> handlerMappings;
    private List<HandlerAdapter> handlerAdapters;
    private List<HandlerExceptionResolver> handlerExceptionResolvers;
    private RequestToViewNameTranslator viewNameTranslator;
    private FlashMapManager flashMapManager;
    private List<ViewResolver> viewResolvers;

     //实现子类的onRefresh()方法,该方法委托为initStrategies()方法。
    @Override
    protected void onRefresh(ApplicationContext context) {
       initStrategies(context);
    }
    
    //初始化默认的Spring Web MVC框架使用的策略(如HandlerMapping)
    protected void initStrategies(ApplicationContext context) {
       initMultipartResolver(context);//文件上传解析
       initLocaleResolver(context);//本地化解析
       initThemeResolver(context);//主题解析
       initHandlerMappings(context);//请求到处理器的映射
       initHandlerAdapters(context);//处理器包装为适配器,从而支持多种类型的处理器
       initHandlerExceptionResolvers(context);//处理器异常解析
       initRequestToViewNameTranslator(context);//将请求URL映射为逻辑视图名
       initViewResolvers(context);//把逻辑视图名解析为具体的View
       initFlashMapManager(context);// ???
    }
    
    /**
     * 文件上传解析器
     **/
    private void initMultipartResolver(ApplicationContext context){
        this.multipartResolver = (MultipartResolver)context.getBean("multipartResolver", MultipartResolver.class);
    }
    
    /**
     * 本地化解析
     **/
    private void initLocaleResolver(ApplicationContext context){
        this.localeResolver = (LocaleResolver)context.getBean("localeResolver", LocaleResolver.class);
    }
    
    /**
     * 主题解析
     **/
    private void initThemeResolver(ApplicationContext context){
        this.themeResolver = (LocaleResolver)context.getBean("themeResolver", ThemeResolver.class);
    }
    
     /**
     * 处理器解析,比如BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping等
     **/
    private void initHandlerMappings(ApplicationContext context){
        this.handlerMappings = null;
        if (this.detectAllHandlerMappings) {
            // 获取IOC容器中实现了HandlerMapping接口的对象
            Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.handlerMappings = new ArrayList(matchingBeans.values());
                AnnotationAwareOrderComparator.sort(this.handlerMappings);
            }
        } else {
            HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
            this.handlerMappings = Collections.singletonList(hm);
        }
        
         if (this.handlerMappings == null) {
            // 获取默认的处理解析器
            this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);
        }
    }
    
    /**
     * 初始化适配器
     **/
    private void initHandlerAdapters(ApplicationContext context) {
        this.handlerAdapters = null;
        if (this.detectAllHandlerAdapters) {
            // 获取IOC容器中实现了HandlerAdapter接口的对象
            Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.handlerAdapters = new ArrayList(matchingBeans.values());
                AnnotationAwareOrderComparator.sort(this.handlerAdapters);
            }
        } else {
            HandlerAdapter ha = (HandlerAdapter)context.getBean("handlerAdapter", HandlerAdapter.class);
            this.handlerAdapters = Collections.singletonList(ha);
        }

        if (this.handlerAdapters == null) {
            // 获取默认的适配器
            this.handlerAdapters = this.getDefaultStrategies(context, HandlerAdapter.class);
        }
    }
    
    /**
     * 初始化异常解析器
     **/
    private void initHandlerExceptionResolvers(ApplicationContext context) {
        this.handlerExceptionResolvers = null;
        if (this.detectAllHandlerExceptionResolvers) {
            Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.handlerExceptionResolvers = new ArrayList(matchingBeans.values());
                AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);
            }
        } else {
            HandlerExceptionResolver her = (HandlerExceptionResolver)context.getBean("handlerExceptionResolver", HandlerExceptionResolver.class);
            this.handlerExceptionResolvers = Collections.singletonList(her);
        }

        if (this.handlerExceptionResolvers == null) {
             // 获取默认的适配器
            this.handlerExceptionResolvers = this.getDefaultStrategies(context, HandlerExceptionResolver.class);
        }

    }
    
    /**
     * 将请求URL映射为逻辑视图名
     **/
    private void initRequestToViewNameTranslator(ApplicationContext context) {
        try {
            this.viewNameTranslator = (RequestToViewNameTranslator)context.getBean("viewNameTranslator", RequestToViewNameTranslator.class);
        } catch (NoSuchBeanDefinitionException var3) {
            this.viewNameTranslator = (RequestToViewNameTranslator)this.getDefaultStrategy(context, RequestToViewNameTranslator.class);
        }
    }
    
    /**
     * 初始化视图解析器
     **/
    private void initViewResolvers(ApplicationContext context) {
        this.viewResolvers = null;
        if (this.detectAllViewResolvers) {
            // 获取IOC容器中实现了ViewResolver接口的对象
            Map<String, ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.viewResolvers = new ArrayList(matchingBeans.values());
                AnnotationAwareOrderComparator.sort(this.viewResolvers);
            }
        } else {
            ViewResolver vr = (ViewResolver)context.getBean("viewResolver", ViewResolver.class);
            this.viewResolvers = Collections.singletonList(vr);
        }

        if (this.viewResolvers == null) {
             // 获取默认的适配器
            this.viewResolvers = this.getDefaultStrategies(context, ViewResolver.class);
        }

    }
}