springmvc使用JSR-303進(jìn)行數(shù)據(jù)校驗(yàn)實(shí)例
項(xiàng)目中,通常使用較多的是前端的校驗(yàn),比如頁(yè)面中js校驗(yàn)以及form表單使用bootstrap校驗(yàn)。然而對(duì)于安全要求較高點(diǎn)建議在服務(wù)端進(jìn)行校驗(yàn)。
服務(wù)端校驗(yàn):
- 控制層controller:校驗(yàn)頁(yè)面請(qǐng)求的參數(shù)的合法性。在服務(wù)端控制層controller校驗(yàn),不區(qū)分客戶端類型。
- 業(yè)務(wù)層service(使用較多):主要校驗(yàn)關(guān)鍵業(yè)務(wù)參數(shù),僅限于service接口中使用的參數(shù)。
- 持久層dao:一般是不校驗(yàn)的。
環(huán)境集成
1、添加jar包:
此處使用hibernate-validator實(shí)現(xiàn)(版本:hibernate-validator-4.3.0.Final-dist.zip),將如下jar包添加到classpath(WEB-INF/lib下即可):
- dist/lib/required/validation-api-1.0.0.GA.jar JSR-303規(guī)范API包
- dist/hibernate-validator-4.3.0.Final.jar Hibernate 參考實(shí)現(xiàn)
2、在spring配置總添加對(duì)JSR-303驗(yàn)證框架的支持
<!-- 校驗(yàn)錯(cuò)誤信息配置文件 --> <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" /> <!-- 對(duì)資源文件內(nèi)容緩存時(shí)間,單位秒 --> <property name="cacheSeconds" value="120" /> </bean>
<!-- 校驗(yàn)器 --> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <!-- hibernate校驗(yàn)器--> <property name="providerClass" value="org.hibernate.validator.HibernateValidator" /> <!-- 指定校驗(yàn)使用的資源文件,在文件中配置校驗(yàn)錯(cuò)誤信息,如果不指定則默認(rèn)使用classpath下的ValidationMessages.properties --> <property name="validationMessageSource" ref="messageSource" /> </bean>
自動(dòng)注冊(cè)validator
<mvc:annotation-driven conversion-service="conversionService" validator="validator"> </mvc:annotation-driven>
例子說(shuō)明
例子一:
import javax.validation.constraints.NotNull; public class UserModel { @NotNull(message="{username.not.empty}") private String username; }
通過(guò)@NotNull指定此username字段不允許為空,當(dāng)驗(yàn)證失敗時(shí)將從之前指定的messageSource中獲取“username.not.empty”對(duì)于的錯(cuò)誤信息,此處只有通過(guò)“{錯(cuò)誤消息鍵值}”格式指定的才能從messageSource獲取。
@Controller public class HelloWorldController { @RequestMapping("/validate/hello") public String validate(@Valid @ModelAttribute("user") UserModel user, Errors errors) { if(errors.hasErrors()) { return "validate/error"; } return "redirect:/success"; } }
通過(guò)在命令對(duì)象上注解@Valid來(lái)告訴Spring MVC此命令對(duì)象在綁定完畢后需要進(jìn)行JSR-303驗(yàn)證,如果驗(yàn)證失敗會(huì)將錯(cuò)誤信息添加到errors錯(cuò)誤對(duì)象中。
驗(yàn)證失敗后需要展示的頁(yè)面(/WEB-INF/jsp/error.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <form:form commandName="user"> <form:errors path="*" cssStyle="color:red"></form:errors><br/> </form:form>
在瀏覽器地址欄中輸入http://localhost:8080/validate/hello,即沒(méi)有username數(shù)據(jù),請(qǐng)求后將直接到驗(yàn)證失敗界面并顯示錯(cuò)誤消息“用戶名不能為空”,如果請(qǐng)求時(shí)帶上“?username=zhang”將重定向到成功頁(yè)面。
例子二:
public class Items { private Integer id; @Size(min=1,max=20,message="{items.name.length.error}") private String name; @NotNull(message="{items.createtime.isNULL}") private Date createtime; 省略set()和get()... }
public String editItemsSubmit(Model model, @Validated Items items, BindingResult bindingResult) throws Exception { if(bindingResult.hasErrors()){ List<ObjectError> allErrors = bindingResult.getAllErrors(); for(ObjectError objectError:allErrors) { System.out.println(objectError.getDefaultMessage()); } //可以直接使用model將提交pojo回顯到頁(yè)面 model.addAttribute("items",items); // 出錯(cuò)重新到商品修改頁(yè)面 return "items/editItems"; } return "success"; }
<table width="100%" border=1> <tr> <td>商品名稱</td> <td><form:input type="text" path="items.name" value="${items.name }"/></td><form:errors path="items.name"/> </tr> <tr> <td>商品生產(chǎn)日期</td> <td><input type="text" name="createtime" value="<fmt:formatDate value="${items.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td> </tr>
然后jsp頁(yè)面還是之前的頁(yè)面,并能顯示輸入不合法的并通過(guò)<form:errors path="items.name"/>顯示出來(lái),這樣明顯更加簡(jiǎn)單。
當(dāng)我們配置了messageSource Bean時(shí),默認(rèn)將為驗(yàn)證的對(duì)象自動(dòng)生成如下錯(cuò)誤消息鍵:
- 驗(yàn)證錯(cuò)誤注解簡(jiǎn)單類名.驗(yàn)證對(duì)象名.字段名
- 驗(yàn)證錯(cuò)誤注解簡(jiǎn)單類名.字段名
- 驗(yàn)證錯(cuò)誤注解簡(jiǎn)單類名.字段類型全限定類名
- 驗(yàn)證錯(cuò)誤注解簡(jiǎn)單類名
使用的優(yōu)先級(jí)是:從高到低,即最前邊的具有最高的優(yōu)先級(jí),而且以上所有默認(rèn)的錯(cuò)誤消息鍵優(yōu)先級(jí)高于自定義的錯(cuò)誤消息鍵。
如測(cè)試用例
public String pattern(@Valid @ModelAttribute(“model”) PatternModel model, Errors errors)
將自動(dòng)產(chǎn)生如下錯(cuò)誤消息鍵:
- Pattern.model.value=驗(yàn)證錯(cuò)誤注解簡(jiǎn)單類名.驗(yàn)證對(duì)象名.字段名
- Pattern.value=驗(yàn)證錯(cuò)誤注解簡(jiǎn)單類名.字段名
- Pattern.Java.lang.String=驗(yàn)證錯(cuò)誤注解簡(jiǎn)單類名.字段類型全限定類名
- Pattern=驗(yàn)證錯(cuò)誤注解簡(jiǎn)單類名
內(nèi)置的驗(yàn)證約束注解如下表所示(摘自hibernate validator reference):
驗(yàn)證注解 | 驗(yàn)證的數(shù)據(jù)類型 | 說(shuō)明 |
---|---|---|
@AssertFalse | Boolean,boolean | 驗(yàn)證注解的元素值是false |
@AssertTrue | Boolean,boolean | 驗(yàn)證注解的元素值是true |
@NotNull | 任意類型 | 驗(yàn)證注解的元素值不是null |
@Null | 任意類型 | 驗(yàn)證注解的元素值是null |
@Min(value=值) | BigDecimal,BigInteger, byte, short, int, long,等任何Number或CharSequence(存儲(chǔ)的是數(shù)字)子類型 | 驗(yàn)證注解的元素值大于等于@Min指定的value值 |
@Max(value=值) | 和@Min要求一樣 | 驗(yàn)證注解的元素值小于等于@Max指定的value值 |
@DecimalMin(value=值) | 和@Min要求一樣 | 驗(yàn)證注解的元素值大于等于@ DecimalMin指定的value值 |
@DecimalMax(value=值) | 和@Min要求一樣 | 驗(yàn)證注解的元素值小于等于@ DecimalMax指定的value值 |
@Digits(integer=整數(shù)位數(shù), fraction=小數(shù)位數(shù)) | 和@Min要求一樣 | 驗(yàn)證注解的元素值的整數(shù)位數(shù)和小數(shù)位數(shù)上限 |
@Size(min=下限, max=上限) | 字符串、Collection、Map、數(shù)組等 | 驗(yàn)證注解的元素值的在min和max(包含)指定區(qū)間之內(nèi),如字符長(zhǎng)度、集合大小 |
@Past | java.util.Date, java.util.Calendar; Joda Time類庫(kù)的日期類型 | 驗(yàn)證注解的元素值(日期類型)比當(dāng)前時(shí)間早 |
@Future | 與@Past要求一樣 | 驗(yàn)證注解的元素值(日期類型)比當(dāng)前時(shí)間晚 |
@NotBlank | CharSequence子類型 | 驗(yàn)證注解的元素值不為空(不為null、去除首位空格后長(zhǎng)度為0),不同于@NotEmpty,@NotBlank只應(yīng)用于字符串且在比較時(shí)會(huì)去除字符串的首位空格 |
@Length(min=下限, max=上限) | CharSequence子類型 | 驗(yàn)證注解的元素值長(zhǎng)度在min和max區(qū)間內(nèi) |
@NotEmpty | CharSequence子類型、Collection、Map、數(shù)組 | 驗(yàn)證注解的元素值不為null且不為空(字符串長(zhǎng)度不為0、集合大小不為0) |
@Range(min=最小值, max=最大值) | BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子類型和包裝類型 | 驗(yàn)證注解的元素值在最小值和最大值之間 |
@Email(regexp=正則表達(dá)式,flag=標(biāo)志的模式) | CharSequence子類型(如String) | 驗(yàn)證注解的元素值是Email,也可以通過(guò)regexp和flag指定自定義的email格式 |
@Pattern(regexp=正則表達(dá)式,flag=標(biāo)志的模式) | String,任何CharSequence的子類型 | 驗(yàn)證注解的元素值與指定的正則表達(dá)式匹配 |
@Valid | 任何非原子類型 | 指定遞歸驗(yàn)證關(guān)聯(lián)的對(duì)象;如用戶對(duì)象中有個(gè)地址對(duì)象屬性,如果想在驗(yàn)證用戶對(duì)象時(shí)一起驗(yàn)證地址對(duì)象的話,在地址對(duì)象上加@Valid注解即可級(jí)聯(lián)驗(yàn)證 |
此處只列出Hibernate Validator提供的大部分驗(yàn)證約束注解,請(qǐng)參考hibernate validator官方文檔了解其他驗(yàn)證約束注解和進(jìn)行自定義的驗(yàn)證約束注解定義。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot中登錄后關(guān)于cookie和session攔截問(wèn)題的案例分析
這篇文章主要介紹了Springboot中登錄后關(guān)于cookie和session攔截案例,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08新手場(chǎng)景Java線程相關(guān)問(wèn)題及解決方案
這篇文章主要介紹了新手場(chǎng)景Java線程相關(guān)問(wèn)題及解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07基于mybatis查詢結(jié)果映射不到對(duì)象的處理
這篇文章主要介紹了mybatis查詢結(jié)果映射不到對(duì)象的處理方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Mybatis-plus獲取雪花算法生成的ID并返回生成ID
本文主要介紹了Mybatis-plus獲取雪花算法生成的ID并返回生成ID,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-09-09Jpa 如何使用@EntityListeners 實(shí)現(xiàn)實(shí)體對(duì)象的自動(dòng)賦值
這篇文章主要介紹了Jpa 如何使用@EntityListeners 實(shí)現(xiàn)實(shí)體對(duì)象的自動(dòng)賦值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08MySQL數(shù)據(jù)文件直接通過(guò)拷貝備份與恢復(fù)的操作方法
這篇文章主要介紹了MySQL數(shù)據(jù)文件直接通過(guò)拷貝備份與恢復(fù)的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09MyEclipse2018中安裝Mybatis generator插件的實(shí)現(xiàn)步驟
這篇文章主要介紹了MyEclipse2018中安裝Mybatis generator插件的實(shí)現(xiàn)步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02