1. DispatcherServlet

2017-10-16  本文已影响0人  banalite

1.1 DispatcherServlet与WebApplicationContext

1.2 WebApplicationContext的层次结构

1.3 DispatcherServlet的请求处理过程

处理过程在介绍DispatcherServlet的处理过程前,先介绍一下DispatcherServlet处理过程中用到的几个bean:

bean类型 说明
HandlerMapping 将请求映射到处理器以及一系列的HandlerInterceptor拦截器,在拦截器中包含了pre-和post-等处理,具体可以查看对应接口定义。同时,映射规则基于HandlerMapping 的具体实现类来定义。
HandlerAdapter 帮助DispatcherServlet调用请求所映射的处理器,这样做的目的是为了对DispatcherServlet隐藏调用处理器的具体实现过程,而DispatcherServlet只需要通过HandlerAdapter来实现调用即可。
HandlerExceptionResolver 解决异常的策略,可以将异常映射到处理器,或者返回错误页面等
ViewResolver 根据处理器返回的视图名称对应到具体的视图(页面),并返回。
LocalResolver & LocalContextResolver 解决时区以及国际化问题。
ThemeResolver 提供了网页应用主题的切换
MultipartResolver 提供了文件上传等类型服务
FlashMapManager 提供输入输出的FlashMap的数据存储与检索,FlashMap用于在不同的请求之间传递属性值,例如重定向的时候

下面是DispatcherServlet的处理过程:

  1. 搜索WebApplicationContext并将其作为一个属性绑定到request上,属性的key:DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE,因此在controller中或者后续的处理过程中可以通过request获取到WebApplicationContext。
  2. LocalResolver绑定到request, 用于后续国际化的处理,当然,这不是必须的。
  3. 绑定ThemeResolver到request,用于判断主题的使用,这也不是必须的。。
  4. 如果指定了multipart文件解析器,则会检查request中的multipart数据,如果发现数据,request会被包装成MultipartHttpServletRequest以进行进一步的处理。
  5. 执行处理,处理过程在一条处理链(preprocessors, postprocessors, and controllers)中完成
  6. 完成处理后返回视图或者数据,也可能在拦截器中直接返回。

1.4 在web.cml中配置DispatcherServlet

<web-app>
<!--  用于装配ApplicationContext的配置信息  -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
<!--  配置文件路径,提供给ContextLoaderListener使用,默认会去/WEB-INF/下加载applicationContext.xml  -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/root-context.xml</param-value>
  </context-param>
<!--  配置DispatcherServlet,并制定其配置文件路径  -->
  <servlet>
    <servlet-name>app1</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/app1-context.xml</param-value>
    </init-param>
    <!--  应用启动即初始化这个servlet,大于0且越小则越优先,小于等于0则不自动启动  -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <!--  将请求路径与servlet做映射  -->
  <servlet-mapping>
    <servlet-name>app1</servlet-name>
    <url-pattern>/app1/*</url-pattern>
  </servlet-mapping>

</web-app>

1.5 在代码中配置DispatcherServlet

先说一下DispatcherServlet 初始化值得三个参数:

参数 说明
contextClass 实现了WebApplicationContext接口,默认实现为XmlWebApplicationContext
contextConfigLocation 配置文件路径,如果有多个利用逗号隔开,如果路径重复,则选用最后一个路径
namespace WebApplicationContext的命名空间,默认为[servlet-name]-servlet

在Servlet3及以上版本,可以使用代码配置Servlet,如下例注册了一个DispatcherServlet:

import org.springframework.web.WebApplicationInitializer;

public class MyWebApplicationInitializer implements WebApplicationInitializer {
        @Override
        public void onStartup(ServletContext container) {
                //WebApplicationContext的默认实现类
                XmlWebApplicationContext appContext = new XmlWebApplicationContext();
                //设置配置文件地址
                appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
                //注册
                ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
                registration.setLoadOnStartup(1);
                registration.addMapping("/");
        }
}

WebApplicationInitializer 是由Spring MVC提供的接口,Spring MVC会自动检测用户的实现类,并执行初始化。如果要使用代码执行DispatcherServlet初始化,利用AbstractDispatcherServletInitializer 这个抽象类更简单,如下:

public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {

        @Override
        protected WebApplicationContext createRootApplicationContext() {
                return null;
        }

        @Override
        protected WebApplicationContext createServletApplicationContext() {
                XmlWebApplicationContext cxt = new XmlWebApplicationContext();
                cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
                return cxt;
        }

        @Override
        protected String[] getServletMappings() {
                return new String[] { "/" };
        }
        //还可以直接添加Filter
        @Override
        protected Filter[] getServletFilters() {
                return new Filter[] { new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
        }

}
上一篇下一篇

猜你喜欢

热点阅读