1. 程式人生 > >ssm資料校驗和資料回顯

ssm資料校驗和資料回顯

資料校驗

校驗的理解:

專案中,通常使用較多是前端的校驗,比如頁面中js校驗。對於安全要求較高點建議在服務端進行校驗。

服務端校驗:

  • 控制層conroller:校驗頁面請求的引數的合法性。在服務端控制層conroller校驗,不區分客戶端型別(瀏覽器、手機客戶端、遠端呼叫)
  • 業務層service(使用較多):主要校驗關鍵業務引數,僅限於service介面中使用的引數。
  • 持久層dao:一般是不校驗的。

springmvc校驗需求:springmvc使用hibernate的校驗框架validation(和hibernate沒有任何關係)。

校驗思路: 頁面提交請求的引數,請求到controller方法中,使用validation進行校驗。如果校驗出錯,將錯誤資訊展示到頁面。

此處做了兩種情況

  1. 檢驗單一controller:pojo封裝物件校驗
  2. 分組校驗多個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";
			
}