ssm引數繫結(簡單,陣列,list,map)
什麼是引數繫結 ?
在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類定義成員變更接收!
圖源:《阿里雲》
在本次介紹中,以下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。
定義陣列有兩種方式(下文采用第二種)
- 在Controller方法定義形參, 不使用@RequestParam簡單繫結獲得ids
- 在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;
實現方式可以分為兩種(建議後者)
- 逐一刪除數組裡的商品資訊(不斷請求資料庫)
- 一次刪除數組裡的商品資訊,需要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方法中。
原理:
- 進入批量商品修改頁面(頁面樣式參考商品列表實現)
- 批量修改商品提交,使用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>
實現方式可以分為兩種(建議後者)
- 逐條提交批量修改商品資訊(不斷請求資料庫)
- 一次性提交批量修改商品資訊,需要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());
}