ssm資料校驗和資料回顯
資料校驗
校驗的理解:
專案中,通常使用較多是前端的校驗,比如頁面中js校驗。對於安全要求較高點建議在服務端進行校驗。
服務端校驗:
- 控制層conroller:校驗頁面請求的引數的合法性。在服務端控制層conroller校驗,不區分客戶端型別(瀏覽器、手機客戶端、遠端呼叫)
- 業務層service(使用較多):主要校驗關鍵業務引數,僅限於service介面中使用的引數。
- 持久層dao:一般是不校驗的。
springmvc校驗需求:springmvc使用hibernate的校驗框架validation(和hibernate沒有任何關係)。
校驗思路: 頁面提交請求的引數,請求到controller方法中,使用validation進行校驗。如果校驗出錯,將錯誤資訊展示到頁面。
此處做了兩種情況
- 檢驗單一controller:pojo封裝物件校驗
- 分組校驗多個controller:pojo物件屬性校驗
單一校驗:pojo物件屬性校驗
需求
本專案介紹的具體需求: 商品修改,新增校驗(校驗商品名稱長度,生產日期的非空校驗),如果校驗出錯,在商品修改頁面顯示錯誤資訊。
環境準備
校驗的三個核心jar包
配置校驗器
<!-- 校驗器 --> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <!-- hibernate校驗器 --> <property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property> <!-- 指定校驗使用的資原始檔,在檔案中配置校驗錯誤資訊,如不指定,則預設classpath下的validationMessage.properties檔案 --> <property name="validationMessageSource" ref="messageSource"></property> </bean> <!-- 校驗錯誤資訊配置檔案 --> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <!-- 資原始檔名 --> <property name="basenames"> <list> <!-- 配置錯誤資訊檔案 CustomValidationMessages.properties--> <value>classpath:CustomValidationMessages</value> </list> </property> <!-- 解決中文亂碼 --> <property name="defaultEncoding" value="utf-8"></property> <!-- 資原始檔編碼格式 --> <property name="fileEncodings" value="utf-8"></property> <!-- 資原始檔快取時間 --> <property name="cacheSeconds" value="120"></property> </bean>
校驗器注入處理器介面卡中
<!-- 自動註冊DefaultAnnotationHandlerMapping與AnnotationMethodHandlerAdapte兩個bean,
是spring MVC為@Controllers分發請求所必須的 -->
<mvc:annotation-driven conversion-service="conversionService" validator="validator" />
在pojo中編寫錯誤規則
// 商品名稱在1-10個字元,message校驗資訊出錯提示 @Size(min=1,max=10,message="{items.items_name.length.error}") private String items_name; // 商品名稱 // 非空校驗 @NotNull(message="{items.items_price.isNull}") private Double items_price; // 商品價格
編寫錯誤資訊
這裡注意:很多情況下java properties file中預設編碼格式是:iso-8859-1,校驗資訊會出現亂碼情況,需要改為UTF-8才能識別中文註釋
解決:Eclipse-Window-Preferences-General-Content Types-Text-Java Properties File-UTF-8
#新增校驗錯誤提示資訊
items.items_name.length.error=請輸入1-10個字元的商品
items.items_price.isNull=請輸入商品價格!
捕獲校驗錯誤資訊
在需要校驗的pojo前邊新增@Validated,後邊新增BindingResult bindingResult接收校驗出錯資訊 注意:
- @Validated和BindingResult bindingResult是配對出現。
- 這裡採用的是pojo的封裝方式,所以需要@Valid來標識pojo的校驗
/**
*
* @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,
@Validated ItemsQueryVo itemsQueryVo, BindingResult bindingResult)
throws Exception {
// 返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
// 有校驗錯誤
if (bindingResult.hasErrors()) {
// 獲得腳亞目錯誤資訊
List<ObjectError> objectErrors = bindingResult.getAllErrors();
// 頁面提示錯誤資訊
// 新增錯誤資訊
modelAndView.addObject("objectErrors", objectErrors);
// 重新查詢所有商品資訊
List<ItemsCustomer> itemsList = itemsService.findItemsList(itemsQueryVo);
// 返回資料
modelAndView.addObject("itemsList", itemsList);
// 指定檢視
modelAndView.setViewName("items/editItemsQuery");
} else {
// 沒有校驗錯誤
// 呼叫itemsService介面方法
// 逐條提交批量修改商品資訊
itemsService.updateAllItems(itemsQueryVo.getItemsList());
// 一次性提交批量修改商品資訊,需要sql拼接
// itemsService.updateAllItemsSubmit(itemsQueryVo.getItemsList());
// 重新查詢所有商品資訊
List<ItemsCustomer> itemsList = itemsService.findItemsList(itemsQueryVo);
// 向頁面傳遞資料
modelAndView.addObject("itemsList", itemsList);
// 指定檢視
modelAndView.setViewName("items/itemsList");
}
// 返回檢視
return modelAndView;
}
在ItemsQueryVo.java商品資訊包裝類中標識校驗
// 接受list集合,批量商品資訊
@Valid
private List<ItemsCustomer> itemsList;
在頁面顯示校驗錯誤資訊
<c:if test="${objectErrors!=null }">
<c:forEach items="${objectErrors}" var="error">
${error.defaultMessage }
</c:forEach>
</c:if>
分組校驗:pojo封裝物件校驗
需求
在pojo中定義校驗規則,而pojo是被多個 controller所共用,當不同的controller方法對同一個pojo進行校驗,但是每個controller方法需要不同的校驗。
解決方法:
定義多個校驗分組(其實是一個java介面),分組中定義有哪些規則
每個controller方法使用不同的校驗分組
校驗分組
在cn.ssm.xhchen.validaGroups包下建立檢驗分組介面,介面不做任何方法,僅對校驗進行分組
商品名稱校驗介面
package cn.ssm.xhchen.validaGroups;
/**
*
* ClassName: ValidaGroup1
*
* @Description: 商品名稱校驗
* @author XHChen
* @date 2018年10月31日 下午9:16:56
*/
public interface ValidaGroupItemsName {}
商品價格校驗校驗介面
package cn.ssm.xhchen.validaGroups;
/**
*
* ClassName: ValidaGroupItems_Price
*
* @Description: 價格校驗
* @author XHChen
* @date 2018年10月31日 下午9:20:50
*/
public interface ValidaGroupItems_Price {}
新增校驗分組
// 商品名稱在1-10個字元,message校驗資訊出錯提示
@Size(min=1,max=10,message="{items.items_name.length.error}",groups=(ValidaGroupItemsName.class))
private String items_name; // 商品名稱
// 非空校驗
@NotNull(message="{items.items_price.isNull}",groups=(ValidaGroupItems_Price.class))
private Double items_price; // 商品價格
Controller指定使用分組
在需要校驗的pojo前邊新增@Validated,後邊新增BindingResult bindingResult接收校驗出錯資訊 注意:
- @Validated和BindingResult bindingResult是配對出現。
- @Validated(value=ValidaGroupItemsName.class)指定校驗分組
- 單一controller不需要@Valid來標識pojo的校驗
/**
*
* @Description: 修改商品資訊
* @param @param request 通過request物件獲取請求資訊
* @param @param id 商品資訊id
* @param @param itemsCustomer
* @param @return 返回商品列表
* @param @throws Exception
* @return ModelAndView
* @throws
* @author XHChen
* @date 2018年10月26日 上午10:18:14
*/
@RequestMapping("/editItemsSubmit.action")
public ModelAndView editItemsSubmit(HttpServletRequest request, Integer id,
@Validated(value=ValidaGroupItems_Price.class) ItemsCustomer itemsCustomer,BindingResult bindingResult,
ItemsQueryVo itemsQueryVo) throws Exception {
// 返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
// 獲得校驗錯誤資訊
if (bindingResult.hasErrors()) {
List<ObjectError> objectErrors = bindingResult.getAllErrors();
// 顯示錯誤資訊但頁面
modelAndView.addObject("objectErrors", objectErrors);
// 指定檢視
modelAndView.setViewName("items/editItems");
} else {
// 呼叫itemsService方法修改商品資訊,需要將頁面資料提交到此方法
itemsService.updateItems(id, itemsCustomer);
// 重新查詢商品資訊
List<ItemsCustomer> itemsList = itemsService.findItemsList(itemsQueryVo);
// 返回引數到頁面
modelAndView.addObject("itemsList", itemsList);
// 指定檢視
modelAndView.setViewName("items/itemsList");
}
// 返回指定檢視
return modelAndView;
}
資料回顯
什麼資料回顯: 提交後,如果出現錯誤,將剛才提交的資料回顯到剛才的提交頁面。
pojo資料回顯方法
- springmvc預設對pojo資料進行回顯。 pojo資料傳入controller方法後,springmvc自動將pojo資料放到request域,key等於pojo型別(首字母小寫) 使用@ModelAttribute指定pojo回顯到頁面在request中的key。
- @ModelAttribute還可以將方法的返回值傳到頁面 在商品查詢列表頁面,通過商品型別查詢商品資訊。 在controller中定義商品型別查詢方法,最終將商品型別傳到頁面。
// 商品分類
// @ModelAttribute最終講方法返回值放在value的key中
@ModelAttribute("itemTypes")
public Map<String, String> getItemTypes() {
Map<String, String> getItemTypes = new HashMap<String, String>();
getItemTypes.put("001", "電腦");
getItemTypes.put("002", "手機");
return getItemTypes;
}
頁面顯示itemtypes資料
<h3>商品型別</h3>
<select name="itemTypes">
<c:forEach items="${itemTypes }" var="itemTypes">
<option value="${itemTypes.key }">${itemTypes.value }</option>
</c:forEach>
</select>
- 使用最簡單方法使用model,可以不用@ModelAttribute。
// 獲得校驗錯誤資訊
if (bindingResult.hasErrors()) {
List<ObjectError> objectErrors = bindingResult.getAllErrors();
// 顯示錯誤資訊但頁面
model.addAttribute("objectErrors", objectErrors);
// 顯示錯誤資訊但頁面
model.addAttribute("items", itemsCustomer);
// 返回指定檢視
return "items/editItems";
}