什么是springmvc
- springmvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合。
- springmvc是一个基于mvc的web框架。
springmvc框架
- 用户发送请求至前端控制器DispatcherServlet。
- DispatcherServlet收到请求调用HandlerMapping处理器映射器。
- 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
- DispatcherServlet调用HandlerAdapter处理器适配器。
- HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
- Controller执行完成返回ModelAndView。
- HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
- ViewReslover解析后返回具体View。
- DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
- DispatcherServlet响应用户。
组件:
前端控制器DispatcherServlet(不需要程序员开发)
作用接收请求,响应结果,相当于转发器,中央处理器。
有了DispatcherServlet减少了其它组件之间的耦合度。处理器映射器HandlerMapping(不需要程序员开发)
作用:根据请求的url查找Handler处理器适配器HandlerAdapter
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler处理器Handler(需要程序员开发)
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler视图解析器View resolver(不需要程序员开发)
作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)视图View(需要程序员开发jsp)
View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)
前端控制器(DispatcherServlet):接收请求,响应结果,相当于电脑的CPU。
处理器映射器(HandlerMapping):根据URL去查找处理器
处理器(Handler):(需要程序员去写代码处理逻辑的)
处理器适配器(HandlerAdapter):会把处理器包装成适配器,这样就可以支持多种类型的处理器,类比笔记本的适配器(适配器模式的应用)
视图解析器(ViewResovler):进行视图解析,多返回的字符串,进行处理,可以解析成对应的页面
Hello World
需求
- spring mvc+mybatis(商品订单管理)。
- 商品列表查询
### 依赖
- spring所有的jar包(一定包括spring-webmvc-3.2.0.RELEASE.jar)
- mybatis以及数据库相关的jar
- jstl.jar
配置前端控制器
在web.xml中配置前端控制器1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<web-app>
<!-- springmvc前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- contextConfigLocation配置springmvc加载的配置文件(配置处理器映射器、适配器等等) 如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-serlvet.xml(springmvc-servlet.xml) -->
<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>springmvc</servlet-name>
<!-- 第一种:*.action,访问以.action结尾 由DispatcherServlet进行解析
第二种:/,所以访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析
使用此种方式可以实现 RESTful风格的url
第三种:/*,这样配置不对,使用这种配置,最终要转发到一个jsp页面时, 仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到handler,会报错。 -->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
- load-on-startup:表示servlet随服务启动;
- url-pattern:*.action的请交给DispatcherServlet处理。
- contextConfigLocation:指定springmvc配置的加载位置,如果不指定则默认加载WEB-INF/[DispatcherServlet 的Servlet 名字]-servlet.xml。
配置处理器适配器
在classpath的springmvc.xml中配置处理器适配器1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<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"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
</beans>
- 适配器都继承HandlerAdapter
- 适配器中有一个supports方法是判断这个适配器是执行哪个接口的handle
开发Handler(处理request)
- 需要实现 controller接口,才能由org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter适配器执行。
- cn.xwmdream.ssm.controller.ItemsController1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29public class ItemsController1 implements Controller{
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//调用service查找 数据库,查询商品列表,这里使用静态数据模拟
List<Items> itemsList = new ArrayList<Items>();
//向list中填充静态数据
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
//返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
//相当 于request的setAttribut,在jsp页面中通过itemsList取数据
modelAndView.addObject("itemsList", itemsList);
//指定视图
modelAndView.setViewName("/WEB-INF/jsp/item/itemsList.jsp");
return modelAndView;
}
}
视图编写
- 使用了jstl解析器,一定要引入这个jar包
/WEB-INF/jsp/item/itemsList.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查询商品列表</title>
</head>
<body>
<form
action="${pageContext.request.contextPath }/item/queryItem.action"
method="post">
查询条件:
<table width="100%" border=1>
<tr>
<td><input type="submit" value="查询" /></td>
</tr>
</table>
商品列表:
<table width="100%" border=1>
<tr>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
<td>操作</td>
</tr>
<c:forEach items="${itemsList }" var="item">
<tr>
<td>${item.name }</td>
<td>${item.price }</td>
<td><fmt:formatDate value="${item.createtime}"
pattern="yyyy-MM-dd HH:mm:ss" /></td>
<td>${item.detail }</td>
<td><a
href="${pageContext.request.contextPath }/item/editItem.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>一个foreach遍历传入的itemsList
配置Handler
将编写Handler在spring容器加载
springmvc.xml1
2<!-- 配置Handler -->
<bean name="/queryItems_test.action" class="cn.xwmdream.ssm.controller.ItemsController1" />
配置处理器映射器
在classpath下的springmvc.xml中配置处理器映射器1
2
3
4<!-- 处理器映射器 将bean的name作为url进行查找 ,需要在配置Handler时指定beanname(就是url)
所有的映射器都实现 HandlerMapping接口。
-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
- 此时handler需要配置路径
1
2<!-- 配置Handler -->
<bean name="/queryItems_test.action" class="cn.xwmdream.ssm.controller.ItemsController1" />
配置视图解析器
在classpath下的springmvc.xml中配置视图解析器
需要配置解析jsp的视图解析器。1
2
3
4
5<!-- 视图解析器
解析jsp解析,默认使用jstl标签,classpath下的得有jstl的包
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
</bean>
运行
- 运行http://localhost:8080/TestSpringMvc/queryItems_test.action
- 前面是项目地址,后面是配置的handler的地址
非注解的处理器映射器和适配器
非注解的处理器映射器
BeanNameUrlHandlerMapping
- 这个映射器是通过handler的name设置映射路径,所以handler的bean需要配置name属性(见hello world)
SimpleUrlHandlerMapping
1 | <!--简单url映射 --> |
- 这个映射器是通过参数的方式配置路径,值是handler的id,所以handler需要配置id
1 | <!-- 配置Handler --> |
- 多个映射器可以并存,前端控制器判断url能让哪些映射器映射,就让正确的映射器处理。
非注解的处理器适配器
SimpleControllerHandlerAdapter
配置适配器
1
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
要求编写的Handler实现 Controller接口(见hello world)
HttpRequestHandlerAdapter
配置适配器
1
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />
要求编写的Handler实现 HttpRequestHandler接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//调用service查找 数据库,查询商品列表,这里使用静态数据模拟
List<Items> itemsList = new ArrayList<Items>();
//向list中填充静态数据
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
//转发数据
request.setAttribute("itemsList",itemsList);
request.getRequestDispatcher("/WEB-INF/jsp/item/itemsList.jsp").forward(request,response);
}使用此方法可以通过修改response,设置响应的数据格式,比如响应json数据(通过getWriter,类似servlet)
1
2
3response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
DispatcherSerlvet.properties
- 如果不在springmvc.xml中配置处理映射器、适配器、视图解析器等组件,使用默认加载的。
- 默认加载的文件
- 这里面配置了多个映射器适配器视图解析器等组件,如果项目中没有指定会对应不同版本加载不同的默认组件
注解的处理器映射器和适配器
默认映射器
在spring3.1之前使用org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping注解映射器。
在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping注解映射器。
默认适配器
在spring3.1之前使用org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter注解适配器。
在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter注解适配器。
配置注解映射器和适配器
1 | <!--注解映射器 --> |
- 当然也可以换一种方式加载
1
2
3
4
5
6<!-- 使用 mvc:annotation-driven代替上边注解映射器和注解适配器配置
mvc:annotation-driven默认加载很多的参数绑定方法,
比如json转换解析器就默认加载了,如果使用mvc:annotation-driven不用配置上边的RequestMappingHandlerMapping和RequestMappingHandlerAdapter
实际开发时使用mvc:annotation-driven
-->
<mvc:annotation-driven></mvc:annotation-driven>
开发注解Handler
- cn.xwmdream.ssm.controller.ItemsController1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34//使用Controller标识 它是一个控制器
public class ItemsController1 {
// 商品查询列表
// @RequestMapping实现 对queryItems方法和url进行映射,一个方法对应一个url
// 一般建议将url和方法写成一样
"/queryItems") (
public ModelAndView queryItems() throws Exception {
// 调用service查找 数据库,查询商品列表,这里使用静态数据模拟
List<Items> itemsList = new ArrayList<Items>();
// 向list中填充静态数据
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
// 返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
// 相当 于request的setAttribut,在jsp页面中通过itemsList取数据
modelAndView.addObject("itemsList", itemsList);
// 指定视图
modelAndView.setViewName("/WEB-INF/jsp/item/itemsList.jsp");
return modelAndView;
}
}
加载注解handler
1 | <!-- 对于注解的Handler可以单个配置 |
调试
访问:http://localhost:8080/TestSpringMvc/queryItems.action
- 记得后面的.action
视图解析器
1 | <!-- 视图解析器 |
- 可以配置前缀和后缀,比如要访问/WEB-INF/jsp/item/itemsList.jsp时候,只需要指定item/itemsList即可
源码分析(了解)
通过前端控制器源码分析springmvc的执行过程。
前端控制器接收请求
调用doDiapatch前端控制器调用处理器映射器查找 Handler
调用处理器适配器执行Handler,得到执行结果ModelAndView
视图渲染,将model数据填充到request域。
视图解析,得到view:
调用view的渲染方法,将model数据填充到request域