前言:本文首先简单介绍下DispatcherServlet及其特殊的Bean,然后学习如何通过注解的方式实现页面控制器。
本篇文章重点关注以下问题:
- 简述DispatcherServlet
- 注解式控制器详解
1. DispatcherServlet概述
DispatcherServlet是前端控制器设计模式的实现(见http://super-wangj.iteye.com/blog/2388441),提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。
DispatcherServlet主要用作职责调度工作,本身主要用于控制流程,主要职责如下:
- 通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor 拦截器);
- 通过 HandlerAdapter 支持多种类型的处理器(HandlerExecutionChain中的处理器);
- 通过ViewResolver 解析逻辑视图名到具体视图实现;
- 渲染具体的视图等;
- 本地化解析;
- 如果执行过程中遇到异常将交给HandlerExceptionResolver 来解析;
- 文件上传解析,如果请求类型是multipart将通过MultipartResolver 进行文件上传解析。
1.1 DispatcherServlet在web.xml中的配置
<!-- 配置 DispatcherServlet --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
- load-on-startup:表示启动容器时初始化该Servlet;
- url-pattern:表示哪些请求交给Spring Web MVC处理, “/” 是用来定义默认servlet映射的。也可以如“*.html”表示拦截所有以html 为扩展名的请求。
注:该 DispatcherServlet 默认使用WebApplicationContext 作为上下文, Spring 默认配置文件为“/WEB-INF/[servlet名字]-servlet.xml”。
DispatcherServlet的初始化参数:
参数 | 描述 |
contextClass | 实现WebApplicationContext接口的类,当前的servlet用它来创建上下文。如果这个参数没有指定, 默认使用XmlWebApplicationContext |
contextConfigLocation | 传给上下文实例(由contextClass指定)的字符串,用来指定上下文的位置。这个字符串可以被分成多个字符串(使用逗号作为分隔符) 来支持多个上下文(在多上下文的情况下,如果同一个bean被定义两次,后面一个优先)。 |
namespace | WebApplicationContext命名空间。默认值是[server-name]-servlet。 |
1.2 上下文关系
集成Web环境的通用配置:
<context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:spring-common-config.xml, classpath:spring-budget-config.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
如上配置是Spring集成Web环境的通用配置;一般用于加载除Web 层的Bean(如DAO、Service等),以便于与其他任何Web 框架集成。
- contextConfigLocation:表示用于加载Bean的配置文件;
- contextClass:表示用于加载Bean的ApplicationContext实现类,默认WebApplicationContext。
从图中可以看出,ContextLoaderListener 初始化的上下文加载的Bean 是对于整个应用程序共享的,不管是使用什么表现层技术,一般如DAO层、Service层Bean;
DispatcherServlet 初始化的上下文加载的Bean 是只对Spring Web MVC 有效的Bean,如Controller、HandlerMapping、HandlerAdapter等等,该初始化上下文应该只加载Web相关组件。
整个DispatcherServlet初始化的过程主要做了如下两件事情:
- 初始化Spring Web MVC使用的Web 上下文,并且可能指定父容器为(ContextLoaderListener加载了根上下文);
- 初始化DispatcherServlet使用的策略,如HandlerMapping、HandlerAdapter等。
1.3 DispatcherServlet中使用的特殊的Bean
DispatcherServlet默认使用WebApplicationContext作为上下文,其上下文中特殊的Bean如下:
- Controller:处理器/页面控制器,做的是MVC中的C 的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;
- HandlerMapping:请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain 对象(包含一个Handler处理器(页面控制器)对象、多个andlerInterceptor 拦截器)对象;如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;
- HandlerAdapter:HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;如SimpleControllerHandlerAdapter将对实现了Controller接口的Bean进行适配,并且调用处理器的handleRequest方法进行功能处理;
- ViewResolver:ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;如InternalResourceViewResolver将逻辑视图名映射为jsp视图;
- LocalResover:本地化解析,因为Spring支持国际化,因此LocalResover 解析客户端的Locale信息从而方便进行国际化;
- ThemeResovler:主题解析,通过它来实现一个页面多套风格,即常见的类似于软件皮肤效果;
- MultipartResolver:文件上传解析,用于支持文件上传;
- HandlerExceptionResolver:处理器异常解析,可以将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);
- RequestToViewNameTranslator:当处理器没有返回逻辑视图名等相关信息时,自动将请求URL 映射为逻辑视图名;
- FlashMapManager:用于管理FlashMap的策略接口,FlashMap用于存储一个请求的输出,当进入另一个请求时作为该请求的输入,通常用于重定向场景,后边会细述。
2. 注解式控制器
Spring3.1之后,SpringMVC使用处理器映射RequestMappingHandlerMapping 和处理器适配器RequestMappingHandlerAdapter来开启支持@Controller 和 @RequestMapping 注解的处理器。
2.1 常用注解
注解 | 作用 |
@Controller | 用于标识是处理器类; |
@RequestMapping | 请求到处理器功能方法的映射规则; |
@RequestParam | 请求参数到处理器功能处理方法的方法参数上的绑定; |
@ModelAttribute | 请求参数到命令对象的绑定; |
@SessionAttributes | 声明session 级别存储的属性,放置在处理器类上,通常列出模型属性(如@ModelAttribute)对应的名称,则这些属性会透明的保存到session 中; |
@InitBinder | 自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型; |
@CookieValue | cookie 数据到处理器功能处理方法的方法参数上的绑定; |
@RequestHeader | 请求头(header)数据到处理器功能处理方法的方法参数上的绑定; |
@RequestBody | 请求的body体的绑定(通过HttpMessageConverter 进行类型转换; |
@ResponseBody | 处理器功能处理方法的返回值作为响应体(通过HttpMessageConverter进行类型转换) |
@ResponseStatus | 定义处理器功能处理方法/异常处理器返回的状态码和原因; |
@ExceptionHandler | 注解式声明异常处理器; |
@PathVariable | 请求URI 中的模板变量部分到处理器功能处理方法的方法参数上的绑定,从而支持RESTful 架构风格的URI; |
2.2 配置控制器样例
2.2.1 配置web.xml
<!-- 配置Spring初始化参数(配置文件位置). --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <!-- 配置Spring监听器. --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置SpringMVC --> <servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping>
2.2.2 创建 Spring MVC 配置文件
<!-- 注解扫描包(SpringMVC只关注控制器类上的注解) --> <context:component-scan base-package="com.wj.web" /> <!-- 开启注解 --> <mvc:annotation-driven /> <!-- 静态资源(js/image)的访问 --> <!-- 针对SpringMVC拦截所有请求的情况下才需要配置,以防对静态资源的访问也被拦截. --> <!-- <mvc:resources location="/js/" mapping="/js/**"/> --> <!-- 定义视图解析器(此处针对Jsp) --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 所有URI的前缀. --> <property name="prefix" value="/jsp/"></property> <!-- 所有URI的后缀. --> <property name="suffix" value=".jsp"></property> </bean>
2.2.3 处理器定义
@Controller // 指明当前类是控制器
@RequestMapping("/jsp/user") // ①处理器的通用映射前缀
public class UserController {
@RequestMapping("/getAllUser.action") // ②相对于①处的映射URL进行窄化
public String getAllUser(HttpServletRequest request){
List<User> userList = userService.getAllUser();
request.setAttribute("userList", userList);
return "user/index";
}
}