第1章:SpringMVC简介
1.1 什么是SpringMVC
- SpringMVC和Struts2都属于表现层的框架,它是Spring框架的一个组件。
1.2 SpringMVC的处理流程
第2章:SpringMVC入门程序
2.1 场景描述
- 在浏览器地址栏中输入
list.action
跳转到一个商品列表的页面。
2.2 步骤分析
- 创建web工程
- 添加jar:springMVC、spring、junit
- 在
web.xml
中添加一个DispatcherServlet[前端控制器]。 - DispatcherServlet需要初始化一个springMVC容器,所以需要添加springmvc.xml
- 创建一个商品pojo
- 创建一个jsp页面
- 创建一个商品的Controller
传统方式:实现一个Controller接口
注解方式:添加一个@Controller标签 - 把Controller配置到springmvc.xml中(传统方式)
开启包扫描(注解方式) - tomcat测试
2.3 步骤一:创建Web项目
2.4 步骤二:导入jar包
2.5 步骤三:在web.xml
中配置DispatcherServlet前端控制器
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
springmvc
*.action
2.6 步骤四:创建springmvc.xml
配置文件
- 在工程下新建一个
Source Folder
文件夹,在此新建springmvc.xml
。
2.7 步骤五:新建一个商品POJO
package com.itzhouq.springmvc.pojo
public class Items {
private Integer id;
private String name;
private Float price;
private String pic;
private Date createtime;
private String detail;
//set/get方法
}
2.8 步骤六:创建一个jsp页面
/SpringMVC_01/WebContent/jsp/itemList.jsp
<%@ 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"%>
查询商品列表
2.9 步骤七:创建商品的Controller
2.9.1 传统方式:实现一个Controller
接口
com.itzhouq.springmvc.controller.ItemsController
package com.itzhouq.springmvc.controller;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.itzhouq.springmvc.pojo.Items;
public class ItemsController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 模拟商品数据
List list =new ArrayList();
for (int i = 0; i < 10; i++) {
Items items = new Items();
items.setId(i);
items.setCreatetime(new Date());
items.setName("小米手机"+i);
items.setDetail("国产");
items.setPrice((float) (1000*i));
list.add(items);
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemList",list); // 相当于把数据放入了request域中
// ViewName逻辑视图:就是jsp路径
modelAndView.setViewName("/jsp/itemList.jsp");
return modelAndView;
}
}
2.9.2 注解方式:添加一个@Controller
注解
- 传统开发方式,
Controller
类中只能有一个方法。这显然不符合实际开发的需要。所以实际开发采用注解方式。 com.itzhouq.springmvc.controller.ItemsController2
package com.itzhouq.springmvc.controller;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.itzhouq.springmvc.pojo.Items;
@Controller
public class ItemsController2{
@RequestMapping("/list")
public ModelAndView list(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 模拟商品数据
List list =new ArrayList();
for (int i = 0; i < 10; i++) {
Items items = new Items();
items.setId(i);
items.setCreatetime(new Date());
items.setName("华为手机"+i);
items.setDetail("也是国产");
items.setPrice((float) (1000*i));
list.add(items);
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemList",list); // 相当于把数据放入了request域中
// ViewName逻辑视图:就是jsp路径
modelAndView.setViewName("/jsp/itemList.jsp");
return modelAndView;
}
}
2.10 把Controller
配置到springmvc.xml
中
2.10.1 传统方式:实现一个Controller
接口的方式的配置
- 在
springmvc.xml
中添加以下配置
- 测试:开启服务器,访问http://localhost/SpringMVC_01/list.action
- 流程描述:当在浏览器中输入
http://localhost/SpringMVC_01/list.action
的时候,请求会首先经过入口web.xml
。该文件中有一个前端控制器DispatcherServlet
,里面有配置
。请求符合*.action *.action
,所以请求会进入前端控制器中。前端控制器会初始化一个springMVC
容器。根据springMVC容器
的配置文件spring.xml
的配置。
- 可以看到请求
list.action
和name
的值相同,所以请求进入到对应的类ItemsController
。执行类中的方法,跳转到类中写明的jsp
页面。
2.10.2 注解方式:添加一个@Controller
注解
- 要使用注解开发,必须在
springmvc.xml
中开启注解扫描器。无需配置
。
- 测试:开启服务器,访问http://localhost/SpringMVC_01/list.action
- 注解方式的优势:可以使用注解
@RequestMapping("/list")
定位ItemsController
类中的不同方法,解决传统开发方式的问题。
第3章:SpringMVC的完整架构
3.1 框架结构
3.2 架构流程
- 流程图
- 流程描述
1、 用户发送请求至前端控制器DispatcherServlet
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器
(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
5、 执行处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9、 ViewReslover解析后返回具体View
10、 DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户
3.3 组件说明
-
DispatcherServlet
:前端控制器用户请求到达前端控制器,它就相当于
mvc
模式中的c
,dispatcherServlet
是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet
的存在降低了组件之间的耦合性。dispatcherServlet
有三大组件。
-
HandlerMapping
:处理器映射器HandlerMapping
负责根据用户请求找到Handler
即处理器,springmvc
提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。Handler
:处理器Handler
是继DispatcherServlet
前端控制器的后端控制器,在DispatcherServlet
的控制下Handler
对具体的用户请求进行处理。由于Handler
涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler
。
- 配置注解开发方式新版本的处理器映射器的方式:在
springmvc.xml
文件中
- HandlAdapter`:处理器适配器
通过HandlerAdapter
对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
- 配置最注解开发方式新版本的处理器适配器方式:在
springmvc.xml
文件中
- 配置最注解开发方式新版本的处理器映射器和处理器适配器的方式可以简化:
-
View Resolver
:视图解析器View Resolver
负责将处理结果生成View
视图,View Resolver
首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View
进行渲染将处理结果通过页面展示给用户。View
:视图springmvc
框架提供了很多的View
视图类型的支持,包括:jstlView
、freemarkerView
、pdfView
等。我们最常用的视图就是jsp
。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。- 在
springmvc.xml
文件配置如下:
- 在
第4章:SpringMVC和Mybatis整合
- 需求分析:整合
SpringMVC
和Mybatis
,展示商品的列表。
4.1 整合的思路
-
Dao
层:-
sqlMapConfig.xml
:可以为空,可以不需要 -
applicationContext-dao.xml
:- 数据库连接池
-
SqlSessionFactory
对象,需要在Spring
和mybatis
整合包下的。 - 配置
mapper
文件扫描器,用来生成代理对象。
-
-
Service
层:-
application-service.xml
:事务管理、包扫描器【扫描@Service
注解】
-
- 表现层:
- 包扫描器,扫描
@Controller
注解的类 - 配置注解驱动
- 视图解析器:前缀和后缀
- 包扫描器,扫描
-
web.xml
:- 前端控制器
- 监听器
- 乱码问题解决
4.2 整合的步骤
- 创建数据库
- 创建
web
工程 - 添加
jar
包:mybatis
、mybatis
扩展包、spring
、spring
和mybatis
整合包、junit
、springmvc
。 - 添加配置文件:
applicationContext-dao.xml
applicationContext-service.xml
jdbc.properties
log4j.properties
springmvc.xml
- 持久层开发
- 业务层开发:接口+实现类
- 表现层开发:注解开发方式
4.3 开始整合
4.3.1 创建数据库和表
- 新建数据库
springmvc
,新建查询springmvc.sql
。
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for items
-- ----------------------------
DROP TABLE IF EXISTS `items`;
CREATE TABLE `items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL COMMENT '商品名称',
`price` float(10,1) NOT NULL COMMENT '商品定价',
`detail` text COMMENT '商品描述',
`pic` varchar(64) DEFAULT NULL COMMENT '商品图片',
`createtime` datetime NOT NULL COMMENT '生产日期',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of items
-- ----------------------------
INSERT INTO `items` VALUES ('1', '台式机', '3000.0', '该电脑质量非常好!!!!', null, '2016-02-03 13:22:53');
INSERT INTO `items` VALUES ('2', '笔记本', '6000.0', '笔记本性能好,质量好!!!!!', null, '2015-02-09 13:22:57');
INSERT INTO `items` VALUES ('3', '背包', '200.0', '名牌背包,容量大质量好!!!!', null, '2015-02-06 13:23:02');
4.3.2 创建工程
- 创建工程,导入jar包。
4.3.3 配置文件
-
web.xml
:加载applicationContext-*.xml
的监听器和解决乱码问题的监听器以及前端控制器
springmvc-mybatis
CharacterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
CharacterEncodingFilter
/*
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
springmvc
*.action
org.springframework.web.context.ContextLoaderListener
contextConfigLocation
classpath:applicationContext-*.xml
-
applicationContext-dao.xml
:加载数据库配置文件,将映射文件交给Spring
容器管理,配置映射器扫描器
-
applicationContext-service.xml
:配置事务管理和使用注解需要的包扫描器
-
springmvc.xml
:配置注解需要的包扫描器、注解驱动、视图解析器的前缀和后缀
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springmvc?characterEncoding=utf-8
jdbc.username=root
jdbc.password=2626
log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
4.3.4 持久层
-
com.itzhouq.ssm.mapper.ItemsMapper
:持久层的接口
package com.itzhouq.ssm.mapper;
import java.util.List;
import com.itzhouq.ssm.pojo.Items;
public interface ItemsMapper {
List findAll();
Items findById(int itemId);
}
-
com/itzhouq/ssm/mapper/ItemsMapper.xml
:持久层的映射器
4.3.4 实体类
com.itzhouq.ssm.pojo.Items
package com.itzhouq.ssm.pojo;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
public class Items {
private Integer id;
private String name;
private Float price;
private String pic;
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date createtime;
private String detail;
//set/get方法
}
4.3.5 业务层
-
com.itzhouq.ssm.service.ItemService
:业务层的接口
package com.itzhouq.ssm.service;
import java.util.List;
import com.itzhouq.ssm.pojo.Items;
public interface ItemService {
public List findAll();
public Items findById(int itemId);
}
-
com.itzhouq.ssm.service.impl.ItemServiceImpl
:业务层的实现类
package com.itzhouq.ssm.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.itzhouq.ssm.mapper.ItemsMapper;
import com.itzhouq.ssm.pojo.Items;
import com.itzhouq.ssm.service.ItemService;
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private ItemsMapper itemsMapper;
public List findAll() {
List list = itemsMapper.findAll();
return list;
}
@Override
public Items findById(int itemId) {
Items item = itemsMapper.findById(itemId);
return item;
}
}
4.3.6 表现层
com.itzhouq.ssm.controller.ItemsController
package com.itzhouq.ssm.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.itzhouq.ssm.pojo.Items;
import com.itzhouq.ssm.service.ItemService;
@Controller
public class ItemsController {
@Autowired
private ItemService itemService ;
@RequestMapping("/list")
public String showAllList(Model model){
List itemList = itemService.findAll();
model.addAttribute("itemList",itemList);
return "itemList";
}
// itemEdit.action?id=1
// 展示修改页面
@RequestMapping("/itemEdit")
public String itemEdit(@RequestParam(value="id",required=false,defaultValue="1")int itemId,HttpServletRequest request, HttpServletResponse response,Model model){
Items items = itemService.findById(itemId);
model.addAttribute("item", items);
// 逻辑视图:jsp的路径
return "editItem";
}
}
4.3.7 页面
WebContent/jsp/itemList.jsp
<%@ 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"%>
查询商品列表
WebContent/jsp/editItem.jsp
<%@ 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"%>
修改商品信息
4.3.8 测试
- 展示商品:发布项目,访问http://localhost/Spring-mybatis-test/list.action
- 修改商品:点击上图修改按钮进入修改页面
第5章:SpringMVC接收参数
5.1 @RequestParam
绑定参数
- 需求分析:比如在一个商品的编辑页面,需要展示商品的信息。那么在编辑商品信息之前,需要提前根据商品的
id
查询商品信息,然后展示到页面。这时候的请求是/itemEdit.action?id=5
。这里假设id
为5。
- 如果请求中的参数名称和处理器中的形参的名称不一致的时候,就不能自动绑定。需要借助
@RequestParam
注解来绑定。
5.2 默认支持的参数类型
处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值。
HttpServletRequest request
HttpServletResponse response
HttpSession session
Model model
5.3 绑定POJO类型
- 需求分析:将页面修改后的商品信息保存到数据库中。这时候请求的
url
为/updateitem.action
。参数是表单中的数据。更新成功后需要跳转页面。如果提交的参数很多,或者表单中的内容很多的时候可以使用pojo
接收数据。要求是pojo
对象中的属性和表单中input
的name
属性一致。 - 页面定义如下:
-
pojo
定义:
- 请求的参数和
pojo
的属性名称一致,会自动请求参数赋值给pojo
属性。
- 注意:此时提交的表单中不要有日期类型的数据,否则会报400错误。如果想提交日期类型的数据需要用到后面的自定义参数绑定的内容。
- 在数据绑定
pojo
类型的的过程中有可能会出现乱码问题。
5.4 解决乱码问题
- 如果请求的方式是
POST
请求,需要使用过滤器。在web.xml
中添加以下配置:
CharacterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
CharacterEncodingFilter
/*
- 如果请求方式是
GET
请求,有两种解决办法。
- 方式一:修改
tomcat
服务器配置文件server.xml
第64行。
- 方式二:对参数进行重新编码
String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
5.5 绑定包装POJO
- 需求分析:使用包装的pojo接收商品信息的查询条件。
- 包装对象定义如下:
- 页面定义:
-
Controller
方法定义如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getItems());
}
- 接收查询条件:
@RequestMapping("/queryitem")
public String queryItem(QueryVo queryVo) {
System.out.println(queryVo.getItems().getName());
System.out.println(queryVo.getItems().getPrice());
return null;
}
5.6 自定义参数绑定
- 需求分析:在商品修改页面可以修改商品的生产日期,并且根据业务需求自定义日期格式。
- 自定义
Converter
转化器
public class DateConverter implements Converter {
@Override
public Date convert(String source) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return simpleDateFormat.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
-
定义好转化器之后需要配置转化器,这里有两种配置方式。第二种更简单。
- 方式一:在
springmvc.xml
配置文件中添加如下配置:
- 方式二:在
pojo
类的日期属性上添加如下注解:
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") private Date createtime;
- 方式一:在
由于日期数据有很多种格式,所以springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定。前端控制器接收到请求后,找到注解形式的处理器适配器,对
RequestMapping
标记的方法进行适配,并对方法中的形参进行参数绑定。在springmvc
这可以在处理器适配器上自定义Converter
进行参数绑定。如果使用
可以在此标签上进行扩展。
第6章:SpringMVC和Struts2的区别
-
springmvc
的入口是一个servlet
即前端控制器,而struts2
入口是一个filter
过虑器。 -
springmvc
是基于方法开发(一个url
对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2
是基于类开发,传递参数是通过类的属性,只能设计为多例。 -
Struts
采用值栈存储请求和响应的数据,通过OGNL
存取数据,springmvc
通过参数解析器是将request
请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView
对象,最后又将ModelAndView
中的模型数据通过request
域传输到页面。Jsp
视图解析器默认使用jstl
。