1.1 DispatcherServlet与WebApplicationContext
- DispatcherServlet基于Servlet实现,用于映射请求,并分发请求到指定的模块进行处理。
- WebApplicationContext通过扩展ApplicationContext实现,用于DispatcherServlet的配置。
- WebApplicationContext关联了ServletContext和Servlet ,可以利用RequestContextUtils中的静态方法查找WebApplicationContext。
1.2 WebApplicationContext的层次结构
- 对于多数应用来说,拥有一个单独的WebApplicationContext已经足够。但是也可以在多个DispatcherServlet实例之间分享一个根WebApplicationContext,同时每个DispatcherServlet拥有自己的子WebApplicationContext。
-
根WebApplicationContext包含了基础性的beans,可以在多个Servlet实例中分享。如下图所示,展示了这种层次结构(图片来至Spring官网):
mvc-context-hierarchy.png
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的处理过程:
- 搜索WebApplicationContext并将其作为一个属性绑定到request上,属性的key:DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE,因此在controller中或者后续的处理过程中可以通过request获取到WebApplicationContext。
- LocalResolver绑定到request, 用于后续国际化的处理,当然,这不是必须的。
- 绑定ThemeResolver到request,用于判断主题的使用,这也不是必须的。。
- 如果指定了multipart文件解析器,则会检查request中的multipart数据,如果发现数据,request会被包装成MultipartHttpServletRequest以进行进一步的处理。
- 执行处理,处理过程在一条处理链(preprocessors, postprocessors, and controllers)中完成
- 完成处理后返回视图或者数据,也可能在拦截器中直接返回。
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() };
}
}
网友评论