Springmvc参数绑定
1. 参数绑定
1.1 Spring参数绑定过程
- 从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到Controller方法的形参上
- springmvc中,接收页面提交的数据是通过方法形参来接收,而不是在Controller中定义成员变量
- 处理器适配器调用springmvc提供参数绑定组件将key/value数据转换成Controller方法的形参
- 参数绑定组件:在springmvc早期版本使用PropertyEditor(只能将字符串转成java对象),后期使用converter(进行任意类型的转换)
- Spring提供了很多converter(转换器),在特殊情况下需要自定义converter
1.2 默认支持的类型
- 直接在Controller方法形参上定义下面类型的对象,就可以使用这些对象,在参数绑定过程中,如果遇到下面类型直接进行绑定
- HttpServletRequest
- 通过request对象获取请求信息
- HttpServletResponse
- 通过response处理响应信息
- HttpSession
- 通过session对象得到session中存放的对象
- Model/ModelMap
- model是一个接口,modelMap是一个接口实现
- 作用:将model数据填充到request域
- HttpServletRequest
1.3 简单类型
- 通过@RequestParam对简单类型的参数进行绑定
- 如果不使用@RequestParam,要求request传入参数名称和Controller方法的形参名一致,方可绑定成功
- 如果使用此参数,则没有此要求
- 示例:
//将传入的名为id的参数绑定给state public String demo(@RequestParam("id")Integer state,HttpServletRequest request)
- @RequestParam其他属性
- request:设置必要参数
- 示例:
//将传入的名为id的参数绑定给state,并且这个参数是必须要的参数 public String demo(@RequestParam(value="id",request="true")Integer state,HttpServletRequest request)
- 示例:
- defaultValue:如果参数没有传递,则启用默认值
- 示例:
@RequestParam(value="id",required=false,defaultValue="0")
- 示例:
- request:设置必要参数
1.4 pojo绑定
- 页面中input的name和Controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo
1.5 自定义参数绑定
- 对于Controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定
- 将请求日期数据串转换成日期类型,要转换的日期类型和pojo中日期属性类型保持一致
配置方式
springmvc.xml中配置
<!-- mvc配置 --> <mvc:annotation-driven conversion-service="conversionService"/> <!-- 自定义参数绑定 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!-- 转换器 --> <property name="converters"> <list> <!-- 日期类型转换 --> <bean class="自定义转换器的类路径(CustomDateConverter)"/> </list> </property> </bean>
自定义转换器
//泛型:Converter<原类型,新类型> public class CustomDateConverter implements Converter<String,Date> { public Date convert(String source) { //实现将日期串转换成日期类型(格式是yyyy-MM-dd HH:mm:ss) SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //转换后直接返回 try { return simpleDateFormat.parse(source); } catch (ParseException e) { e.printStackTrace(); } //参数绑定失败返回null return null; } }
2. 包装类型pojo参数绑定
- 包装类型:即内部封装了pojo作为属性
2.1 需求
- 商品查询Controller方法中实现商品查询条件传入
2.2 实现方法
- 第一种方法:在形参中添加HTTPServletRequest request参数,通过request接收查询条件参数
- 第二种方法:在形参中让包装类型的pojo接收查询条件参数
- 页面传参特点:复杂,多样
- 如果将用户账号,商品编号,订单信息等放在简单pojo(属性是简单类型)中,pojo类属性比较多,比较乱,建议使用包装类型的pojo
2.3 页面参数和Controller方法形参定义
- 页面参数:
//包装类型传值,用属性中的 pojo.要传递的属性值
商品名称:<input name="itemsCustom.name" />
- Controller方法形参
public ModelAndView queryItems(HTTPServletRequest request,ItemsQueryVo itemsQueryvo)
//包装类写法
public class ItemsQueryVo{
//商品信息
private Items items;
//为了系统可扩展性,对原始生成的po进行扩展
private ItemsCustom itemsCustom;
}
3. 集合类型绑定
3.1 数组绑定
- 需求:商品批量删除,用户再页面选择多个商品,批量删除
- 关键点:选择(多选)的商品id,传到Controller方法的形参,方法形参使用数组接收页面请求的多个商品id
- 页面定义
//循环列表复选框 <input type="check" name="items_id" value="${item.id}"/>
- Controller方法定义
//批量删除商品 @RequestMapping(/deleteItems) public String deleteItems(Integer[] items_id)
3.2 list绑定
- 方式一:
- 需求:通常在需要批量提交数据时,将提交的数据绑定到list
中,比如:成绩录入(录入多门科成绩,批量提交) - 页面定义
<c:forEach value="itemsList" var="item" varStatus="status"> <!--itemsList:对应包装pojo中的list类型属性名 status.index:对应下标 .name:对应包装pojo中list类型的属性中的pojo的值--> <input name="itemsList[${status.index}].name" value="${items.name}" /> <input name="itemsList[${status.index}].price" value="${items.price}" /> </c:forEach>
- Controller方法定义
- 1.进入批量商品修改页面
- 2.批量修改商品提交
- 使用list接收页面提交的批量数据,通过包装pojo接收,在包装pojo中定义list
属性 - 包装类代码:
public class ItemsQueryVo{ //商品信息 private Items items; //批量商品信息 private List<ItemsCustom> itemsList; }
- Controller接收
public String editItemsAllSubmit(ItemsQueryVo itemsQueryVo)
- 使用list接收页面提交的批量数据,通过包装pojo接收,在包装pojo中定义list
- 需求:通常在需要批量提交数据时,将提交的数据绑定到list
方式二:
前台json格式
[{ "name":"kasi", "sex":"nan", "age":"23", "address":"dongbao" }, { "name":"carmen", "sex":"nv", "age":"23", "address":"voion" }]
- 后台接收
public String saveUser(@RequestBody List<UserVo> userVoList
3.3 map绑定
- 在包装类中定义Map对象,并添加get/set方法,action使用包装对象接收
- 包装类定义如下
public class QueryVo{ private Map<String,Object> itemInfo = new HashMap<String,Object>(); //get和set方法 }
- 页面定义如下
<!--itemInfo:包装类中Map属性名 `name`:map中的key--> <input type="text" name="itemInfo['name']" /> <input type="text" name="itemInfo['price']" />