一、综述
Spring MVC框架是围绕DispatcherServlet这个核心展开的。
处理流程如下:
- 客户端浏览器发送HTTP请求
- 核心控制器DispatcherServlet截获请求
- 分发到相应的业务控制器中
- 业务控制器调用业务处理方法处理业务逻辑
- 返回一个模型和视图对象
- 核心控制器根据此对象找到视图
- 显示出处理结果
可以看到,Spring MVC框架里面有以下组件:
- 核心控制器
- 业务控制器
- 控制器映射
- 模型与视图
- 视图解析器
- Command对象
下面对这些组件进行介绍。
1.核心控制器
核心控制器就是DispatcherServlet,负责接收并拦截HTTP请求,将请求封装成对象数据并创建ApplicationContext.
在web.xml文件中就要对核心控制器进行配置。
<servlet>
<!-- 声明Servlet -->
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 初始化上下文对象 -->
<init-param>
<!-- 参数名称 -->
<param-name>contextConfigLocation</param-name>
<!-- 加载配置文件 -->
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<!-- 设置启动的优先级 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 采用通配符映射所有HTML类型的请求 -->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
在上面的配置中声明了一个名为dispatcherServlet的Servlet对象,并采用通配符的方式将所有HTML类型的请求都映射到了DispatcherServlet对象上。
2.业务控制器
所有业务控制器必须实现Controller接口
public interface Controller{
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
Controller控制器的结构如下:
(1)AbstractController(简单控制器)
实现了Controller接口,继承WebContentGenerator
(2)ParameterizableViewController(参数映射控制器)
继承AbstractController,提供了getter()与setter()方法
(3)UrlFilenameViewController (文件名映射控制器)
使用“前缀+请求名+后缀”的方式来生成视图的名称。声明了prefix与suffix属性,提供了getter()与setter()方法.
(4)SimpleFormController (表单控制器)
重写该类中的onSubmit()方法。
(5)MultiActionController (多动作控制器)
在该控制器内可以定义多个方法,定义的方法的返回值是ModelAndView,Map或void,方法的形参要有这两个参数HttpServletRequest与HttpServletResponse.
3.控制器映射(HandlerMapping)
通过控制器映射,核心控制器DispatcherServlet可以找到对应HTTP请求的业务控制器。
控制器映射的类型如下:
BeanNameUrlHandlerMapping(文件名映射控制器)
在Spring中查找与URL请求名称相同的处理器
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
SimpleUrlHandlerMapping(URL映射控制器)
使用类型为Properties的mappings属性来定义URL到处理器的映射关系
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/index.html">forwardController</prop>
<prop key="/stu/*.html">forwardController</prop>
</props>
</property>
</bean>
- ControllerClassNameHandlerMapping(短类名控制器)
4.模型与视图
一个ModelAndView对象,用来负责传递模型层处理后的结果集与指定的视图层名称
5.视图解析器
显示结果。
实现了ViewResovler接口
public interface ViewResovler{
View resolveViewName(String viewName, Locale locale) throws Exception;
}
视图解析器的结构如下。
(1)InternalResourceViewResovler
将逻辑视图名映射到保存在WEB-INF文件夹中的JSP页面文件,即通过“前缀+逻辑视图名+后缀”的方式得到一个指向确定地址的JSP页面文件。
6.command对象
Command对象是普通的java对象,用于封装用户请求中的参数。
二、核心原理
- 用户发送请求到服务器,url: **.do
- 服务器收到请求,调用DispatcherServlet
- DispatcherServlet内部,通过handlerMapping检查这个URL有没有对应的Controller.如果有Controller,就调用这个Controller.
- 执行Controller
- Controller执行完毕后,如果返回字符串,则ViewResolver将字符串转化为相应的视图对象;如果返回ModelAndView对象,该对象本身就包含了视图的对象信息。
- DispatcherServlet将视图对象中的数据,输出给服务器
- 服务器将数据显示到客户端
三、注解
使用注解需要使用如下类似的文件定义
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
...
</beans>
加载注解的驱动
<mvc:annotation-driven />
Spring的controller是单例的。
为了使spring能找到定义controller的bean,需要在spring-context的配置文件下添加如下类似的定义:
<context:component-scan base-package="com.lzr" />
@Component 跟@ Controller一样能起到同样的作用
@Controller 声明一个处理器类
@RequestMapping 声明对应请求的映射关系
@Controller
@RequestMapping("/user.save")
public class UserController {
private IUserService userService;
public IUserService getUserService() {
return userService;
}
@Resource
public void setUserService(IUserService userService) {
this.userService = userService;
}
@RequestMapping(params = "method=save")
public ModelAndView save(User user){
ModelAndView mav = new ModelAndView("success");
mav.addObject("user", user);
try {
userService.save(user);
} catch (Exception e) {
mav.setViewName("error/error");
}finally {
return mav;
}
}
}
@RequestParam
当request请求的参数跟方法的形参前后不一致,比如下面的username和name,使用@RequestParam手动指定参数username对应形参name.
@RequestMapping(params="method=reg3")
public String reg3(@RequestParam("username") String name){
...
}
@SessionAttributes
将ModelMap指定的属性放到Session里面。
@Component
@RequestMapping("...")
@SessionAttributes({"a","b"})
public class UserController {
...
@RequestMapping(params = "method=...")
public ModelAndView save(User user){
ModelMap map = new ModelMap();
map.addAttribute("a", "value");
...
ModelAndView mav = new ModelAndView("success");
...
return mav;
}
}
在上面的代码里,当ModelMap里面添加了指定的属性”a”,则”a”也会添加到Session里面。
@ModelAttribute
跟@SessionAttributes配合使用,将ModelMap中的属性值自动赋值给指定变量
四、附录
针对Spring MVC 4.2.4.RELEASE版本