2.高级参数绑定(重点)
2.1.数组类型
数组类型的参数可以传递一批相同的数据到Controller的方法中。
2.1.1.需求
批量删除:在商品列表页面选中多个商品,然后删除。
2.1.2.需求分析
此功能要求商品列表页面中的每个商品前有一个checkbook,选中多个商品后点击删除按钮把商品id传递给Controller,根据商品id删除商品信息。
功能分解
前端:1)能选中多个商品;2)能提交选中的多个商品
后端:1)能接收到选中商品的id;2)进行删除处理
2.1.3.演示代码
1.Jsp
可以重新创建一个专门演示批量删除的画面【itemListDelBatch.jsp】,利用原来的itemList.jsp拷贝一个,然后在表格的最前面增加一列checkbox。
【itemListDelBatch.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"%>
<!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 }/delAll.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>
<td>操作</td>
</tr>
<c:forEach items="${itemList }" var="item">
<tr>
<td><input type="checkbox" name="ids" value="${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 }/toEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
2.Controller
【ItemsController.java】先定义一个方法用于itemListDelBatch.jsp页面的显示:
@RequestMapping("/listForDel")
public ModelAndView getListForDel() throws Exception {
List<Items> itemsList = itemsService.getItemsList();
ModelAndView modelAndView = new ModelAndView();
// request.setAttribute(key, value)
// 底层仍然是把属性名和属性值放到request对象中
// jsp页面永远是从request对象中取得数据的
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("items/itemListDelBatch");
return modelAndView;
} 然后再定义一个执行删除的方法(这里主要是学习如何传参数,不做具体的删除操作)
方式一:直接传递数组参数
·传参规范:页面上input框的name属性值必须等于接收时数组参数的变量名称。
/**
* 演示接收数组(直接接收数组)
*/
@RequestMapping("/delAll")
public String delAll(Integer[] ids) throws Exception {
// 批量删除:可以循环这个ids数组,逐条删除即可。
return "success";
} 方式二:在Vo中传递数组参数
【QueryVo.java】
package cn.baidu.pojo; import java.util.List; public class QueryVo { private Integer[] ids; // getter/setter方法。。。。。。
} ·传参规范:页面上input框的name属性值必须等于接收时Vo中数组类型属性的变量名称。
/**
* 演示接收数组(用Vo传递数组)
*/
@RequestMapping("/delAll")
public String delAll(QueryVo vo) throws Exception {
// 批量删除:可以循环这个Vo中的ids数组,逐条删除即可。
return "success";
} 2.1.4.传参规范
总结上面两种规范:Input框的name与Controller方法参数中的数组名要相同。(无论数组定义在方法形参中还是定义在形参Vo中)
2.2.List集合类型
可以利用List集合类型的参数传递多条数据进行批量处理。比如批量更新。
2.2.1.需求
批量更新:实现商品数据的批量修改。
2.2.2.需求分析
要想实现商品数据的批量修改,需要在商品列表中可以对商品信息进行修改,并且可以批量提交修改后的商品数据。提交的数据应该是一个List。
功能分解:
前端:1)列表改成input输入框;2)定义改好的input框的name属性;
后端:1)能接收到提交过来的更新数据;2)批量更新处理
2.2.3.演示代码
1.接收商品列表的pojo
注意:SpringMVC不能直接传递List集合类型的参数,必须包装在Vo中。这是SpringMVC框架的强制要求。
【QueryVo.java】
package cn.baidu.pojo; import java.util.List; public class QueryVo { private List<Items> updateItemsList; // setter/getter方法。。。。。。。 } 2.Jsp
可以重新创建一个专门演示批量更新的画面【itemListUpdBatch.jsp】,利用原来的itemList.jsp拷贝一个,然后将表格中的项目都改成input输入框,可以直接修改数据。
【itemListUpdBatch.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"%>
<!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 }/updateAll.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="${itemList }" var="item" varStatus="status"> <!-- status.index表示集合的下标,从0开始 -->
<tr>
<td><input type="text" name="updateItemsList[${status.index }].name" value="${item.name }" /></td>
<td><input type="text" name="updateItemsList[${status.index }].price" value="${item.price }" /></td>
<td><input type="text" name="updateItemsList[${status.index }].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>" /></td>
<td><input type="text" name="updateItemsList[${status.index }].detail" value="${item.detail }" /></td> <td><input type="hidden" name="updateItemsList[${status.index }].id" value="${item.id}" />
<a href="${pageContext.request.contextPath }/toEdit.action?id=${item.id}">修改</a>
</td>
</tr>
</c:forEach>
</table>
</form>
</body> </html>
附:
varStatus属性常用参数总结下:
${status.index} 输出行号,从0开始。
${status.count} 输出行号,从1开始。
${status.current} 当前这次迭代的(集合中的)项
${status.first} 判断当前项是否为集合中的第一项,返回值为true或false
${status.last} 判断当前项是否为集合中的最后一项,返回值为true或false
begin属性、end属性、step属性分别表示:起始序号,结束序号,跳跃步伐。 3.Controller
【ItemsController.java】先定义一个方法用于itemListDelBatch.jsp页面的显示:
@RequestMapping("/listForUpd")
public ModelAndView getListForUpd() throws Exception {
List<Items> itemsList = itemsService.getItemsList();
ModelAndView modelAndView = new ModelAndView();
// request.setAttribute(key, value)
// 底层仍然是把属性名和属性值放到request对象中
// jsp页面永远是从request对象中取得数据的
modelAndView.addObject("itemsList", itemsList);
modelAndView.setViewName("items/itemListUpdBatch");
return modelAndView;
} 再定义一个方法,用来更新处理。这里不做具体的更新,我们主要学习如何接收List参数。
/**
* 演示接收List
*/
@RequestMapping("/updateAll")
public String updateAll(QueryVo vo) throws Exception {
System.out.println(vo); // 批量修改:遍历List,逐个修改。
return "success";
} 2.2.4.传参规范
1.SpringMVC不能直接传递List集合类型的参数,必须包装在java bean中。这是SpringMVC框架的强制要求。
2.页面上input框的name属性值必须等于Controller方法形参java bean中List属性名 + [集合下标] + . + List泛型中的属性名。
例如:
<input type="text" name="itemsUpdLst[${status.index }].name" value="${item.name }" /> 3.@RequestMapping(重点)
注解@RequestMapping控制着url到请求方法的映射,对url能访问到Controller中正确的响应方法起到了至关重要的作用。
3.1.使用在方法上
标记url到请求方法的映射,即通过一段url找到Controller中对应的方法。这个在以前的示例中已经练习了。
3.2.使用在类上
官方的说法叫做窄化请求映射,其实就是为了防止你和你的同事起的url重名,在类上多给url加了一层目录。
【ItemsController.java】的修改:
@Controller
@RequestMapping("/items")
public class ItemsController {
。。。。。。
}
访问地址从【http://localhost:8080/ssm-1/list.action】变成了【http://localhost:8080/ssm-1/items/list.action】,多了一层【/items】目录。
注意:
此时SpringMVC.xml中的视图解析器的前缀的开头要加斜杠/WEB-INF/jsp,如果写成WEB-INF/jsp就会被SpringMVC认为是相对路径,直接拼在类上面@RequestMapping中url的后面。
3.3.限制请求类型
1.Http请求类型:post、get、put、delete等,不过put、delete现在已经很少使用了。
2.post与get:
必须明确指定是post时,才是post请求;否则默认是get请求。
在浏览器中输入url提交的请求是get请求。
3.@RequestMapping使用方式:
a)默认方式:之前使用@RequestMapping都是它的默认使用方式,默认的@RequestMapping支持所有的Http请求类型。
b)正常方式:@RequestMapping(value=”具体url路径”, method=某一种http请求类型)
指定了Http请求类型就限制只能用指定的请求类型提交请求。
c)多请求方式:@RequestMapping(value=”具体url路径”, method={请求类型1, 请求类型2,……})
4.示例:
◆限定只允许GET方法访问:
@RequestMapping(value=”/list”, method = RequestMethod.GET)
◆限定只允许POST方法访问:
@RequestMapping(value=”/list”, method = RequestMethod.POST)
◆GET和POST方法都可以:
@RequestMapping(value=”/list”, method = {RequestMethod.POST, RequestMethod.GET })

@RequestMapping(”/list”) 以商品列表画面的访问为例,是通过get方式访问的,因此可以在@RequestMapping的method属性中设置请求的类型是【RequestMethod.GET】:
@RequestMapping(value="/list", method=RequestMethod.GET)
public ModelAndView itemsList() throws Exception { List<Items> itemsList = itemsService.findItemsList(); // 1. 设置返回页面需要的数据 2. 指定返回页面的地址
ModelAndView modelAndView = new ModelAndView(); // 1. 设置返回页面需要的数据
modelAndView.addObject("itemList", itemsList); // 2. 逻辑视图名称的设置(就是视图文件的文件名)
modelAndView.setViewName("itemList"); return modelAndView;
}
尝试是否能访问成功。
然后把【RequestMethod.GET】改成【RequestMethod.POST】,再试一次,会报405错误:
HTTP Status 405 - Request method 'GET' not supported
这说明请求访问受限了。
同样如果用POST方法访问【RequestMethod.GET】修饰的URL也会报405错误:
HTTP Status 405 - Request method 'POST' not supported
3.4.用途
大家是不是有一个疑问,感觉这个功能多余,还不如不限制。是的,如果在传统web系统中这个限制功能使用的很少。但在RESTful的url中十分有用。
4.Controller方法的返回值(重点)
提到Controller方法的返回值主要指两方面内容:
1.怎样指定返回页面的路径?
2.怎样指定返回页面的数据?
4.1.ModelAndView模型和视图
可以调用里面的方法指定页面的地址;还可以调用里面的方法指定返回给页面的数据。
这个在第一天的内容中已经介绍过了。这里就不多说了。
4.2.字符串
4.2.1.返回普通的字符串
Controller方法如果返回的是普通字符串,那就是视图文件的逻辑视图名或者是视图文件的物理地址。这个在第一天的代码示例中已经介绍过了,这里不多说了。
对于处理好的数据可以借助于默认的参数Model将数据返回给页面。
4.2.2.请求转发与重定向
1.请求转发和重定向的特征(也是区别):
请求转发时浏览器中URL不发生改变,说明还是在同一个请求中,因此request对象是一个,request域中的数据可以带到转发后的方法中。
重定向时浏览器中的URL发生改变,说明是重新发起了一个请求,因此request对象不是一个,重定向前request域中的数据不能带到重定向后的方法中。
4.2.3.请求转发字符串
1.SpringMVC中请求转发的字符串特征:
返回的字符串中以【forward:】开头,后面跟转发的URL路径。
这个URL必须是Controller方法上@RequestMapping注解配置的URL。这样就可以转发到对应的方法中进行处理然后返回给页面。
2.对代码的改造:
比如:我们可以设计在商品的详细修改页面点击【保存】后,又重新回到详细页面。用请求转发的方式转发到商品详细页面的检索方法【itemEdit】中。
具体改造代码【ItemsController.java】:
/**
* 演示请求转发:
* 在Controller方法返回的字符串中以【forward:】开头为请求转发,后面跟转发的url路径
*/
@RequestMapping("/update")
public String updateItems(Items items, Model model) throws Exception {
itemsService.updateItems(items);
// 将转发后商品详细信息查询需要的主键id传递过去。
// 用model可以,因为在底层model仍然是把数据放到了request域中。
model.addAttribute("id", items.getId());
// 因为jsp是从request对象中接收参数,因此也可以直接用request对象直接传值。
// 也可以直接用request对象直接传。 // 请求转发
return "forward:toEdit.action";
} 因为请求转发前后的request对象是同一个,所以也可以直接用request对象直接传值:
/**
* 演示请求转发:
* 在Controller方法返回的字符串中以【forward:】开头为请求转发,后面跟转发的url路径
*/
@RequestMapping("/update")
public String updateItems(Items items, Model model, HttpServletRequest request) throws Exception {
itemsService.updateItems(items);
// 也可以直接用request对象直接传。
request.setAttribute("id", items.getId()); // 请求转发
return "forward:toEdit.action";
} 4.2.4.重定向字符串
1.重定向的字符串特征:
返回的字符串中以【redirect:】开头,后面跟重定向的URL路径。
这个URL必须是Controller方法上@RequestMapping注解配置的URL。这样就可以转发到对应的方法中进行处理然后返回给页面。
2.对代码的改造:
还是上面的例子我们也可以用重定向来做,但重定向前和后是两个独立的request域,因此传递主键id时不能使用request对象来传递,只能通过model对象完成,底层model会把数据赋给新的request域中。
具体代码【ItemsController.java】改造:
可以先试一试看看用request对象是不是真的传递不过去。
/**
* 演示重定向:
* 在Controller方法返回的字符串中以【redirect:】开头的为重定向,后面跟重定向的url路径
*/
@RequestMapping("/update")
public String updateItems(Items items, HttpServletRequest request, Model model) throws Exception {
itemsService.updateItems(items);
request.setAttribute("id", items.getId());
return "redirect:toEdit.action";
}
此处用request设置了id,然后可以debug到【itemEdit】方法中看id能否传过去,结果是id无法传过去。
使用model对象传值:
/**
* 演示重定向:
* 在Controller方法返回的字符串中以【redirect:】开头的为重定向,后面跟重定向的url路径
*/
@RequestMapping("/update")
public String updateItems(Items items, Model model) throws Exception {
itemsService.updateItems(items);
// 将重定向后商品信息详细查询需要的主键id传递过去。
model.addAttribute("id", items.getId());
return "redirect:toEdit.action";
}
此处用Model设置了id,然后可以debug到【itemEdit】方法中看id能否传过去,结果id被传递到了【itemEdit】方法中。
这就是为什么SpringMVC不推荐直接用request对象传值的原因,它自己定义了一个用于传值的对象Model,这样就不怕跨不同request对象的重定向传值问题了。
也有人说还可以用session传递,这个没错,是可以传的,但是session在实际工作中是不可以随便往里面放数据的,session需要有项目负责人统一规划可以往里面放的数据,比如用户登录信息。因此不可以使用session。
4.2.5.请求转发和重定向的路径写法为什么不以/开头
1.这就是url的相对路径和绝对路径的问题。
以【localhost:8080/ssm-1/items/toEdit.action】为例说明问题:
url相对路径:相对于当前目录下的路径,示例中的当前目录是/items,当对于它下的相对路径是/toEdit.action
url绝对路径:从项目名后开始的完整的url路径:/items/toEdit.action
2.SpringMVC怎么才能区分出相对路径还是绝对路径呢?
SpringMVC规定:在请求转发和重定向关键字后以斜杠/开头的url为绝对路径,不以斜杠/开头的是相对路径。
由此可知:
请求转发的相对路径:forward:toEdit.action
请求转发的绝对路径:forward:/items/toEdit.action
重定向的相对路径:redirect:toEdit.action
重定向的绝对路径:redirect:/items/toEdit.action
3.两种路径的使用范围:
url相对路径:
在Controller类上有@RequestMapping并且是在此Controller内部方法间跳转时可使用。
url绝对路径:
任何时候都可以使用,但是在跳转到其他Controller方法的时候必须用绝对路径。
如果实在记不住:就一律用绝对路径。
4.3.void
如果使用void为返回值,那么就需要使用原生的HttpServletRequest,HttpServletResponse等,这样就不走SpringMVC的视图解析器,这样就破坏了SpringMVC的体系结构,所以一般不要使用。这里只是提一下。
返回值为void一般在ajax的时候使用,用response.getWriter().write("。。。")返回数据
示例代码【ItemsController.java】
/**
* 演示void
*/
@RequestMapping("/update")
public void updateItems(Items items, HttpServletRequest request, HttpServletResponse response) throws Exception {
itemsService.updateItems(items);
request.setAttribute("id", items.getId());
request.getRequestDispatcher("/WEB-INF/jsp/editItem.jsp").forward(request, response);
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
}

SpringMVC框架之第三篇的更多相关文章

  1. Lucene&Solr框架之第三篇

    1.SolrCore的配置 a)schma.xml文件 b)配置中文分析器 2.配置业务域和批量索引导入 a)配置业务域 b)批量索引导入 c)Solrj复杂查询(用Query页面复杂查询.用程序实现 ...

  2. SpringMVC框架之第四篇

    5.SpringMVC异常处理 5.1.异常分类 1.可预知异常: Java编译时可检测异常,例如:IOException.SQLException等. 自定义异常(继承Exception父类的自定义 ...

  3. MyBatis框架之第三篇

    8.Spring与Mybatis整合 框架的整合就是软件之间的集成,它很抽象,因此在做整合之前先想好思路.规划好思路然后按照思路一步一步的做就可以实现框架的整合. 8.1.SM整合思路 8.1.1.思 ...

  4. Django(四)框架之第三篇模板语法

    https://www.cnblogs.com/yuanchenqi/articles/6083427.htm https://www.cnblogs.com/haiyan123/p/7725568. ...

  5. Django框架之第三篇模板语法(重要!!!)

    一.什么是模板? 只要是在html里面有模板语法就不是html文件了,这样的文件就叫做模板. 二.模板语法分类 一.模板语法之变量:语法为 {{ }}: 在 Django 模板中遍历复杂数据结构的关键 ...

  6. Java SpringMVC框架学习(三)springMVC的执行流程

    具体执行逻辑如下: 浏览器提交请求到中央调度器. 中央调度器将请求转给处理器映射器. 处理器映射器根据请求, 找到请求对应的处理器, 并将其封装为处理器执行链返回给中央调度器. 中央调度器根据处理器执 ...

  7. Django框架之第三篇模板语法

    一.什么是模板? 只要是在html里面有模板语法就不是html文件了,这样的文件就叫做模板. 二.模板语法分类 一.模板语法之变量:语法为 {{ }}: 在 Django 模板中遍历复杂数据结构的关键 ...

  8. Django框架之第三篇(路由层)--有名/无名分组、反向解析、路由分发、名称空间、伪静态

    一.Django请求生命周期 二.路由层  urls.py url()方法 第一个参数其实就是一个正则表达式,一旦前面的正则匹配到了内容,就不会再往下继续匹配,而是直接执行对应的视图函数. djang ...

  9. 开源DDD设计模式框架YMNNetCoreFrameWork第三篇-增加ASp.net core Identity身份认证,JWT身份认证

    1.框架增加Identity注册功能 2.框架增加identity登录以后获取JWTtoken 3.请求接口通过token请求,增加验证特性 源代码地址:https://github.com/topg ...

随机推荐

  1. 基于webpack实现多html页面开发框架六 提取公共代码

    一.解决什么问题 1.如果a.js和b.js都引用了common.js,那在打包的时候common.js会被重复打入到a.js和b.js,造成重复打包 2.单独打包common.js对性能有帮助,浏览 ...

  2. Numpy的基础用法

    1.用Numpy创建数组 numpy.array(object):创建数组,与array.array(typecode[, initializer])不同,array.array()只能创建一维数组 ...

  3. js之观察者模式和发布订阅模式区别

    观察者模式(Observer) 观察者模式指的是一个对象(Subject)维持一系列依赖于它的对象(Observer),当有关状态发生变更时 Subject 对象则通知一系列 Observer 对象进 ...

  4. 实现一个简单的散列表(HashMap)

    下面参考java.util.HashMap<K, V>,写了一个简单的散列表,只实现了其中的put和get方法,使用链接法"碰撞冲突".代码最后,自定义了一个Peopl ...

  5. 高质量iOS博客推荐

    https://www.jianshu.com/p/ea9fabdc12ed 原文地址 原作者记录了一些高质量ios博客地址,本文只做收藏使用.

  6. JavaScript基础5

    字符串操作方法和属性 length   获取字符串的长度 str.chartAt(指定字符的索引)  获取指定位置的字符 返回string类型的值 str.concat(字符串)   链接多个字符串  ...

  7. 从零开始openGL——三、模型加载及鼠标交互实现

    前言 在上篇文章中,介绍了基本图形的绘制.这篇博客中将介绍模型的加载.绘制以及鼠标交互的实现. 模型加载 模型存储 要实现模型的读取.绘制,我们首先需要知道模型是如何存储在文件中的. 通常模型是由网格 ...

  8. Ceph 架构以及原理分析

    一.架构 Ceph在一个统一的系统中独特地提供对象,块和文件存储. Ceph高度可靠,易于管理且免费. Ceph的强大功能可以改变您公司的IT基础架构以及管理大量数据的能力. Ceph提供了非凡的可扩 ...

  9. 2- 设置断点修改Request

    以下是借鉴别人的知识分享.我在这里转载,如有冒犯,还请告知. 如何设置断点修改Request呢? fiddler最强大的功能就是可以设置断点了.设置好之后,你可以修改HttpRequest的任何信息, ...

  10. 一次使用pip后的总结

    pip 常用命令及搭配操作 一 .当安装了多个版本python的时候,表示用pythonx 的pip 进行: 1.pythonx -m pip install + 包名 装 包 2.pythonx - ...