DispatcherServlet详解

6,153 阅读6分钟

为什么我们需要DispatcherServlet

我们想要将外部的请求分发处理。

DispatcherServlet是什么

DispatcherServlet是前端控制器设计模式的实现,提供了Spring Web MVC的集中访问点, 而且负责职责的分派,而且与Spring Ioc容器无缝集成, 从而可以获的Spring的所有好处。

DispatcherServlet作用

DispatcherServlet主要用作职责调度工作,本身主要用于控制流程,主要职责如下:

  1. 文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;
  2. 通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器);
  3. 通过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器);
  4. 通过ViewResolver解析逻辑视图名到具体视图实现;
  5. 本地化解析;
  6. 渲染具体的视图等;
  7. 如果执行过程中遇到异常将交给HandlerExceptionResolver来解析。

DispatcherServlet的工作流程

DispatcherServlet实现详解

DospatcherServlet实际上是一个Servlet(它继承HttpServlet)。DispatcherServlet处理的请求必须在同一个web.xml文件里使用url-mapping定义映射。这是标准的J2EE servlet配置。下面的例子展示了如何配置DispatcherServlet。 DispatcherServlet配置在web.xml文件中。配置文件如下。

<web-app>

    <servlet>
        <servlet-name>example</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>example</servlet-name>
        <url-pattern>*.form</url-pattern>
    </servlet-mapping>

</web-app>

在上述例子中所有以.form结尾的请求都会由名为example的DispatcherServlet处理。这只是配置Spring Web MVC的第一步。接下来你需要配置DispatcherServlet本身和Spring Web MVC框架所需要的各种bean。

3.13 Additional Capabilities of the ApplicationContext的定义中,Spring中的ApplicationContext可以被限制在不同的作用域(scope)中。在Web MVC框架中,每个DispatcherServlet有它自己的WebApplicationContext,这个context继承了WebApplicationContext的所有bean定义。继承的这些bean可以在每个servlet自己所属的域中被覆盖,覆盖的bean可以被设置成只有这个servlet实例自己才可以使用的属性。

Spring Web MVC中的上下文层次结构

在初始化DispatcherServlet过程中,框架首先在WEB-INF目录下找到名字叫[servlet-name]-servlet.xml的文件,创建其中定义的bean,这些bean会覆盖全局范围中定义的同名bean。

我们可以看一下下面这个DispatcherServlet例子

<web-app>

    <servlet>
        <servlet-name>golfing</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>golfing</servlet-name>
        <url-pattern>/golfing/*</url-pattern>
    </servlet-mapping>

</web-app>

如果想要上述的配置生效,我们需要配置一个/WEB-INF/golfing-servlet.xml文件。这个文件中声明了你在Spring Web MVC框架中需要的特殊的组件(bean)。 这个文件的路径也可以通过web.xml中servlet的初始化参数来更改。

WebApplicationContext是一个普通的ApplicationContext的扩展,但是它有一个Web应用必要的功能。它与一个标准的ApplicationContext不同之处在于,它能够解析主题(参考 Using themes),并且它知道自己与哪个servlet相关联(通过ServletContext)。WebApplicationContext被绑定在ServletContext上,当你需要的时候,可以使用RequestContextUtils提供的静态方法找到WebApplicationContext。

Spring DispatcherServlet使用特殊的bean来处理请求和渲染视图。这些bean是Spring框架的一部分,如同你配置其他bean一样,你可以在WebApplicationContext中配置他们。对大多数bean,Spring都提供了合理的缺省值,所以在开始阶段,你不必担心如何对其进行配置。

在WebApplicationContext中的特殊的bean

Bean类型 解释
控制器(Controller) MVC 中的 c 部分
处理器映射(Handler mapping) 处理预处理器、后置处理器和控制器列表的执行(如果满足特定的条件,如:符合控制器的指定的URL)
视图解析器(View resolvers) 将视图名解析为视图
本地化解析器(Locale resolver) 本地化解析器是一个能够解析客户端正在使用的本地配置的组件,以提供国际化视图
主题解析器(Theme resolver) 主题解析器能够解析你的web应用所使用的主题,以提供个性化的布局
上传文件解析器(multipart file resolver) 上传文件解析器提供HTML表单文件上传功能
异常处理解析器(Handler exception resolvers) 异常处理解析器可以将异常对应到视图,或者实现更加复杂的异常处理代码

处理流程

当你配置好DispatcherServlet后,DispatcherServlet接收到与其对应的请求之时,处理就开始了。处理流程如下:

  1. 找到WebApplicationContext并将其绑定到请求的一个属性上,以便控制器和处理链上的其它处理器能使用WebApplicationContext。默认的属性名为 DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE

  2. 将本地化解析器绑定到请求上,这样使得处理链上的处理器在处理请求(准备数据、显示视图等等)时能进行本地化处理。如果不需要本地化解析,忽略它就可以了。

  3. 将主题解析器绑定到请求上,这样视图可以决定使用哪个主题。如果你不需要主题,可以忽略它。

  4. 如果你指定了一个上传文件解析器,Spring会检查每个接收到的请求是否存在上传文件,如果是,这个请求将被封装成MultipartHttpServletRequest以便被处理链中的其它处理器使用。(Spring's multipart (fileupload) support查看更详细的信息)

  5. 找到合适的处理器,执行和这个处理器相关的执行链(预处理器,后处理器,控制器),以便为视图准备模型数据。

  6. 如果模型数据被返回,就使用配置在WebApplicationContext中的视图解析器显示视图,否则视图不会被显示。有多种原因可以导致返回的数据模型为空,比如预处理器或后处理器可能截取了请求,这可能是出于安全原因,也可能是请求已经被处理过,没有必要再处理一次。

在请求处理过程中抛出的异常,可以被任何定义在WebApplicationContext中的异常解析器所获取。使用这些异常解析器,你可以在异常抛出时根据需要定义特定行为。

Spring的DispatcherServlet也支持返回Servlet API定义的last-modification-date。决定某个请求最后修改的日期很简单:DispatcherServlet会首先寻找一个合适的handler mapping,检查从中取得指定的处理器是否实现了LastModified接口,如果是,将调用long getLastModified(request)方法,并将结果返回给客户端。

你可以通过两种方式定制Spring的DispatcherServlet:在web.xml文件中增加添加context参数,或servlet初始化参数。下面是目前支持的参数。

DispatcherServlet初始化参数

参数 描述
contextClass 实现WebApplicationContext接口的类,当前的servlet用它来创建上下文。如果这个参数没有指定,默认使用XmlWebApplicationContext。
contextConfigLocation 传给上下文实例(由contextClass指定)的字符串,用来指定上下文的位置。这个字符串可以被分成多个字符串(使用逗号作为分隔符)来支持多个上下文(在多上下文的情况下,如果同一个bean被定义两次,后面一个优先)。
namespace WebApplicationContext命名空间。默认值是[server-name]-servlet。

参考