Spring mvc服務(wù)端數(shù)據(jù)校驗實現(xiàn)流程詳解
B/S 系統(tǒng)中對http 請求數(shù)據(jù)的校驗多數(shù)在客戶端進行,這也是出于簡單及用戶體驗性上考慮,但是在一些安全性要求高的系統(tǒng)中服務(wù)端校驗是不可缺少的,實際上,幾乎所有的系統(tǒng),凡是涉及到數(shù)據(jù)校驗,都需要在服務(wù)端進行二次校驗。為什么要在服務(wù)端進行二次校驗?zāi)兀窟@需要理解客戶端校驗和服務(wù)端校驗各自的目的。
客戶端校驗,我們主要是為了提高用戶體驗,例如用戶輸入一個郵箱地址,要校驗這個郵箱地址是否合法,沒有必要發(fā)送到服務(wù)端進行校驗,直接在前端用 js 進行校驗即可。但是大家需要明白的是,前端校驗無法代替后端校驗,前端校驗可以有效的提高用戶體驗,但是無法確保數(shù)據(jù)完整性,因為在 B/S 架構(gòu)中,用戶可以方便的拿到請求地址,然后直接發(fā)送請求,傳遞非法參數(shù)。
服務(wù)端校驗,雖然用戶體驗不好,但是可以有效的保證數(shù)據(jù)安全與完整性。
綜上,實際項目中,兩個一起用。
Spring 支持JSR-303 驗證框架,JSR-303 是 JAVA EE 6 中的一項子規(guī)范,叫做 Bean Validation,官方參考實現(xiàn)是 Hibernate Validator(與Hibernate ORM 沒有關(guān)系),JSR-303 用于對 Java Bean 中的字段的值進行驗證。
普通校驗
普通校驗,是這里最基本的用法。
首先,我們需要加入校驗需要的依賴:
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.0.Final</version> </dependency>
接下來,在 SpringMVC 的配置文件中配置校驗的 Bean:
<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" id="validatorFactoryBean"> <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/> </bean> <mvc:annotation-driven validator="validatorFactoryBean"/>
配置時,提供一個 LocalValidatorFactoryBean 的實例,然后 Bean 的校驗使用 HibernateValidator。
這樣,配置就算完成了。
接下來,我們提供一個添加學(xué)生的頁面:
<form action="/addstudent" method="post">
<table>
<tr>
<td>學(xué)生編號:</td>
<td><input type="text" name="id"></td>
</tr>
<tr>
<td>學(xué)生姓名:</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>學(xué)生郵箱:</td>
<td><input type="text" name="email"></td>
</tr>
<tr>
<td>學(xué)生年齡:</td>
<td><input type="text" name="age"></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="提交">
</td>
</tr>
</table>
</form>
在這里需要提交的數(shù)據(jù)中,假設(shè)學(xué)生編號不能為空,學(xué)生姓名長度不能超過 10 且不能為空,郵箱地址要合法,年齡不能超過 150。那么在定義實體類的時候,就可以加入這個判斷條件了。
public class Student {
@NotNull
private Integer id;
@NotNull
@Size(min = 2,max = 10)
private String name;
@Email
private String email;
@Max(150)
private Integer age;
...
}
在這里:
- @NotNull 表示這個字段不能為空
- @Size 中描述了這個字符串長度的限制
- @Email 表示這個字段的值必須是一個郵箱地址
- @Max 表示這個字段的最大值
定義完成后,接下來,在 Controller 中定義接口:
@Controller
public class StudentController {
@RequestMapping("/addstudent")
@ResponseBody
public void addStudent(@Validated Student student, BindingResult result) {
if (result != null) {
//校驗未通過,獲取所有的異常信息并展示出來
List<ObjectError> allErrors = result.getAllErrors();
for (ObjectError allError : allErrors) {
System.out.println(allError.getObjectName()+":"+allError.getDefaultMessage());
}
}
}
}
在這里:
- @Validated 表示 Student 中定義的校驗規(guī)則將會生效
- BindingResult 表示出錯信息,如果這個變量不為空,表示有錯誤,否則校驗通過。
接下來就可以啟動項目了。訪問 jsp 頁面,然后添加 Student,查看校驗規(guī)則是否生效。
默認情況下,打印出來的錯誤信息時系統(tǒng)默認的錯誤信息,這個錯誤信息,我們也可以自定義。自定義方式如下:
由于 properties 文件中的中文會亂碼,所以需要我們先修改一下 IDEA 配置,點
File–>Settings->Editor–>File Encodings,如下:
https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6901df99-8a2e-418b-b791-77cff9fc1bb7/Untitled.png
然后定義錯誤提示文本,在 resources 目錄下新建一個 MyMessage.properties 文件,內(nèi)容如下:
student.id.notnull=id 不能為空
student.name.notnull=name不能為空
student.name.length=name最小長度為 2 ,最大長度為10
student.email.error=email地址非法
student.age.error=年齡不能超過 150
接下來,在 SpringMVC 配置中,加載這個配置文件:
<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" id="validatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<property name="validationMessageSource" ref="bundleMessageSource"/>
</bean>
<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="bundleMessageSource">
<property name="basenames">
<list>
<value>classpath:MyMessage</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
<property name="cacheSeconds" value="300"/>
</bean>
<mvc:annotation-driven validator="validatorFactoryBean"/>
最后,在實體類上,加上校驗出錯時的消息
public class Student {
@NotNull(message = "{student.id.notnull}")
private Integer id;
@NotNull(message = "{student.name.notnull}")
@Size(min = 2,max = 10,message = "{student.name.length}")
private String name;
@Email(message = "{student.email.error}")
private String email;
@Max(value = 150,message = "{student.age.error}")
private Integer age;
...
}
配置完成后,如果校驗再出錯,就會展示我們自己的出錯信息了。
分組校驗
由于校驗規(guī)則都是定義在實體類上面的,但是,在不同的數(shù)據(jù)提交環(huán)境下,校驗規(guī)則可能不一樣。例如,用戶的 id 是自增長的,添加的時候,可以不用傳遞用戶 id,但是修改的時候則必須傳遞用戶 id,這種情況下,就需要使用分組校驗。
分組校驗,首先需要定義校驗組,所謂的校驗組,其實就是空接口:
public interface ValidationGroup1 {
}
public interface ValidationGroup2 {
}
然后,在實體類中,指定每一個校驗規(guī)則所屬的組:
public class Student {
@NotNull(message = "{student.id.notnull}",groups = ValidationGroup1.class)
private Integer id;
@NotNull(message = "{student.name.notnull}",groups = {ValidationGroup1.class, ValidationGroup2.class})
@Size(min = 2,max = 10,message = "{student.name.length}",groups = {ValidationGroup1.class, ValidationGroup2.class})
private String name;
@Email(message = "{student.email.error}",groups = {ValidationGroup1.class, ValidationGroup2.class})
private String email;
@Max(value = 150,message = "{student.age.error}",groups = {ValidationGroup2.class})
private Integer age;
...
}
在 group 中指定每一個校驗規(guī)則所屬的組,一個規(guī)則可以屬于一個組,也可以屬于多個組。
最后,在接收參數(shù)的地方,指定校驗組:
@Controller
public class StudentController {
@RequestMapping("/addstudent")
@ResponseBody
public void addStudent(@Validated(ValidationGroup2.class) Student student, BindingResult result) {
if (result != null) {
//校驗未通過,獲取所有的異常信息并展示出來
List<ObjectError> allErrors = result.getAllErrors();
for (ObjectError allError : allErrors) {
System.out.println(allError.getObjectName()+":"+allError.getDefaultMessage());
}
}
}
}
配置完成后,屬于 ValidationGroup2 這個組的校驗規(guī)則,才會生效。
校驗注解
@Null 被注解的元素必須為 null
@NotNull 被注解的元素必須不為 null
@AssertTrue 被注解的元素必須為 true
@AssertFalse 被注解的元素必須為 false
@Min(value) 被注解的元素必須是一個數(shù)字,其值必須大于等于指定的最小值
@Max(value) 被注解的元素必須是一個數(shù)字,其值必須小于等于指定的最大值
@DecimalMin(value) 被注解的元素必須是一個數(shù)字,其值必須大于等于指定的最小值
@DecimalMax(value) 被注解的元素必須是一個數(shù)字,其值必須小于等于指定的最大值
@Size(max=, min=) 被注解的元素的大小必須在指定的范圍內(nèi)
@Digits (integer, fraction) 被注解的元素必須是一個數(shù)字,其值必須在可接受的范圍內(nèi)
@Past 被注解的元素必須是一個過去的日期
@Future 被注解的元素必須是一個將來的日期
@Pattern(regex=,flag=) 被注解的元素必須符合指定的正則表達式
@NotBlank(message =) 驗證字符串非 null,且長度必須大于0
@Email 被注解的元素必須是電子郵箱地址
@Length(min=,max=) 被注解的字符串的大小必須在指定的范圍內(nèi)
@NotEmpty 被注解的字符串的必須非空
@Range(min=,max=,message=) 被注解的元素必須在合適的范圍內(nèi)
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot隨機數(shù)設(shè)置及參數(shù)間引用的操作步驟
在Spring Boot配置文件中設(shè)置屬性時,除了可以像前面示例中顯示的配置屬性值外,還可以使用隨機值和參數(shù)間引用對屬性值進行設(shè)置。下面給大家介紹SpringBoot參數(shù)間引用隨機數(shù)設(shè)置的操作步驟,感興趣的朋友一起看看吧2021-06-06
記一次集成swagger2(Knife4j)在線文檔提示:Knude4j文檔請求異常的解決辦法
Knife4j是一個集Swagger2 和 OpenAPI3為一體的增強解決方案,下面這篇文章主要給大家介紹了關(guān)于一次集成swagger2(Knife4j)在線文檔提示:Knude4j文檔請求異常的解決辦法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-02-02
JavaWeb servlet實現(xiàn)下載與上傳功能的方法詳解
這篇文章主要介紹了JavaWeb servlet實現(xiàn)下載與上傳功能的方法,結(jié)合實例形式詳細分析了JavaWeb servlet實現(xiàn)下載與上傳功能的原理、實現(xiàn)方法與操作注意事項,需要的朋友可以參考下2020-04-04
大廠禁止SpringBoot在項目使用Tomcat容器原理解析
這篇文章主要為大家介紹了大廠禁止SpringBoot在項目使用Tomcat原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07
Spring @Component自定義注解實現(xiàn)詳解
@Component是一個元注解,意思是可以注解其他類注解,如@Controller @Service @Repository @Aspect。官方的原話是:帶此注解的類看為組件,當(dāng)使用基于注解的配置和類路徑掃描的時候,這些類就會被實例化2022-09-09

