第二章 DispatcherServlet

来源:互联网 发布:mac的绝对路径 编辑:程序博客网 时间:2024/05/17 05:15

说明:此系列文章为博主原创翻译,转载请注明:http://blog.csdn.net/hugh282003/article/details/19057165

    与其他类型的Web MVC框架一样,Spring MVC也是请求驱动的,以一个中心Servlet来转发请求交由具体的控制器处理。SpringDispatcherServlet便是这样的中心Servlet,它的工作要更多。它完全集成于SpringIoC容器中,因此通过它可以使用Spring的其他任何特性。DispatcherServlet的请求处理流程在下面的流程图中进行了描述。从图中我们可以看出来,DispatcherServlet的设计就是基于“前端控制器”这种其他一流的Web框架都使用的设计模式。

    客户端请求首先到达DispatcherServlet这个前端控制器,然后再委派给具体的控制器来处理请求并生成数据模型,然后返回给DispatcherServlet来生成响应,DispatcherServlet再把模型数据交由视图模板来生成最终返回给客户端的响应,最后由DispatcherServlet将响应内容返回给客户端。

    DispatcherServlet继承于HttpServlet基类,属于一种标准的Servlet,因此需要在web.xml文件中声明。像其他标准的Java EE Servlet配置一样,在web.xml文件中通过URL映射来配置客户端请求交由DispatcherServlet处理。下面是一个示例:

<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>/example/*</url-pattern>

    </servlet-mapping>

</web-app>

    在上面的例子中,所有以/example开头的请求都会交由DispatcherServlet的名为example的实例来处理。在Servlet 3.0以上的容器中,以上示例也可以通过编码来进行配置。如下面的代码所示:

public class MyWebApplicationInitializer implements WebApplicationInitializer {

 

    @Override

    public void onStartup(ServletContext container) {

        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());

        registration.setLoadOnStartup(1);

        registration.addMapping("/example/*");

    }

}

    上述代码中,WebApplicationInitializerSpring MVC提供的接口用以保证代码实现的配置能够被Web容器检测到,并被自动地用来初始化Servlet 3容器。该接口的一个抽象类实现是AbstractDispatcherServletInitializer,通过它注册DispatcherServlet更加简单,只需指明URL映射即可。关于代码配置的详细信息将会在后面的章节说明。上面的配置只是设置Spring Web MVC的第一步。Spring Web MVC框架所使用到的众多Beans还需要进一步配置,而不是配置DispatcherServlet一个。

    SpringApplicationContext实例是有作用域的。在Spring Web MVC中,每个DispatcherServlet的实例都有属于自己的WebApplicationContext实例,它继承了所有根WebApplicationContext实例里定义的Beans。这些继承的Beans可以在特定的Servlet的作用域内被覆写,也可以定义属于某一Servlet实例的本地作用域的新Beans。下图为Spring Web MVCContext层级:



    DispatcherServlet初始化时,Spring MVC框架会搜索应用程序WEB-INF目录下的[servlet-name]-servlet.xml文件,如果该文件存在的话会创建里面定义的Beans,同时也会覆写全局作用域内同名Bean的定义。考虑下面web.xml文件中的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>

    对于上面的DispatcherServlet配置,我们还需要一个相应的/WEB-INF/golfing-servlet.xml的文件,这个文件将会包括所有的Spring Web MVC相关的组件即Beans。当然该文件的存放位置也可以通过DispatcherServlet的初始化参数来指定。后面将会有详细说明。Spring Web MVCWebApplicationContext是对Spring框架的ApplicationContext的扩展,包含了一些Web应用程序必需的额外的特性。它与普通的ApplicationContext的区别在于:它能够解析主题(具体的细节将会在后面的章节中说明),以及通过它可以获得与之关联的Servlet的信息,这一点是通过对ServletContext的引用来实现的。WebApplicationContext是与ServletContext绑定的,我们可以通过RequestContextUtils工具类的静态方法来获取到特定的WebApplicationContext实例。

2.1 WebApplicationContext中的特殊的Bean类型

    SpringDispatcherServlet使用了特定的Beans来处理客户端请求和生成合适的视图。这些Beans隶属于Spring MVC。这些Beans可以在WebApplicationContext中加以配置使用。但是Spring MVC提供了默认的Beans配置,因此如无特别需求,我们无需自己来配置。下表列出了DispatcherServlet可能会使用到的特殊的Bean类型:

Bean类型

说明

HandlerMapping 

根据不同的HandlerMapping实现,按照定义的标准,通过它将客户端的请求映射到具体的控制器以及拦截器链(分为前拦截器和后拦截器)。最常用的实现提供了对使用注解的控制器的支持。

HandlerAdapter

提供了对调用某一请求对应的控制器处理方法的统一封装。比如,触发某一带有注解的控制器需要首先解析这些注解,HandlerAdapter的作用便是对DispatcherServlet屏蔽这些细节。

HandlerExceptionResolver 

使不同的异常映射到不同的视图,以及对异常的复杂处理逻辑。

ViewResolver 

解析字符串形式的逻辑视图名称为具体的视图类型。

LocaleResolver &LocaleContextResolver 

解析客户端的地区和时区信息以提供对国际化视图的支持。

ThemeResolver 

解析Web应用程序所使用的主题以提供对个性化布局的支持。

MultipartResolver 

解析文件流请求以提供对来自HTML表单的文件上传功能的支持。

FlashMapManager 

存取输入输出FlashMap以提供对跨请求传值的支持,通常用在一个重定向请求中。

 

2.2 DispatcherServlet的默认配置

    DispatcherServlet的默认Beans配置信息保存在org.springframework.web.servlet包下的fileDispatcherServlet.properties文件中。所有特殊Bean类型都有自己的默认Bean。我们可能需要配置这些Beans的某些属性,比如,对于InternalResourceViewResolver,通常需要配置它相对于视图文件父目录的前缀属性。

    这里需要理解的一点是,一旦我们在WebApplicationContext中配置了上述的特殊Beans,例如InternalResourceViewResolver,我们就相当于覆写了框架对于该类型Bean的默认配置。比如,如果我们配置了InternalResourceViewResolver,那么ViewResolver的默认配置就会被忽略。

2.3 DispatcherServlet的处理流程

    在配置好DispatcherServlet之后,当请求交由该DispatcherServlet处理时,其处理流程如下:

    1、构造WebApplicationContext被作为属性绑定到请求上以备控制器和其他元素使用。绑定的默认keyDispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE

    2、绑定地区解析器到请求上以备解析地区时使用,比如生成视图和准备数据时等等。如果不需要解析地区,则无需使用。

    3、绑定主题解析器到请求上以备视图等元素加载主题时使用。

    4、如果配置了文件流解析器,则会检测请求中是否包含文件流,如果包含,则请求会被包装为MultipartHttpServletRequest供其他元素做进一步处理。这一部分将会在后面的章节中进行详细说明。

    5、搜索合适的处理器处理请求。找到的话,与该处理器相关联的执行链(前拦截器、后拦截器、控制器等)会被执行以准备模型数据或生成视图。

    6、如果返回了模型对象,下一步就会进行视图的渲染。如果没有任何模型对象返回,例如因为安全的原因被前拦截器或后拦截器拦截了请求,那么就没有视图会生成,因为该请求已经结束了。

 

    WebApplicationContext中声明的处理器异常解析器会处理在请求处理过程中抛出的异常。通过这些异常解析器,我们可以自定义异常处理动作。

    SpringDispatcherServlet还支持返回Servlet API中定义的上次修改时间(last-modification-date)信息。对于确定某一特定请求的上次修改时间的流程是这样的:DispatcherServlet找到一个合适的处理器映射器后,测试找到的处理器是否实现了LastModified接口,如果实现了接口的话,LastModifiedgetLastModified(request)方法会返回一个long型的值给客户端。

    我们还可以通过init-param标签在web.xml文件中Servlet声明的地方加上Servlet的初始化参数来配置单独的DispatcherServlet实例。下表列出了可以使用的参数:

参数

说明

contextClass

值为实现了WebApplicationContext接口的类,该类被Servlet用来实例化Servlet上下文。默认值为XmlWebApplicationContext

contextConfigLocation

一个字符串值被contextClass的实例用来指明上下文所在的位置。如果有多个上下文的话则以逗号分隔。如果有Bean被在不同的上下文中重复定义了,则以最后出现的为准。

namespace

WebApplicationContext的命名空间。默认值为[servlet-name]-servlet

 

0 0