天天看點

SpringMVC和Mybatis(三)pojo參數綁定、服務端校驗、分組校驗、資料回顯

包裝類型pojo參數綁定

商品查詢controller方法中實作商品查詢條件傳入

第一種:在形參中添加HttpServletRequest request參數,通過request接收查詢條件參數。

第二種:在形參中添加包裝類型的pojo來接收查詢參數。

分析:頁面傳入參數複雜

是以使用包裝類型pojo

修改ItemsController.java

@Controller

@RequestMapping("/items")

public class ItemsController {

//注入service

@Autowired

private ItemsService itemsService;

//商品查詢清單

//一般建議将url和方法名寫成一樣,友善queryItems和url進行映射,一個方法對應一個url

@RequestMapping("/queryItems")

public ModelAndView queryItems(ItemsQueryVo itemsQueryVo)throws Exception{

//調用service查找資料庫,查詢商品,這裡先使用靜态模拟

List<ItemsCustom> itemsList = itemsService.findItemsList(itemsQueryVo);

修改頁面增加查詢的input

itemsList.jsp

<body>

  <form action="${pageContext.request.contextPath }/items/queryItems.action" 

method="post">

  查詢條件:

  <table width="100%" border=1>

  <tr>

  <td>

  商品名稱:<input name="itemsCustom.name" />

  </td>

  <td><input type="submit" value="查詢" /></td>

  </tr>

  </table>

在送出修改頁面,也要增加包裝類型的pojo,也就是說所有非簡單類型的pojo,都需要多重包裝,防止items

的name和user的name名稱一緻,無法傳遞參數。

ItemsCustomVo.java extends ItemsCustom.java

送出修改頁面由ItemsCustom 改成ItemsCustomVo

頁面使用ItemsCustom.name

集合類型綁定

批量删除、批量修改

數組綁定:批量删除

controller層:

重要:将頁面選擇(多選)的商品id,傳到controller方法的形參,方法形參使用數組接收頁面請求的多個

商品id。

修改itemsList.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"

contentType="text/html; charset=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">

<html>

  <head>

    <title>check list</title>

<meta http-equiv="pragma" content="no-cache">

<meta http-equiv="cache-control" content="no-cache">

<meta http-equiv="expires" content="0">    

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

<meta http-equiv="description" content="This is my page">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<!--

<link rel="stylesheet" type="text/css" href="styles.css" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >

-->

<script type="text/javascript">

function deleteItems(){

//送出form

document.itemsForm.action="${pageContext.request.contextPath 

}/items/deleteItems.action";

document.itemsForm.submit();

}

function queryItems(){

//送出form

document.itemsForm.action="${pageContext.request.contextPath 

}/items/queryItems.action";

document.itemsForm.submit();

}

</script>

  </head>

  <body>

  <form name="itemsForm" action="${pageContext.request.contextPath 

}/items/queryItems.action" method="post">

  查詢條件:

  <table width="100%" border=1>

  <tr>

  <td>

  商品名稱:<input name="itemsCustom.name" />

  </td>

  <td><input type="button" value="查詢" οnclick="queryItems()"/>

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

  </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="${itemsList }" var="item">

  <tr>

  <td><input type="checkbox" name="items_id" 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 }/items/editItems.action?id=

${item.id}" target="_blank" rel="external nofollow" >修改</a></td>

  </tr>

  </c:forEach>

  </table>

  </form>

  </body>

</html>

ItemsController.java

//批量删除

@RequestMapping("/deleteItems")

public String deleteItems(Model model,Integer[] items_id)throws Exception{

//service層的代碼

return "success";

}

list綁定

将送出的資料綁定到list<pojo>中,比如:批量修改。

controller層:

1.進入批量商品的頁面

2.批量修改商品送出

使用List來接收頁面的資料,通過包裝pojo接收。

ItemsQueryVo.java加set和get方法

public class ItemsQueryVo {

//商品資訊包裝進入

private Items items;

//為了系統可以擴充性,對商品資訊定義擴充類

private ItemsCustom itemsCustom;

//批量商品資訊

private List<ItemsCustom> itemsList;

ItemsController.java

//批量修改商品,将商品查詢,在頁面中批量編輯

//商品查詢清單

//一般建議将url和方法名寫成一樣,友善queryItems和url進行映射,一個方法對應一個

url

@RequestMapping("/editItemsQuery")

public ModelAndView editItemsQuery(ItemsQueryVo itemsQueryVo)throws Exception{

List<ItemsCustom> itemsList = itemsService.findItemsList(itemsQueryVo);

ModelAndView modelAndView = new ModelAndView();

modelAndView.addObject("itemsList",itemsList);

modelAndView.setViewName("items/editItemsQuery");

return modelAndView;

}

//批量修改商品送出

@RequestMapping("/editItemsAllSubmit")

public String editItemsAllSubmit(ItemsQueryVo itemsQueryVo)throws Exception{

//service層資料

return "success";

}

頁面editItemsQuery.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"

contentType="text/html; charset=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">

<html>

  <head>

    <title>check list</title>

<meta http-equiv="pragma" content="no-cache">

<meta http-equiv="cache-control" content="no-cache">

<meta http-equiv="expires" content="0">    

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

<meta http-equiv="description" content="This is my page">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<!--

<link rel="stylesheet" type="text/css" href="styles.css" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >

-->

<script type="text/javascript">

function editItemsAllSubmit(){

//送出form

document.itemsForm.action="${pageContext.request.contextPath 

}/items/editItemsAllSubmit.action";

document.itemsForm.submit();

}

function queryItems(){

//送出form

document.itemsForm.action="${pageContext.request.contextPath 

}/items/queryItems.action";

document.itemsForm.submit();

}

</script>

  </head>

  <body>

  <form name="itemsForm" action="${pageContext.request.contextPath 

}/items/queryItems.action" method="post">

  查詢條件:

  <table width="100%" border=1>

  <tr>

  <td>

  商品名稱:<input name="itemsCustom.name" />

  </td>

  <td><input type="button" value="查詢" οnclick="queryItems()"/>

  <input type="button" value="批量修改送出" οnclick="editItemsAllSubmit()"/>

  </td>

  </tr>

  </table>

  商品清單:

  <table width="100%" border=1>

  <tr>

  <td>商品名稱</td>

  <td>商品價格</td>

  <td>生産日期</td>

  <td>商品描述</td>

  <td>操作</td>

  </tr>

  <c:forEach items="${itemsList }" var="item" varStatus="status">

  <tr>

  <td><input name="itemsList[${status.index }].name" value="${item.name }" 

/></td>

  <td><input name="itemsList[${status.index }].price" value="${item.price }" 

/></td>

  <td><input name="itemsList[${status.index }].createtime" value="<fmt:formatDate 

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

  <td><input name="itemsList[${status.index }].detail" value="${item.detail }" 

/></td>

  </tr>

  </c:forEach>

  </table>

  </form>

  </body>

</html>

<td><input name="itemsList[${status.index }].name" value="${item.name }" /></td>

name對應包裝pojo中的list類型.屬性名  ${status.index }下标從0開始   value預設對應前台頁面查詢到

的name

Map綁定

在包裝類中定義Map對象,并添加get和set方法,action使用包裝對象接收。

包裝類中定義Map對象:

Public class QueryVo{

private Map<String, Object> itemInfo = new HashMap<String, Object>();

//get和set方法

}

頁面定義

<tr>

<td>資訊:</td>

<td>

姓名:<input type="text" name="itemInfo['name']" />

價格:<input type="text" name="itemInfo['price']" />

</td>

</tr>

controller:

public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{

//service 層

System.out.println(queryVo.getStudentinfo());

}

===============================================================================================

========

服務端校驗

項目中,最多的使用前端校驗。對于安全要求高,在服務端校驗。

控制層controller:校驗頁面請求的參數的合法性。對于手機、遠端調用等其他平台來說,統一校驗。

業務層service(主要):關鍵業務參數,僅限service接口的參數。

持久層dao:一般不校驗。

springmvc校驗使用hibernate的校驗架構validation

思路:頁面請求參數,請求到controller方法中,使用validation進行校驗。出錯,展示。

校驗商品名稱長度和生産日期非空

加入jar包

validation-api-1.0.0.GA.jar

jboss-logging-3.1.0.CR2.jar

hibernate-validator-4.3.0.Final.jar

配置校驗器

springmvc.xml

<!-- 校驗器 -->

<bean id="validator"

class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">

<!-- hibernate校驗器 -->

<property name="providerClass" value="org.hibernate.validator.HibernateValidator" />

<!-- 指定校驗使用資源檔案,如果不能确定則使用預設classpath下的

ValidationMessages.properties -->

<property name="validationMessageSource" ref="messageSource" />

</bean>

<!-- 校驗錯誤資訊配置檔案 -->

<bean id="messageSource"

class="org.springframework.context.support.ReloadableResourceBundleMessageSource">

<!-- 資源檔案 -->

<property name="basenames">

<list>

<value>classpath:CustomValidationMessages</value>

</list>

</property>

<!-- 資源檔案編碼格式 -->

<property name="fileEncodings" value="utf-8" />

<!-- 對資源檔案内容緩存時間,機關秒 -->

<property name="cacheSeconds" value="120" />

</bean>

</beans>

config建立CustomValidationMessages.properties

校驗器注入到處理器擴充卡

springmvc.xml

<mvc:annotation-driven conversion-service="conversionService" 

validator="validator" ></mvc:annotation-driven>

配置方式2

<!-- 自定義webBinder -->

<bean id="customBinder"

class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">

<property name="validator" ref="validator" />

</bean>

<!--注解擴充卡-->

<bean 

class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">

<property name="webBindingInitializer" ref="customerBinder">

</property>

</bean>

CustomValidationMessages.properties

#\u6DFB\u52A0\u6821\u9A8C\u9519\u8BEF\u63D0\u4EA4\u4FE1\u606F

items.name.length.error=\u8BF7\u8F93\u51651\u523030\u4E2A\u5B57\u7B26\u7684\u5546\u54C1\u540D

\u79F0

items.createtime.isNull.error=\u751F\u4EA7\u65E5\u671F\u4E0D\u80FD\u4E3A\u7A7A

在pojo添加校驗規則

import javax.validation.constraints.NotNull;

import javax.validation.constraints.Size;

Items.java

public class Items {

    private Integer id;

    //校驗名稱在1到10字元中間

    @Size(min=1,max=10,message="{items.name.length.error}")

    private String name;

    private Float price;

    private String pic;

    @NotNull(message="{items.createtime.isNull.error}")

    private Date createtime;

ItemsController.java

//商品資訊修改送出

//在要校驗的參數前面添加注解,在參數後面添加參數來接收校驗資訊,是配對出現(一前一後)

@RequestMapping("/editItemsSubmit")

public String editItemsSubmit(Model model,Integer id,

@Validated ItemsCustom itemsCustom,BindingResult bindingResult)throws 

Exception{

//擷取校驗資訊

if (bindingResult.hasErrors()) {

List<ObjectError> allErrors = bindingResult.getAllErrors();

for (ObjectError objectError : allErrors) {

System.out.println(objectError.getDefaultMessage());

}

model.addAttribute("allErrors", allErrors);

}

itemsService.updateItems(id, itemsCustom);

return "items/editItems";

// return "forward:queryItems.action";

}

editItems.jsp

<body>

  <!-- 顯示錯誤資訊 -->

  <c:if test="${allErrors!=null }">

  <c:forEach items="${allErrors }" var="error">

  ${error.defaultMessage }<br />

  </c:forEach>

  </c:if>

=============================================================================

分組校驗

定義多個校驗分組(java接口),分組中定義哪些規則

每個controller方法使用不同校驗分組。

在controller的包内再建立validation包再建立ValidGroup1.java

ValidGroup1.java

public interface ValidGroup1 {

//此分組校驗商品名稱長度

}

//不需要定義任何方法,對不同校驗規則進行分組

在po包内找到validation的class,并添加注釋内容group

Items.java

public class Items {

    private Integer id;

    //校驗名稱在1到30字元中間

    @Size(min=1,max=10,message="{items.name.length.error}",groups={ValidGroup1.class})

    private String name;

在商品修改送出的controller内同樣增加注釋内容value屬性

//商品資訊修改送出

//在要校驗的參數前面添加注解,在參數後面添加參數來接收校驗資訊,是配對出現(一前一後)

@RequestMapping("/editItemsSubmit")

public String editItemsSubmit(Model model,Integer id,

@Validated(value={ValidGroup1.class}) ItemsCustom 

itemsCustom,BindingResult bindingResult)throws Exception{

========================================================================================

資料回顯

pojo資料回顯,springmvc自動帶pojo資料回顯,pojo資料已經放到request域内,key等于pojo類型(首字母

小寫)

如果前台界面,沒有用pojo類型定義key,就隻能使用注解進行資料回顯。修改前台頁面的${itemsCustom.name}修改為${items.name},也就是沒有用pojo類型定義key

@ModelAttribute可以指定pojo回顯到頁面,在request中的key

//商品資訊修改送出

//在要校驗的參數前面添加注解,在參數後面添加參數來接收校驗資訊,是配對出現(一前一後)

@RequestMapping("/editItemsSubmit")

public String editItemsSubmit(Model model,Integer id,

@ModelAttribute("items")@Validated(value={ValidGroup1.class}) 

ItemsCustom itemsCustom,BindingResult bindingResult)throws Exception{

@ModelAttribute還可以将方法的傳回值傳到頁面

在商品查詢的清單頁面,通過商品類型查詢商品資訊。

在ItemsController.java

public class ItemsController {

//注入service

@Autowired

private ItemsService itemsService;

//商品的分類

@ModelAttribute("itemtypes")

public Map<String, String> getItemType(){

Map<String, String> itemTypes = new HashMap<String, String>();

itemTypes.put("101", "數位");

itemTypes.put("102", "母嬰");

return itemTypes;

}

數位和母嬰為靜态資料,應該從資料庫内查到。

itemsList.jsp

<td>

  商品名稱:<input name="itemsCustom.name" />

  商品類型:

  <select name="itemtypes">

  <c:forEach items="${itemtypes }" var="itemtype">

  <option value="${itemtype.key }">${itemtype.value }</option>

  </c:forEach>

  </select>

  </td>

  <td><input type="button" value="查詢" οnclick="queryItems()"/>

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

  </td>

使用簡單類型使用model進行回顯,可以不用@ModelAttribute

model.addAttribute("allErrors", allErrors);

model.addAttribute("itemsCustom", itemsCustom);

return "items/editItems";