复制前天的工程springmvc-mybatis(Java网课基础笔记(20))作为今天开发的工程mybatis2
1.高级参数的绑定
需求:在商品列表页面选择多商品,然后删除。
分析:功能要求商品列表页面中的每个商品前有一个checkbox,选中多个商品后点击删除按钮把商品id传递给Controller,根据商品id删除商品信息
演示获取id数组
(1)数组类型的参数绑定
- 修改itemList.jsp页面,增加多选框,提交url是queryitem.action
<form action="${pageContext.request.contextPath }/queryItem.action" method="post">
查询条件:
<table width="100%" border=1>
<tr>
<td>商品id<input type="text" name="item.id"/> </td>
<td>商品名称<input type="text" name="item.name"/> </td>
<td><input type="submit" value="查询"/></td>
</tr>
</table>
商品列表:
<table width="100%" border=1>
<tr>
<td>编号</td>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
<td>操作</td>
</tr>
<c:forEach items="${itemList }" var="item">
<tr>
<td><input type="checkbox" name="ids" value="{item.id }">${item.id }</td>
<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 }/itemEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
</table>
</form>
页面选中多个checkbox向controller方法传递
本身属于一个form表单,提交url是queryItem.action
- Controller
Controller方法中可以用String接收,或者pojoString[]属性接收。
定义QueryVo增加属性ids
public class QueryVo {
private Item item;
//用对象的属性接收数组,属性名要同页面的name值相同
private String[] ids;
public String[] getIds() {
return ids;
}
public void setIds(String[] ids) {
this.ids = ids;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
}
ItemController修改queryItem方法
//绑定包装数据类型 绑定数组,可以用两种方法,pojo的属性接收,和直接接收
@RequestMapping("/queryItem")
public String queryItem(QueryVo queryVo,Integer[] ids){
System.out.println(queryVo.getItem().getId());
System.out.println(queryVo.getItem().getName());
System.out.println(queryVo.getIds().length);
System.out.println(ids.length);
return "success";
}
控制台输出
(2)将表单的数据绑定到List
需求:实现商品数据的批量修改
分析:
- 在商品列表页面中可以对商品信息进行修改
- 可以批量提交修改后的商品数据
- 定义pojo
List中存放对象,并将定义的List放在包装类QueryVo中使用包装pojo对象接收。
//用对象的属性接收List集合
private List<Item> itemList;
public List<Item> getItemList() {
return itemList;
}
public void setItemList(List<Item> itemList) {
this.itemList = itemList;
}
- jsp改造
name属性必须是list属性名+下标+元素属性
itemList.jsp(全都改为输入框,可直接批量修改)
<c:forEach items="${itemList }" var="item" varStatus="s">
<tr>
<td><input type="checkbox" name="ids" value="${item.id}"/></td>
<td>
<input type="hidden" name="itemList[${s.index}].id" value="${item.id }"/>
<input type="text" name="itemList[${s.index}].name" value="${item.name }"/>
</td>
<td><input type="text" name="itemList[${s.index}].price" value="${item.price }"/></td>
<td><input type="text" name="itemList[${s.index}].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
<td><input type="text" name="itemList[${s.index}].detail" value="${item.detail }"/></td>
<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
在itemController.java设置断点,进入debug模式
测试(拿到数据即可,不进行数据库操作)
注意:接收List类型的数据必须是pojo的属性,如果方法的形参为ArryList类型无法正确收到数据。
2.@RequestMapping
通过@RequestMapping注解可以定义不同的处理器映射规则
- URL路径映射
@RequestMapping(value="itemList")或 @RequestMapping("/itemList")
value的值是数组,可以将多个url映射到同一方法
//或@RequestMapping(value="itemList")
@RequestMapping("/itemList")
public ModelAndView queryAll(){
//调用service层获取数据
List<Item> items = itemService.queryItemList();
//把数据装在modelAndView
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemList", items);
//返回视图(前缀后缀不用写)
modelAndView.setViewName("itemList");
return modelAndView;
}
@RequestMapping(value= {"itemList","itemListAll"})
//@RequestMapping("/itemList")
public ModelAndView queryAll(){
//调用service层获取数据
List<Item> items = itemService.queryItemList();
//把数据装在modelAndView
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemList", items);
//返回视图(前缀后缀不用写)
modelAndView.setViewName("itemList");
return modelAndView;
}
http://localhost:8080/SpringMVC-mybatis2/itemList.action
http://localhost:8080/SpringMVC-mybatis2/itemListAll.action
都是同一个页面
- 添加在类上面
在class上添加@RequestMapping(url)指定通用请求前缀,限制此类下的所有方法请求url必须以请求前缀开头
可以使用此方法对url进行分类管理
@RequestMapping("item")
public class ItemController {
...
}
此时需要进入queryItemList()方法的请求url为:
http://localhost:8080/SpringMVC-mybatis2/item/itemList.action或
http://localhost:8080/SpringMVC-mybatis2/item/itemListAll.action
3.请求方法限定
除了可以对url进行设置,还可以限定请求进来的方法
- 限定get方法(默认)
@RequestMapping(value= {"itemList","itemListAll"},method = RequestMethod.GET)
- 限定post方法
@RequestMapping(value= {"itemList","itemListAll"},method = RequestMethod.POST)
如果用get方法提交,则出现405错误
- get和post都可以
@RequestMapping(value= {"itemList","itemListAll"},method = {RequestMethod.GET,RequestMethod.POST})
4.Controller方法返回值
- 返回ModelAndView
controller方法中定义ModelAndView对象并返回,对象中可以添加model数据、指定view。
- 返回void
在Controller方法形参上可以定义request和response,使用request或response指定响应结果
@RequestMapping("/queryItem")
public void queryItem(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
//1.使用reques进行转发(地址栏不会变)
request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request, response);
//2.使用response进行重定向到编辑页面
response.sendRedirect("/SpringMVC-mybatis2/itemEdit.action");
//3.使用response直接显示(输出流输出字符串)
response.getWriter().print("{\"abc\":123}");
}
使用request进行转发
点击查询(实际上是跳转到成功界面胆慑地址栏还是queryItem.action
使用response进行重定向到编辑页面(地址栏会变化)
点击查询
使用response直接显示(输出流)
点击查询
- 返回字符串
逻辑视图名
controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址
//指定逻辑视图名,经过视图解析器解析为jsp物理视图路径:
/WEB-INF/jsp/itemList.jsp
retrun "itemList";
Redirect重定向
//修改数据
@RequestMapping("/updateitem")
public String updateItem(Item item){
//更新商品
itemService.updateItem(item);
//修改商品成功后,重定向到商品编辑页面
//重定向后浏览器地址栏变更为重定向的地址
//重定向相当于执行了新的request和respons,所有之前的请求参数都会丢失
//如果要指定请求参数,需要在重定向的url后面添加?itemId=1这样的请求参数
return "redirect:/itemEdit.action?itemId="+item.getId();
}
Controller方法返回字符串可以重定向到一个url地址
如下商品修改提交后重定向到编辑页面
选中台式机点击修改
修改后点击提交,注意地址栏的变化
forward转发
Controller方法执行后继续执行另一个Controller方法
如下商品修改提交后转向到商品修改页面,修改商品的id参数可以带到商品修改方法中
@RequestMapping("/updateitem")
public String updateItem(Item item){
//更新商品
itemService.updateItem(item);
//修改商品成功后,继续执行另一个方法
//使用转发的方式实现,转发后浏览器地址栏还是原来的请求地址
//转发并没有执行新的request和response,所以之前的请求参数都存在
return "forward:/itemListAll.action";
}
点击提交直接跳转到商品列表页面
5.springmvc异常处理
springmvc在处理请求过程中出现异常信息交给异常处理器进行处理,自定义异常处理器可以实现的异常处理逻辑。
- 异常处理思想
Throwable(error,Exception)
系统中异常包括两类:已检查异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交给异常处理器进行异常处理
- 自定义异常类
如果controller、sercice、dao抛出此类异常说明是系统预期处理的异常信息
package com.feng.ssm.exception;
public class Myexception extends Exception{
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Myexception(String message) {
super();
this.message = message;
}
}
- 自定义异常处理器
public class CustomHandleException implements HandlerExceptionResolver{
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception exception) {
// TODO Auto-generated method stub
//自定义异常信息
String msg;
//判断异常类型
if(exception instanceof Myexception) {
//如果是自定义异常,读取异常信息
msg=exception.getMessage();
}else {
//如果是运行时异常,则取错误堆栈,从堆栈中获取异常信息
Writer out=new StringWriter();
PrintWriter s=new PrintWriter(out);
exception.printStackTrace(s);
msg=out.toString();
}
//把错误信息发给相关人员,邮件、短信等方式
//返回错误页面,给用户友好页面显示错误信息
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("msg",msg);
modelAndView.setViewName("error");
return modelAndView;
}
}
- 异常处理器配置
在springmvc.xml添加
<!-- 配置全局异常处理器 -->
<bean id="customHandleException" class="com.feng.ssm.exception.CustomHandleException"></bean>
- 创建错误error页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>系统发生异常了</h1>
<br>
<h3>异常信息</h3>
<br>
<h3>${msg}</h3>
</body>
</html>
- 测试
- 在itemController.java中增加异常
@RequestMapping(value= {"itemList","itemListAll"},method = {RequestMethod.GET,RequestMethod.POST})
//@RequestMapping("/itemList")
public ModelAndView queryAll(){
int i=1/0;
//调用service层获取数据
List<Item> items = itemService.queryItemList();
//把数据装在modelAndView
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemList", items);
//返回视图(前缀后缀不用写)
modelAndView.setViewName("itemList");
return modelAndView;
}
运行时抛出异常
- 自定义异常