什么是参数绑定 ?

在Controller使用方法参数接收值,就是把web端的值给接收到Controller中处理,这个过程就叫做参数绑定。

 

springmvc所支持参数绑定

默认支持参数类型

Controller默认支持的参数类型有四个,足以满足开发需求

  • HttpServletRequest  通过request对象获取请求信息
  • HttpServletResponse  通过response处理响应信息
  • HttpSession  通过session对象得到session中存放的对象
  • Model/ ModelMap  将模型数据填充到request域 model是一个接口modelMap是一个接口实现

 

1.简单数据类型绑定,整型、字符串、日期...

·只要保证request请求的参数名和形参名称一致,自动绑定成功。

·如果request请求的参数名和形参名称不一致,可以使用@RequestParam(指定request请求的参数名),@RequestParam加在形参的前边。

2. 支持pojo类型绑定

只要保证request请求的参数名称和pojo中的属性名一致,自动将request请求的参数设置到pojo的属性中。(注意:形参中即有pojo类型又有简单类型,参数绑定互不影响。)

3. 集合类型绑定

通常在需要批量提交数据时,将提交的数据通过集合绑定完成数据提交

  • 数组绑定
  • list绑定
  • map绑定

4. 自定义参数绑定

例:日期类型绑定自定义:定义Converter<源类型,目标类型>接口实现类,比如:Converter<String,Date>表示:将请求的日期数据串转成java中的日期类型。(注意:要转换的目标类型一定和接收的pojo中的属性类型一致。将定义的Converter实现类注入到处理器适配器中。)

 

参数绑定过程

从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上。

springmvc中,接收页面提交的数据是通过方法形参来接收。而不是在controller类定义成员变更接收!

ssm参数绑定(简单,数组,list,map)

图源:《阿里云》

 

在本次介绍中,以下4种绑定方法统一运用默认使用支持参数HttpServletRequest类型绑定。直接在controller方法形参上定义下边类型的对象,就可以使用这些对象。其他默认参数绑定类型与其类似。

 

简单数据类型绑定

通过@RequestParam对简单类型的参数进行绑定。

1.不使用@RequestParam,要求request传入参数名称和controller方法的形参名称一致,方可绑定成功。

2.使用@RequestParam,不用限制request传入参数名称和controller方法的形参名称一致。

  • 指定request返回参数名称与controller形参名称绑定
  • required,指定参数必须传入
  • defaultValue,指定默认参数

itemsList.jsp

<td><a href="${PageContext.request.ContextPath }/items/editItems.action?id=${item.id}">修改</a></td>

Controller

        /**
	 * 
	 * @Description: 商品信息修改页面
	 * @param @param request 通过request对象获取请求信息
	 * @param @param id 商品信息id
	 * @param @return 返回修改页面
	 * @param @throws Exception
	 * @return ModelAndView
	 * @throws
	 * @author XHChen
	 * @date 2018年10月26日 上午10:16:06
	 */
	// 1.Integer id,要求request返回参数名称与controller形参名称一致
	// [email protected]对简单类型的参数进行绑定
	// 	[email protected],指定request返回参数名称与controller形参名称绑定
	// 	b.required,指定参数必须传入
	// 	c.defaultValue,id默认参数
	@RequestMapping("/editItems.action")
	public ModelAndView editItems(
			HttpServletRequest request,
			@RequestParam(value = "id", required = true, defaultValue = "id") Integer id)
			throws Exception {

		// 调用itemsService接口,查询商品信息
		ItemsCustomer itemsCustomer = itemsService.findItemsById(id);

		// 创建ModelAndView
		ModelAndView modelAndView = new ModelAndView();

		// 返回数据到页面
		modelAndView.addObject("itemsCustomer", itemsCustomer);

		// 指定视图
		// 路径前缀和后缀已由springmvc.xml配置
		modelAndView.setViewName("items/editItems");

		// 返回指定视图
		return modelAndView;

	}

ItemsService.java

        /**
	 * 
	 * @Description: 找到修改商品信息
	 * @param @param id 查询商品的id
	 * @param @return
	 * @param @throws Exception
	 * @return ItemsCustomer
	 * @throws
	 * @author XHChen
	 * @date 2018年10月20日 下午8:23:06
	 */
	public ItemsCustomer findItemsById(Integer id) throws Exception;

ItemsServiceImpl.java

        @Override
	/**
	 * 根据id查询商品信息
	 */
	public ItemsCustomer findItemsById(Integer id) throws Exception {
		
		// 根据id查询商品信息
		Items items = itemsMapper.findItemsById(id);
		
		// 创建ItemsCustomer对象
		ItemsCustomer itemsCustomer = new ItemsCustomer();
		
		// 把商品信息items复制到itemsCustomer
		BeanUtils.copyProperties(items, itemsCustomer);
		
		// 返回拓展类ItemsCustomer
		return itemsCustomer;
	}

itemsMapper.java

// 通过id查询
public Items findItemsById(int id) throws Exception;

itemsMapper.xml

<!-- 通过id查询 -->
<select id="findItemsById" parameterType="java.lang.Integer" resultType="cn.ssm.xhchen.po.Items">
	<!-- 插入查询语句 -->
	select * from items where id=#{id}
</select>

自定义参数绑定

对于controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定。

将请求日期数据串传成日期类型,要转换的日期类型和pojo中日期属性的类型保持一致(下文的Converter<String, Date>接口)。

pojo对象

private Date items_creattime; // 商品生产时间

itemsList.jsp

<td><fmt:formatDate value="${item.items_creattime }" pattern="yyyy:MM:dd HH:mm:ss"/></td>

自定义日期类型绑定

在cn.ssm.xhchen.controller.converter下创建CustomerDateConverter.java并实现Converter<String, Date>接口

package cn.ssm.xhchen.controller.converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.core.convert.converter.Converter;

/**
 * 
 * ClassName: CustomerDateConverter
 * 
 * @Description: 日期转换器
 * @author XHChen
 * @date 2018年10月21日 上午11:56:35
 */
public class CustomerDateConverter implements Converter<String, Date> {

	@Override
	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();
		}

		return null;
	}

}

配置方式

自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapte两个bean

<!-- 自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapte两个bean, 
	是spring MVC为@Controllers分发请求所必须的 -->
<mvc:annotation-driven conversion-service="conversionService" />

<!-- 自定义参数绑定 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
	<!-- 转换器 -->
	<property name="converters">
		<list>
		    <!-- 日期类型转换 -->
		    <bean class="cn.ssm.xhchen.controller.converter.CustomerDateConverter" />
		</list>
	</property>
</bean>

pojo类型绑定

页面中input的name和controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo。

controller的pojo形参的定义

// 系统拓展性,对原始po进行拓展
private ItemsCustomer itemsCustomer;

itemsList.jsp

<td><input type="text" name="itemsCustomer.items_name"></td>
<td><input type="button" value="搜索商品" onclick="queryItems()"></td>
function queryItems() {
   document.itemsForm.action="${PageContext.request.ContextPath }/items/queryItems.action";
   document.itemsForm.submit();
}

Controller

        /**
	 * 
	 * @Description: 查询商品信息,pojo绑定
	 * @param @param itemsQueryVo pojo绑定
	 * @param @return 返回商品列表
	 * @param @throws Exception
	 * @return ModelAndView
	 * @throws
	 * @author XHChen
	 * @date 2018年10月26日 上午10:23:36
	 */
	@RequestMapping("/queryItems.action")
	public ModelAndView queryItems(HttpServletRequest request, ItemsQueryVo itemsQueryVo)
			throws Exception {

		// 调用service方法查询数据库
		List<ItemsCustomer> itemsList = itemsService.findItemsList(itemsQueryVo);

		// 遍历结果
		for (ItemsCustomer itemsCustomer2 : itemsList) {
			System.out.println(itemsCustomer2);
		}
		System.out.println(itemsList.size());

		// 返回ModelAndView
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.addObject("itemsList", itemsList);

		// 指定视图
		// 路径前缀和后缀已由springmvc.xml配置
		modelAndView.setViewName("items/itemsList");

		return modelAndView;

	}

ItemsService.java

        /**
	 * 
	 * @Description: 商品列表查询
	 * @param @param itemsQueryVo 封装商品信息的类
	 * @param @return
	 * @param @throws Exception
	 * @return List<ItemsCustomer> 数据库返回的值映射到ItemsCustomer
	 * @throws
	 * @author XHChen
	 * @date 2018年10月20日 下午8:23:28
	 */
	public List<ItemsCustomer> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception;

ItemsServiceImpl.java

        @Override
	/**
	 * 通过itemsQueryVo查询商品信息
	 */
	public List<ItemsCustomer> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception {

		// 通过ItemsMapperCustomer查询数据库
		return itemsMapperCustomer.findItemsList(itemsQueryVo);
	}

ItemsMapperCustomer.java

// 商品列表查询 
public List<ItemsCustomer> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception;

ItemsMapperCustomer.xml

        <!-- ItemsMapper的拓展mapper -->
        <mapper namespace="cn.ssm.xhchen.mapper.ItemsMapperCustomer">

	<!-- sql片段 -->
	<sql id="where_query_Items">
		<!-- 使用动态sql,满足条件进行sql拼接 -->
		<!-- 商品信息通过 ItemsQueryVo包装类中的ItemsCustomer传递 -->
		<if test="itemsCustomer != null">
			<if test="itemsCustomer.items_name != null and itemsCustomer.items_name != ''">
				items_name like '%${itemsCustomer.items_name}%';
			</if>
		</if>
	</sql>
	
	
	<!-- 商品列表查询 
		parameterType:商品信息包装类 
		resultType:商品信息po拓展类 
		-->
	<select id="findItemsList" parameterType="cn.ssm.xhchen.po.ItemsQueryVo" resultType="cn.ssm.xhchen.po.ItemsCustomer">
		select * from items
		<where>
			<include refid="where_query_Items"></include>
		</where>
	</select>

集合类型绑定

数组绑定

需求:商品批量删除,用户在页面选择多个商品,批量删除。

原理:

将页面选择(多选)的商品id,传到controller方法的形参,方法形参使用数组接收页面请求的多个商品id。

定义数组有两种方式(下文采用第二种)

  1. 在Controller方法定义形参, 不使用@RequestParam简单绑定获得ids
  2. 在ItemsQueryVo定义数组属性,通过get获得ids

itemsList.jsp

checkbox

<td><input type="checkbox" name="items_ids" value="${item.id }"></td>

input

<td><input type="button" value="批量删除" onclick="deleteItems()"></td>

javascript

function deleteItems() {
  document.itemsForm.action="${PageContext.request.ContextPath }/items/deleteItems.action";
  document.itemsForm.submit();
}

ItemsQueryVo.java

// 接收数组,属性名要和页面name保持一致
private Integer[] items_ids;

实现方式可以分为两种(建议后者)

  1.  逐一删除数组里的商品信息(不断请求数据库)
  2.  一次删除数组里的商品信息,需要sql拼接

Controller.java

        /**
	 * 
	 * @Description: 批量删除商品
	 * @param @param items_id 与页面checkbox的名称保持一致
	 * @param @return 返回商品列表
	 * @return String
	 * @throws Exception
	 * @throws
	 * @author XHChen
	 * @date 2018年10月26日 上午9:57:26
	 */
	@RequestMapping("/deleteItems.action")
	public ModelAndView deleteItems(HttpServletRequest requests, ItemsQueryVo itemsQueryVo) throws Exception {

		// 调用itemsService方法
		// 逐一删除商品信息
		// itemsService.deleteItemsArray(itemsQueryVo.getItems_ids());
		
		// 一次删除商品信息,需要sql拼接
		itemsService.deleteItemsArrayAllIn(itemsQueryVo.getItems_ids());

		// 重新查询商品信息
		List<ItemsCustomer> itemsList = itemsService.findItemsList(itemsQueryVo);

		// 返回ModelAndView
		ModelAndView modelAndView = new ModelAndView();

		// 返回参数到页面
		modelAndView.addObject("itemsList", itemsList);

		// 指定视图
		modelAndView.setViewName("items/itemsList");

		// 返回指定视图
		return modelAndView;
	}

itemsService.java

        /**
	 * 
	 * @Description: 逐次删除数组商品信息
	 * @param @param items_id 商品id
	 * @return void
	 * @throws
	 * @author XHChen
	 * @date 2018年10月26日 上午11:22:56
	 */
	public void deleteItemsArray(Integer[] items_id) throws Exception;
	
	/**
	 * 
	 * @Description: 一次性删除商品信息
	 * @param @param items_ids
	 * @param @throws Exception   
	 * @return void  
	 * @throws
	 * @author XHChen
	 * @date 2018年10月27日 上午11:33:32
	 */
	public void deleteItemsArrayAllIn(Integer[] items_ids) throws Exception;

ItemsServiceImpl.java

        @Override
	/**
	 * 单个删除数组商品信息
	 */
	public void deleteItemsArray(Integer[] items_ids) throws Exception {
		
		// 每次传一个id值删除
		try {
			for (Integer id : items_ids) {
				// 调用itemsMapper接口方法
				itemsMapper.deleteItems(id);
			}
		} catch (Exception e) {
			// 输出错误日志
			System.out.println(e.getMessage());
		}
	}

	
	@Override
	/**
	 * 一次性删除商品信息
	 */
	public void deleteItemsArrayAllIn(Integer[] items_ids) throws Exception {
		
		// 调用itemsMapperCustomer接口方法
		itemsMapperCustomer.deleteItemsArrayAllIn(items_ids);
	}

ItemsMapper.xml

<!-- 删除数据 -->
<delete id="deleteItems" parameterType="cn.ssm.xhchen.po.Items">
    <!-- 插入删除语句 -->
    delete from items where id=#{id}
</delete>

ItemsMapper.java

// 删除
public void deleteItems(int id) throws Exception;

ItemsMapperCustomer.xml

       <!-- 批量删除数组商品信息 
		collection: 传入单参数的参数类型
		index: 每次迭代到的位置
		item: 每一个元素进行迭代时的别名
		open: 以什么开始
		separator: 每次进行迭代之间以什么符号作为分隔 符
		close: 以什么结束
	-->
	<delete id="deleteItemsArrayAllIn" parameterType="java.util.List">
		delete from items where id in
		<foreach collection="list" index="index" item="items_id" open="(" separator="," close=")">
			#{items_id}
		</foreach>
	</delete>

ItemsMapperCustomer.java

// 一次性删除商品信息
public void deleteItemsArrayAllIn(Integer[] items_ids) throws Exception;

List绑定

需求:批量商品修改,在页面输入多个商品信息,将多个商品信息提交到controller方法中。

原理:

  1. 进入批量商品修改页面(页面样式参考商品列表实现)
  2. 批量修改商品提交,使用List接收页面提交的批量数据,通过包装pojo接收,在包装pojo中定义list<pojo>属性, 并添加get/set方法

Pojo定义

// 接受list集合,批量商品信息
private List<ItemsCustomer> itemsList;

editItemsQuery.jsp

<c:forEach items="${itemsList}" var="item" varStatus="status">
<tr>
    <td>
	<input type="text"  name="itemsList[${status.index }].items_name" value="${item.items_name }">
    </td>
    <td>
        <input type="text" name="itemsList[${status.index }].items_price" value="${item.items_price }">
    </td>
    <td>
        <input type="text" name="itemsList[${status.index }].items_creattime" value="<fmt:formatDate value="${item.items_creattime }" pattern="yyyy:MM:dd HH:mm:ss"/>">
    </td>
    <td>
	<input type="text" name="itemsList[${status.index }].items_detail" value="${item.items_detail }">
    </td>
</tr>
</c:forEach>

实现方式可以分为两种(建议后者)

  1.  逐条提交批量修改商品信息(不断请求数据库)
  2.  一次性提交批量修改商品信息,需要sql拼接

Controller

        /**
	 * 
	 * @Description: 批量修改商品信息页面 ,list绑定
	 * @param @param request 通过request对象获取请求信息
	 * @param @param itemsQueryVo pojo绑定
	 * @param @return 返回批量修改商品信息页面
	 * @param @throws Exception   
	 * @return ModelAndView  
	 * @throws
	 * @author XHChen
	 * @date 2018年10月26日 下午9:14:40
	 */
	@RequestMapping("/editItemsQuery.action")
	public ModelAndView editItemsQuery(HttpServletRequest request, ItemsQueryVo itemsQueryVo)
			throws Exception {
		
		// 查询所有商品信息
		List<ItemsCustomer> itemsList = itemsService.findItemsList(itemsQueryVo);
		
		// 返回ModelAndView
		ModelAndView modelAndView = new ModelAndView();
		
		// 向页面传递数据
		modelAndView.addObject("itemsList", itemsList);
		
		// 指定视图
		modelAndView.setViewName("items/editItemsQuery");
		
		// 返回指定视图
		return modelAndView;
		
	}
	

	/**
	 * 
	 * @Description: 提交批量修改商品信息
	 * 绑定原理:通过ItemsQueryVo批量提交商品信息,将商品信息存储在ItemsQueryVo的itemsList属性中
	 * @param @param request 通过request对象获取请求信息
	 * @param @param itemsQueryVo pojo绑定
	 * @param @return 返回商品信息页面
	 * @param @throws Exception   
	 * @return ModelAndView  
	 * @throws
	 * @author XHChen
	 * @date 2018年10月26日 下午9:30:23
	 */
	@RequestMapping("/editItemsAllSubmit.action")
	public ModelAndView editItemsAllSubmit(HttpServletRequest request, ItemsQueryVo itemsQueryVo) 
			throws Exception {
		
		// 调用itemsService接口方法
		// 逐条提交批量修改商品信息
		// itemsService.updateAllItems(itemsQueryVo.getItemsList());
		
		// 一次性提交批量修改商品信息,需要sql拼接
		itemsService.updateAllItemsSubmit(itemsQueryVo.getItemsList());
		
		// 重新查询所有商品信息
		List<ItemsCustomer> itemsList = itemsService.findItemsList(itemsQueryVo);
		
		// 返回ModelAndView
		ModelAndView modelAndView = new ModelAndView();
		
		// 向页面传递数据
		modelAndView.addObject("itemsList", itemsList);
		
		// 指定视图
		modelAndView.setViewName("items/itemsList");
		
		// 返回指定视图
		return modelAndView;
	}

itemsService.java

        /**
	 * 
	 * @Description:逐次提交批量修改商品信息
	 * @param @param itemsList   
	 * @return void  
	 * @throws
	 * @author XHChen
	 * @date 2018年10月27日 上午10:16:57
	 */
	public void updateAllItems(List<ItemsCustomer> itemsList) throws Exception;

	/**
	 * 
	 * @Description: 一次性提交批量修改商品信息
	 * @param @param itemsList   
	 * @return void  
	 * @throws
	 * @author XHChen
	 * @date 2018年10月27日 上午10:47:18
	 */
	public void updateAllItemsSubmit(List<ItemsCustomer> itemsList) throws Exception;

ItemsServiceImpl.java

        @Override
	/**
	 * 逐条提交批量修改商品信息
	 */
	public void updateAllItems(List<ItemsCustomer> itemsList) throws Exception {
		
		try {
			for (ItemsCustomer itemsCustomer : itemsList) {
				// 调用itemsMapper接口方法
				itemsMapper.updateItems(itemsCustomer);
			}
		} catch (Exception e) {
			// 输出错误日志
			System.out.println(e.getMessage());
		}
	}

	
	@Override
	/**
	 * 一次性提交批量修改商品信息
	 */
	public void updateAllItemsSubmit(List<ItemsCustomer> itemsList) throws Exception {
		
		// 调用itemsMapperCustomer接口方法
		itemsMapperCustomer.updateAllItemsSubmit(itemsList);
	}

ItemsMapper.xml

<!-- 修改数据 -->
<update id="updateItems" parameterType="cn.ssm.xhchen.po.Items">
	<!-- 插入修改sql语句 -->
	update items set items_name=#{items_name}, items_detail=#{items_detail}, items_price=#{items_price} where id=#{id}
</update>

ItemsMapper.java

// 修改
public void updateItems(Items items) throws Exception;

ItemsMapperCustomer.xml

        <!-- 提交批量修改商品信息
		collection: 传入单参数的参数类型
		index: 每次迭代到的位置
		item: 每一个元素进行迭代时的别名
		open: 以什么开始
		separator: 每次进行迭代之间以什么符号作为分隔 符
		close: 以什么结束
	 -->
	<update id="updateAllItemsSubmit" parameterType="java.util.List">
		update items set status = 
			<foreach collection="list" index="index" item="itemsList" open="case ID" separator=" " close="end">
				when #{itemsList.id} then #{itemsList.status}
			</foreach>
		where id in
			<foreach collection="list" index="index" item="itemsList" open="(" separator="," close=")">
				#{itemsList.id,jdbcType=INT}
			</foreach>
	</update>

以上mybatis相当于如下mysql的批量更新

UPDATE xianyu2.Items 
SET items_name = CASE id 
      WHEN 2 THEN '小米8'
      WHEN 3 THEN '苹果10' 
      END, 
items_price = CASE id 
      WHEN 2 THEN 3499.79
      WHEN 3 THEN 5099.69
      END
WHERE id IN (2,3)

ItemsMapperCustomer.java

// 一次性提交批量修改商品信息
public void updateAllItemsSubmit(List<ItemsCustomer> itemsList) throws Exception;

Map绑定(不做详细介绍,与list绑定类似)

也通过在包装pojo中定义map类型属性。

原理:在包装类中定义Map对象,并添加get/set方法,action使用包装对象接收。

包装类中定义Map对象

Public class ItemsQueryVo {
private Map<String, Object> itemInfo = new HashMap<String, Object>();
  //get/set方法..
}

页面定义

<tr>
<td>学生信息:</td>
<td>
姓名:<inputtype="text"name="itemInfo['name']"/>
年龄:<inputtype="text"name="itemInfo['price']"/>
.. .. ..
</td>
</tr>

Controller

public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getStudentinfo());
}

 

相关文章:

  • 2022-12-23
  • 2021-06-15
  • 2022-12-23
  • 2022-12-23
  • 2021-08-02
  • 2021-12-16
猜你喜欢
  • 2022-12-23
  • 2021-12-02
  • 2021-05-29
  • 2021-11-23
  • 2022-12-23
  • 2021-06-30
  • 2021-11-17
相关资源
相似解决方案