SpringMVC第二天
1. 回顾
1、Springmvc介绍? Springmvc是Spring公司
2、Springmvc入门程序
第一步:Web工程
第二步:导Jar包
第三步:web.xml配置前端控制器 servlet Filtter
*.do.action /拦截所有不包含jsp /*拦截所有(真拦截)
第四步:配置上下文springmvc.xml 配置扫描@Controller
第五步:Handler Controller 程序员自己写的 @RequestMapping(value=”/item/queryItem.action)
Public ModelAndView quyerITem(){
跳转/WEB-INF/jsp/itemList.jsp
}
商品列表查询
3、 springmvc 原理图
用户请求到前端控制器、让处理器映射器去找相应的路径 对应的方法
返回找到的方法
前端控制器、让处理器适配器 去执行此方法(执行前绑定参数)
返回ModelAndView
前端控制器、让视图解析器 数据填充在.jsp的标签处、html
一个中心
三大组件
写的
Handler JSP
4、参数绑定 简单类型 queryItem(Integer id) jsp页面上input type=text name=id
POJO Item
修改商品提交 input type=text name = pojo里面要一致
包装POJO QueryVo(里面Item) name=item.id
自定义参数绑定
日期类型
Yyyy-MM_dd
2. 计划
1、高级参数绑定
a) 数组类型的参数绑定
b) List类型的绑定
2、@RequestMapping注解的使用
3、Controller方法返回值
4、Springmvc中异常处理
5、图片上传处理
6、Json数据交互
7、Springmvc实现RESTful
8、拦截器
3. 高级参数绑定
3.1. 复制工程
把昨天的springmvc-web工程复制一份,作为今天开发的工程
复制工程,如下图:
粘贴并修改工程名为web2,如下图:
工程右键点击,如下图:
修改工程名,如下图:
3.2. 绑定数组
3.2.1. 需求
在商品列表页面选中多个商品,然后删除。
3.2.2. 需求分析
功能要求商品列表页面中的每个商品前有一个checkbok,选中多个商品后点击删除按钮把商品id传递给Controller,根据商品id删除商品信息。
我们演示可以获取id的数组即可
3.2.3. Jsp修改
修改itemList.jsp页面,增加多选框,提交url是queryItem.action
页面选中多个checkbox向controller方法传递
本身属于一个form表单,提交url是queryItem.action
3.2.4. Controller
Controller方法中可以用String[]接收,或者pojo的String[]属性接收。两种方式任选其一即可。
定义QueryVo,如下图:
ItemController修改queryItem方法:
打断点测试
效果,如下图:
3.3. 将表单的数据绑定到List
3.3.1. 需求
实现商品数据的批量修改。
3.3.2. 开发分析
开发分析
1. 在商品列表页面中可以对商品信息进行修改。
2. 可以批量提交修改后的商品数据。
3.3.3. 定义pojo
List中存放对象,并将定义的List放在包装类QueryVo中
使用包装pojo对象接收,如下图:
3.3.4. Jsp改造
前端页面应该显示的html代码,如下图:
分析发现:name属性必须是list属性名+下标+元素属性。
Jsp做如下改造:
${current} 当前这次迭代的(集合中的)项
${status.first} 判断当前项是否为集合中的第一项,返回值为true或false
${status.last} 判断当前项是否为集合中的最
varStatus属性常用参数总结下:
${status.index} 输出行号,从0开始。
${status.count} 输出行号,从1开始。
${status.后一项,返回值为true或false
begin、end、step分别表示:起始序号,结束序号,跳跃步伐。
3.3.5. 效果
这里只演示List的绑定,能够接收到list数据。
可以拿到数据即可,不做数据库的操作。
测试效果如下图:
注意:接收List类型的数据必须是pojo的属性,如果方法的形参为ArrayList类型无法正确接收到数据。
4. @RequestMapping
通过@RequestMapping注解可以定义不同的处理器映射规则。
4.1. URL路径映射
@RequestMapping(value="item")或@RequestMapping("/item")
value的值是数组,可以将多个url映射到同一个方法
4.2. 添加在类上面
在class上添加@RequestMapping(url)指定通用请求前缀, 限制此类下的所有方法请求url必须以请求前缀开头
可以使用此方法对url进行分类管理,如下图:
此时需要进入queryItemList()方法的请求url为:
http://127.0.0.1:8080/springmvc-web2/item/itemList.action
或者
http://127.0.0.1:8080/springmvc-web2/item/itemListAll.action
注意:练习此项后,把类上的@RequestMapping注释掉,如下:
以方便后面的练习
4.3. 请求方法限定
除了可以对url进行设置,还可以限定请求进来的方法
u 限定GET方法
@RequestMapping(method = RequestMethod.GET)
如果通过POST访问则报错:
HTTP Status 405 - Request method 'POST' not supported
例如:
@RequestMapping(value = "itemList",method = RequestMethod.POST)
u 限定POST方法
@RequestMapping(method = RequestMethod.POST)
如果通过GET访问则报错:
HTTP Status 405 - Request method 'GET' not supported
u GET和POST都可以
@RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})
5. Controller方法返回值
5.1. 返回ModelAndView
controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。
参考第一天的内容
5.2. 返回void
在Controller方法形参上可以定义request和response,使用request或response指定响应结果:
1、使用request转发页面,如下:
request.getRequestDispatcher("页面路径").forward(request, response);
request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request, response);
2、可以通过response页面重定向:
response.sendRedirect("url")
response.sendRedirect("/springmvc-web2/itemEdit.action");
3、可以通过response指定响应结果,例如响应json数据如下:
response.getWriter().print("{"abc":123}");
5.2.1. 代码演示
以下代码一次测试,演示上面的效果
5.3. 返回字符串
5.3.1. 逻辑视图名
controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
参考第一天内容
5.3.2. Redirect重定向
Contrller方法返回字符串可以重定向到一个url地址
如下商品修改提交后重定向到商品编辑页面。
5.3.3. forward转发
Controller方法执行后继续执行另一个Controller方法
如下商品修改提交后转向到商品修改页面,修改商品的id参数可以带到商品修改方法中。
需要修改之前编写的根据id查询商品方法
因为请求进行修改商品时,请求参数里面只有id属性,没有itemId属性
修改,如下图::
6. 异常处理器
springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。
6.1. 异常处理思路
系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:
// 异常信息
6.2. 自定义异常类 |
为了区别不同的异常,通常根据异常类型进行区分,这里我们创建一个自定义系统异常。
如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息。
6.3. 自定义异常处理器
6.4. 异常处理器配置
在springmvc.xml中添加:
6.5. 错误页面
6.6. 异常测试
修改ItemController方法“queryItemList”,抛出异常:
7. 上传图片
7.1. 配置虚拟目录
在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加:
<Context docBase="D:developupload emp" path="/pic" reloadable="false"/>
访问http://localhost:8080/pic即可访问D:developupload emp下的图片。
也可以通过eclipse配置,如下图:
复制一张图片到存放图片的文件夹,使用浏览器访问
测试效果,如下图:
7.2. 加入jar包
实现图片上传需要加入的jar包,如下图:
把两个jar包放到工程的lib文件夹中
7.3. 配置上传解析器
在springmvc.xml中配置文件上传解析器
7.4. jsp页面修改
在商品修改页面,打开图片上传功能,如下图:
设置表单可以进行文件上传,如下图:
7.5. 图片上传
在更新商品方法中添加图片上传逻辑
效果,如下图:
8. json数据交互
8.1. @RequestBody
作用:
@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容(json数据)转换为java对象并绑定到Controller方法的参数上。
传统的请求参数:
itemEdit.action?id=1&name=zhangsan&age=12
现在的请求参数:
使用POST请求,在请求体里面加入json数据
本例子应用:
@RequestBody注解实现接收http请求的json数据,将json数据转换为java对象进行绑定
8.2. @ResponseBody
作用:
@ResponseBody注解用于将Controller的方法返回的对象,通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端
本例子应用:
@ResponseBody注解实现将Controller方法返回java对象转换为json响应给客户端。
8.3. 请求json,响应json实现:
8.3.1. 加入jar包
如果需要springMVC支持json,必须加入json的处理jar
我们使用Jackson这个jar,如下图:
8.3.2. ItemController编写
8.3.3. 安装谷歌浏览器测试工具
安装程序在课后资料
参考安装文档,如下图:
8.3.4. 测试方法
测试方法,如下图:
8.3.5. 测试结果
如下图:
8.3.6. 配置json转换器
如果不使用注解驱动<mvc:annotation-driven />,就需要给处理器适配器配置json转换器,参考之前学习的自定义参数绑定。
在springmvc.xml配置文件中,给处理器适配器加入json转换器:
9. RESTful支持
9.1. 什么是restful?
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、修改、查询。
传统方式操作资源
http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST
使用RESTful操作资源
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE
9.2. 需求
RESTful方式实现商品信息查询,返回json数据
9.3. 从URL上获取参数
使用RESTful风格开发的接口,根据id查询商品,接口地址是:
http://127.0.0.1/item/1
我们需要从url上获取商品id,步骤如下:
1. 使用注解@RequestMapping("item/{id}")声明请求的url
{xxx}叫做占位符,请求的URL可以是“item /1”或“item/2”
2. 使用(@PathVariable() Integer id)获取url上的数据
如果@RequestMapping中表示为"item/{id}",id和形参名称一致,@PathVariable不用指定名称。如果不一致,例如"item/{ItemId}"则需要指定名称@PathVariable("itemId")。
http://127.0.0.1/item/123?id=1
注意两个区别
1. @PathVariable是获取url上数据的。@RequestParam获取请求参数的(包括post表单提交)
2. 如果加上@ResponseBody注解,就不会走视图解析器,不会返回页面,目前返回的json数据。如果不加,就走视图解析器,返回页面
10. 拦截器
10.1. 定义
Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
10.2. 拦截器定义
实现HandlerInterceptor接口,如下:
10.3. 拦截器配置
上面定义的拦截器再复制一份HandlerInterceptor2,注意新的拦截器修改代码:
System.out.println("HandlerInterceptor2....preHandle");
在springmvc.xml中配置拦截器
10.4. 正常流程测试
浏览器访问地址
http://127.0.0.1:8080/springmvc-web2/itemList.action
10.4.1. 运行流程
控制台打印:
HandlerInterceptor1..preHandle..
HandlerInterceptor2..preHandle..
HandlerInterceptor2..postHandle..
HandlerInterceptor1..postHandle..
HandlerInterceptor2..afterCompletion..
HandlerInterceptor1..afterCompletion..
10.5. 中断流程测试
浏览器访问地址
http://127.0.0.1:8080/springmvc-web2/itemList.action
10.5.1. 运行流程
HandlerInterceptor1的preHandler方法返回false,HandlerInterceptor2返回true,运行流程如下:
HandlerInterceptor1..preHandle..
从日志看出第一个拦截器的preHandler方法返回false后第一个拦截器只执行了preHandler方法,其它两个方法没有执行,第二个拦截器的所有方法不执行,且Controller也不执行了。
HandlerInterceptor1的preHandler方法返回true,HandlerInterceptor2返回false,运行流程如下:
HandlerInterceptor1..preHandle..
HandlerInterceptor2..preHandle..
HandlerInterceptor1..afterCompletion..
从日志看出第二个拦截器的preHandler方法返回false后第一个拦截器的postHandler没有执行,第二个拦截器的postHandler和afterCompletion没有执行,且controller也不执行了。
总结:
preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用
postHandler在拦截器链内所有拦截器返成功调用
afterCompletion只有preHandle返回true才调用
10.6. 拦截器应用
10.6.1. 处理流程
1、有一个登录页面,需要写一个Controller访问登录页面
2、登录页面有一提交表单的动作。需要在Controller中处理。
a) 判断用户名密码是否正确(在控制台打印)
b) 如果正确,向session中写入用户信息(写入用户名username)
c) 跳转到商品列表
3、拦截器。
a) 拦截用户请求,判断用户是否登录(登录请求不能拦截)
b) 如果用户已经登录。放行
c) 如果用户未登录,跳转到登录页面。
10.6.2. 编写登录jsp
10.6.3. 用户登陆Controller
10.6.4. 编写拦截器
10.6.5. 配置拦截器
只能拦截商品的url,所以需要修改ItemController,让所有的请求都必须以item开头,如下图:
在springmvc.xml配置拦截器