SpringMVC就像其它WebMVC框架一样,以请求为驱动,围绕一个中央Servlet派遣请求给控制层,和提供一些其它的有助于Web应用程序开发的功能。但是,Spring前置控制器不仅仅做了这些。 他完全集成了SpringIOC容器,因此你还可以使用Spring框架的一些特性 SpringMVC前置控制器(DispatcherServlet)对请求的处理流程参见下图。对模式非常了解的读者可能会意识到,所谓的DispatcherServlet是“前置控制器”设计模式的表达 (这是SpringMVC和其它许多优秀网页框架都采用的模式)
DispatcherServlet实际上是一个Servlet(它继承自HttpServlet基类),因此你需要在你的网页应用中声明。你需要对希望被DispatcherServlet处理的请求进行URL映射。 这是JavaEE Servlet在Servlet 3.0版本以上的标配
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
ServletRegistration.Dynamic registration = container.addServlet("example", new DispatcherServlet());
registration.setLoadOnStartup(1);
registration.addMapping("/example/*");
}
}
在上面这个例子,所有的请求以/example开头就会被名为example的DispatcherServlet实例处理
WebApplicationInitializer
是一个SpringMVC提供的接口,用来确保你的基于代码的配置在任何Servlet3容器中能被检测并自动初始化。 一个名为AbstractAnnotationConfigDispatcherServletInitializer
的接口的抽象基类通过实现指定其servlet映射并列出配置类来更容易的注册DispatcherServlet。它甚至推荐你去设置你的SpringMVC应用。
DispatcherServlet实际上就是一个Servlet(它继承自HttpServlet基类),因此它在你的web应用中的web.xml声明。同样,你也要在web.xml中通过URL映射需要被dispacherServlet处理的请求。 这是javaEE Servlet的标准配置。在接下来的例子展示DispatcherServlet的声明和映射
接下来的Web.xml相当于上面java代码的例子
<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>
详细信息在7.15章节Additional Capabilities of the ApplicationContext,Spring中的ApplicationContext实例能被限定。在Web MVC框架中,每个DispatcherServlet都有自己的WebApplicationContext, 它继承了已经在根WebApplicationContext中定义的所有bean。根WebApplicationContext应该包含所有的在其它的上下文和servlet实例中共享的基础类bean, 这些继承的bean能够在servlet特定的范围内被覆盖(应该是重写的意思),你也能在给定的Servlet中本地定义一个新的特定范围的bean
在初始化DispatcherServlet时,SpringMVC在你的web应用中寻找WEB-INF目录下的[servlet-name]-servlet.xml,并创建在这个文件中定义的bean,在全局范围内覆盖定义任何重名的bean定义。
请考虑以下DispatcherServlet Servlet配置(在web.xml文件中)
<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>
上述的Servlet配置,你需要有一个名为/WEB-INF/golfing-servlet.xml的文件在你的应用中。这个文件包含你所有Spring Web MVC
具体的组件(bean)。 你可以通过Servlet初始化参数修改此配置文件的具体位置
单个DispatcherServlet方案也有可能只有一个根上下文
这可以通过设置一个空的ContextConfigLocation servlet init参数进行配置,如下所示:
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
WebApplicationContext是作为对原生ApplicationContext的一个扩展,它具有web应用所需的一些额外的重要特性。它与普通的ApplicationContext不同之处在于它能解析主题, 并且它知道它与那个servlet相关联(通过连接到ServletContext)。WebApplicationContext绑定在ServletContext中,如果你需要的话可以通过RequestContextUtils静态类上的方法可以随时查找WebApplicationContext。
请注意,我们可以用java代码实现同样的配置
public class GolfingWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
// GolfingAppConfig defines beans that would be in root-context.xml
//需要在root-context.xml中定义的bean
return new Class[] { GolfingAppConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
// GolfingWebConfig defines beans that would be in golfing-servlet.xml
// GolfingWebConfig需要在golfing-servlet.xml定义的bean
return new Class[] { GolfingWebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/golfing/*" };
}
}
22.2.1 Special Bean Types In the WebApplicationContext
Spring框架的DispatcherServlet使用一些特殊的bean来处理request并呈现适当的视图,这些bean是SpringMVC的一部分。你可以通过在WebApplicationContext简单配置一个或者多个来使用这些bean. ,你并不需要初始化这些bean,如果你没有配置任何内容也不要紧因为SpringMVC内部维护了一个默认的bean列表。更多的在下一节。 首先看下表列出DispatcherServlet依赖的特殊bean类型。
HandlerMapping | 根据一些标准将传入的请求映射到处理程序和前处理程序和后处理程序列表(处理程序拦截器),其细节由HandlerMapping实现而异。 最流行的实现支持注释控制器,但其他实现也存在。 |
HandlerAdapter | 帮助DispatcherServlet调用映射到请求的处理程序,而不管实际调用哪个处理程序。 例如,调用带注释的控制器需要解析各种注释。 因此,HandlerAdapter的主要目的是屏蔽DispatcherServlet和这些细节。 |
HandlerExceptionResolver | 映射视图的异常也允许更复杂的异常处理代码。 |
ViewResolver | 将基于逻辑字符串的视图名称解析为实际的View类型。 |
LocaleResolver & LocaleContextResolver | 解决客户端正在使用的区域设置以及可能的时区,以便能够提供国际化的视图 |
ThemeResolver | 解决您的Web应用程序可以使用的主题,例如,提供个性化的布局 |
MultipartResolver | 解析多部分请求,以支持从HTML表单处理文件上传。 |
FlashMapManager | .存储并检索可以用于将属性从一个请求传递到另一个请求的“输入”和“输出”FlashMap,通常是通过重定向。 |
Default DispatcherServlet Configuration
默认的DispatcherServlet配置在上一章节针对每一个特殊的bean所述,DispatcherServlet会维护默认使用的实现列表。此信息保存在包 org.springframework.web.servlet中的文件DispatcherServlet.properties中。
所有的特殊bean都有一个合理的默认值,不久之后,您将需要自定义这些bean提供的一个或多个属性。 例如,将InternalResourceViewResolver设置的前缀属性配置为视图文件的父位置是很常见的。
无论细节如何,这里要理解的重要概念是,一旦在WebApplicationContext中配置了一个特殊的bean,如InternalResourceViewResolver。您就有效地覆盖了该特殊bean类型的默认实现列表。 例如,如果配置了InternalResourceViewResolver,则会忽略ViewResolver实现的默认列表。
在第22.16节“配置Spring MVC”中,您将了解配置Spring MVC的其他选项,包括MVC Java配置和MVC XML命名空间,这两个命名空间都提供了一个简单的起点,并且对Spring MVC的工作原理几乎不了解。 无论您如何选择配置应用程序,本节中介绍的概念都是根本的,应该对您有所帮助。
DispatcherServlet Processing Sequence
DispatcherServlet处理序列
在您设置了DispatcherServlet之后,并且该特定DispatcherServlet启动了一个请求,DispatcherServlet将按如下所示开始处理请求
1. 在请求中搜索并绑定WebApplicationContext作为控件和进程中的其他元素可以使用的属性。 默认情况下,它将在DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE键下绑定。
2.语言环境解析器被绑定到请求,以使进程中的元素能够解决在处理请求时使用的区域设置(渲染视图,准备数据等)。 如果您不需要语言环境解析,则不需要它。
3.主题解析器被绑定到使得诸如视图之类的元素确定要使用哪个主题的请求。 如果不使用主题,可以忽略它。
4.如果指定了多部分文件解析器,则会检查该请求的多部分; 如果找到多部分,则请求被包装在MultipartHttpServletRequest中,以便进程中的其他元素进一步处理。 有关多部分处理的更多信息,请参见第22.10节“Spring的多部分(文件上传)支持”。
5.搜索适当的处理程序。 如果找到处理程序,则执行与处理程序(预处理程序,后处理程序和控制器)关联的执行链,以便准备模型或呈现
6.如果返回模型,则呈现视图。 如果没有返回模型(可能是由于预处理程序或后处理程序拦截请求,可能是出于安全原因),则不会生成视图,因为请求可能已经被满足
在WebApplicationContext中声明的处理程序异常解析程序在处理请求期间提取异常。 使用这些异常解析器允许您定义自定义行为来解决异常。
Spring DispatcherServlet还支持返回由Servlet API指定的最后修改日期。 确定特定请求的最后修改日期的过程很简单:DispatcherServlet查找适当的处理程序映射,并测试发现的处理程序是否实现了LastModified接口。 如果是,则LastModified接口的long getLastModified(request)方法的值将返回给客户端。
您可以通过将Servlet初始化参数(init-param元素)添加到web.xml文件中的Servlet声明来自定义单独的DispatcherServlet实例。 有关支持的参数列表,请参见下表。
参数 | 说明 |
contextClass | 实现WebApplicationContext的类,它实例化了这个Servlet使用的上下文。 默认情况下,使用XmlWebApplicationContext。 |
contextConfigLocation | 传递给上下文实例(由contextClass指定)以指示可以找到上下文的字符串。 该字符串可能包含多个字符串(使用逗号作为分隔符)来支持多个上下文。 在具有两次定义的bean的多个上下文位置的情况下,优先级最高。 |
namespace | WebApplicationContext的命名空间。 默认为[servlet-name] -servlet。 |