高级参数绑定
* 绑定数组
当表单提交多个属性相同的参数,例如,选中的多个CheckBox,提交的是数组。
<form action="${pageContext.request.contextPath}/insertItem.action" method="post">
编号:<input type="text" name="item.id" ><br/>
名称:<input type="text" name="item.name" ><br/>
出厂时间:<input type="text" name="item.time" ><br/>
备注:<input type="text" name="item.remark" ><br/>
颜色:
<input type="checkbox" name="color" value="1">黑色
<input type="checkbox" name="color" value="2">天空蓝
<input type="checkbox" name="color" value="3">玫瑰金<br/>
<input type="submit" value="提交">
映射器方法里面使用数组进行接收
* 第一种方式,直接在方法形参里面,定义一个同名的数组,接收
@RequestMapping("/insertItem.action")
public String insertItem(QueryVo queryVo,Integer[] color){
return "itemList";
}
* 第二种方法,将数组封装到QueryVO中。
public class QueryVo {
private Item item;
private Integer[] color;
public Integer[] getColor() {
return color;
}
public void setColor(Integer[] color) {
this.color = color;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
}
@RequestMapping("/insertItem.action")
public String insertItem(QueryVo queryVo){
return "itemList";
}
* 将表单的数据绑定到List
需求:批量修改商品的信息
1. 定义pojo
public class QueryVo {
private Item item;
private Integer[] color;
//接受多个商品信息pojo
private List<Item> list;
public List<Item> getList() {
return list;
}
public void setList(List<Item> list) {
this.list = list;
}
public Integer[] getColor() {
return color;
}
public void setColor(Integer[] color) {
this.color = color;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
}
2. 定义界面,这里需要注意
<form action="${pageContext.request.contextPath}/editItems.action">
<table cellpadding="0" border="1" cellspacing="0" >
<thead>
<tr style="text-align: center;">
<th>编号</th>
<th>名称</th>
<th>时间</th>
<th>备注</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:if test="${not empty list }">
<c:forEach items="${list }" var="obj" varStatus="s">
<tr style="text-align: center;">
<td>
<input type="text" name="list['${s.index}'].id" value="${obj['id']}">
</td>
<td>
<input type="text" name="list['${s.index}'].name" value="${obj.name }">
</td>
<td>
<input type="text" name="list['${s.index}'].time" value='<fmt:formatDate pattern="yyyyMMdd HH:mm:ss" value="${obj.time }"/>'>
</td>
<td>
<input type="text" name="list['${s.index}'].remark" value="${obj.remark }">
</td>
<td><a style="color: red;" href="">修改</a></td>
</tr>
</c:forEach>
</c:if>
</tbody>
</table>
<input type="submit" value="提交">
</form>
name属性,定义为list[索引].属性名的形式
另外,关于jstl里面foreach元素迭代的补充说明,begin、end、step属性表示起始序号,结束序号,跳跃步伐
属性:varStatus = "s"
${s.index} 输出行号,从0开始
${s.count} 输出行号,从1开始
${s.first} 判断是否是集合中的第一项,true/false
${s.last} 判断是否是集合中的最后一项 true/false
3. 定义映射器方法
@RequestMapping("/editItems.action")
public String editItems(QueryVo qv){
测试,打个断点看下
@RequestMapping注解
URL 路径映射
* 添加在类上,限定映射路径
@Controller
@RequestMapping("item")
public class ItemController {
之前:http://localhost:8080/工程名/itemList.action
加上类映射限制后,访问映射方法的路径改为 http://localhost:8080/工程名/item/itemList.action
* 请求方法限定
一个映射器方法可以处理多个映射路径,并限制方法访问类型
限定为get请求
@Controller
@RequestMapping("item")
public class ItemController {
@RequestMapping(value={"/itemList.action","/itemInfo.action"},method=RequestMethod.GET)
public String itemList(
HttpServletRequest request,
Model model,
@RequestParam(value="itemId",required=false,defaultValue="")
Integer id
){
Controller方法返回值
1. 返回ModelAndView
2. 返回void
形参上获取request,response,转发或者重定向,写回数据
3. 字符串
3.1 逻辑视图名,数据仍然封装到model中
@RequestMapping(value={"/itemList.action","/itemInfo.action"},method=RequestMethod.GET)
public String itemList(
HttpServletRequest request,
Model model,
@RequestParam(value="itemId",required=false,defaultValue="")
Integer id
){
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
List<Item> list = new ArrayList<Item>();
list.add(new Item(1, "小米1", new Date(), "千元神机!"));
list.add(new Item(2, "小米2", new Date(), "千元神机!"));
list.add(new Item(3, "小米3", new Date(), "千元神机!"));
list.add(new Item(4, "小米4", new Date(), "千元神机!"));
list.add(new Item(5, "小米5", new Date(), "千元神机!"));
model.addAttribute("list", list);
return "itemList";
}
3.2 Redirect重定向
在Controller方法中重定向到一个新的URL中,进行重定向,请求中携带的参数丢失,如果想要携带参数适用?进行参数拼接
@RequestMapping("/editItems.action")
public String editItems(QueryVo qv){
List<Item>list = qv.getList();
if(list!=null){
for(int i =0 ;i<list.size();i++){
System.out.println(list.get(i).getId());
}
}
return "redirect:itemList.acition?id=1";
}
3.3 转发,从一个Controller方法转发到另一个Controller方法
因为转发的特点,response和request都是同一个。转发后的处理器方法中可以获取前一个处理器方法中获取到的参数
,如果在请求中的参数名称和方法中的形参不一致,可以使用注解@Requestparam进行参数绑定
@RequestMapping("/editItems.action")
public String editItems(Item item){
//.......
return "forward:queryItem.action";
}
@RequestMapping("/queryItem.action")
public String queryItem(@RequestParam(value="id")Integer itemId){
//TODO
return "";
}
SpringMVC的异常处理器
系统中的异常分为两类,预期异常和运行时异常,预期异常可以try catch进行捕获,运行时异常只能多测试,减少发生。
SpringMVC中的异常解决方案,将dao、service、controller的异常向上抛出,不进行捕获,交由SpringMVC的前端控制器,再由前端控制器交给异常处理器统一处理。
自定义异常类:
/**
* 自定义异常
* @author zhouy
*
*/
public class BusiException extends Exception{
private static final long serialVersionUID = -1175358759985574587L;
//异常信息
private String message;
public BusiException() {
super();
}
public BusiException(String message){
super(message);
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
异常处理器:
public class BusinessExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(
HttpServletRequest request,
HttpServletResponse response, Object paramObject,
Exception exception) {
String message = "";
if(exception instanceof BusiException){
BusiException be = (BusiException) exception;
message = be.getMessage();
}else{
//否则从堆栈中获取异常信息
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
exception.printStackTrace(pw);
message = sw.toString();
}
//...处理异常信息,发送短信。。。
//跳转到异常页面
ModelAndView mav = new ModelAndView();
mav.addObject("msg", message);
mav.setViewName("error");
return mav;
}
}
在springMVC.xml中配置全局异常处理器
<!-- 全局异常处理器 -->
<bean id="beh" class="cn.bing.exception.BusinessExceptionHandler"></bean>
测试一下:
定义页面:
<body>
<h1>出了点小问题!!!!</h1>
<h2>${msg}</h2>
</body>
修改下controller方法:
@Controller
@RequestMapping("item")
public class ItemController {
@RequestMapping(value={"/itemList.action","/itemInfo.action"},method=RequestMethod.GET)
public String itemList(
HttpServletRequest request,
Model model,
@RequestParam(value="itemId",required=false,defaultValue="")
Integer id
) throws BusiException{
if(id!=null&&id==1){
throw new BusiException("我的业务异常.....");
}
int i = 1/0;
启动web:
1. http://localhost:8081/goldSpringDemo/item/itemList.action?itemId=1 ,页面出现的 我的业务异常
2. http://localhost:8081/goldSpringDemo/item/itemList.action ,捕获的是运行时异常