SpringMVC Validator驗證示例
SpringMVC服務(wù)器驗證一種是有兩種方式,一種是基于Validator接口,一種是使用Annotaion JSR-303標(biāo)準(zhǔn)的驗證,下面主要是學(xué)習(xí)這兩種,工作中推薦后者,方便很多
一.基于Validator接口的驗證.
首先創(chuàng)建User實例,并加入幾個屬性
public class User {
private String username;
private String password;
private String nickname;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
@Override
public String toString() {
return "username--"+username+"password--"+password+"nickname--"+nickname;
}
}
接著創(chuàng)建用于校檢的類UserValidator,讓其實現(xiàn)Validator,覆蓋其中的兩個方法
import main.java.model.User;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
public class UserValidator implements Validator {
@Override
public boolean supports(Class<?> aClass) {
//判斷是否是要校驗的類,這里是User
return User.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors) {
User u = (User) o;
if (null == u.getPassword() || "".equals(u.getPassword())){
//此方法可以加四個參數(shù),第一個表單域field,
//區(qū)分是哪個表單出錯,第二個errorCode錯誤碼,
//第三個制定了資源文件中占位符,第四個具體錯誤返回信息
//簡寫版可以把2,3參數(shù)去掉
errors.rejectValue("password",null,null,"password is null");
}
}
}
上面的類只實現(xiàn)了對密碼判斷是否為空,為空則注冊這一錯誤信息,也就是”password is null”,接下來要實現(xiàn)控制器,控制器要做的事情,第一是注冊這個校驗器,第二是實現(xiàn)校驗.
import main.java.model.User;
......
/**
* 加上@Controller決定這個類是一個控制器
*/
@Controller
@RequestMapping("/user")
public class HelloController {
//我們知道在Controller類中通過@InitBinder標(biāo)記的方法只有在請求當(dāng)前Controller的時候才會被執(zhí)行
//所以在這里注冊校驗器
@InitBinder
public void initBainder(DataBinder binder){
binder.replaceValidators(new UserValidator());
}
//這個方法主要是跳轉(zhuǎn)到登錄頁面
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String login(Model model){
model.addAttribute(new User());
return "user/login";
}
//處理登錄表單
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(@Validated User user, BindingResult br){
if (br.hasErrors()){
return "user/login";
}
return "--";
}
}
上面代碼可以看到@Validated User user, BindingResult br這兩個參數(shù),@Validated表明參數(shù)user是要校驗的類,BindingResult是存儲錯誤信息的類,兩者必須一一對應(yīng),并且位置挨著,不能中間有其他參數(shù),
最后隨便寫一個jsp頁面實現(xiàn)校檢
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<%
request.setCharacterEncoding("utf-8");
%>
<html>
<head>
<meta charset="utf-8">
<title>用戶登錄</title>
</head>
<body>
<sf:form modelAttribute="user" method="post">
用戶名:<sf:input path="username"/><sf:errors path="username"/>
<br>
密碼:<sf:input path="password"/><sf:errors path="password"/>
<br>
昵稱:<sf:input path="nickname"/><sf:errors path="nickname"/>
<br>
<input type="submit" value="提交">
</sf:form>
</body>
</html>

前面實現(xiàn)的是局部校驗,只對當(dāng)前控制器有效,如果要實現(xiàn)全局校驗的話需要配置springMVC.xml文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <mvc:annotation-driven validator="userValidator"/> <bean id="userValidator" class="com.xxx.xxx.UserValidator"/> ... </beans>
二.使用Annotaion JSR-303標(biāo)準(zhǔn)的驗證
使用這個需要導(dǎo)入支持JSR-303標(biāo)準(zhǔn)的包,建議使用hibernate Validator這個包,先看這個標(biāo)準(zhǔn)的原生標(biāo)注
| 限制 | 說明 |
|---|---|
| @Null | 限制只能為null |
| @NotNull | 限制必須不為null |
| @AssertFalse | 限制必須為false |
| @AssertTrue | 限制必須為true |
| @DecimalMax(value) | 限制必須為一個不大于指定值的數(shù)字 |
| @DecimalMin(value) | 限制必須為一個不小于指定值的數(shù)字 |
| @Digits(integer,fraction) | 限制必須為一個小數(shù),且整數(shù)部分的位數(shù)不能超過integer,小數(shù)部分的位數(shù)不能超過fraction |
| @Future | 限制必須是一個將來的日期 |
| @Max(value) | 限制必須為一個不大于指定值的數(shù)字 |
| @Min(value) | 限制必須為一個不小于指定值的數(shù)字 |
| @Past | 限制必須是一個過去的日期 |
| @Pattern(value) | 限制必須符合指定的正則表達(dá)式 |
| @Size(max,min) | 限制字符長度必須在min到max之間 |
| @Past | 驗證注解的元素值(日期類型)比當(dāng)前時間早 |
| @NotEmpty | 驗證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0) |
| @NotBlank | 驗證注解的元素值不為空(不為null、去除首位空格后長度為0),不同于@NotEmpty,@NotBlank只應(yīng)用于字符串且在比較時會去除字符串的空格 |
| 驗證注解的元素值是Email,也可以通過正則表達(dá)式和flag指定自定義的email格式 |
要使用很簡單,在需要驗證的變量前面加上該Annotation即可,看下面使用后的User
public class User {
@NotEmpty(message = "用戶名不能為空")
private String username;
@Size(min=6 ,max= 20 ,message = "密碼長度不符合標(biāo)準(zhǔn)")
private String password;
private String nickname;
......
}
然后再控制器里面加入驗證就可以了
@Controller
@RequestMapping("/user")
public class HelloController {
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String login(Model model){
model.addAttribute(new User());
return "user/login";
}
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(@Validated User user, BindingResult br){
if (br.hasErrors()){
return "user/login";
}
return "user/login";
}
}
然后jsp頁面還是之前的頁面,驗證效果如下,這種方法明顯簡單多了

3.定義自己的Annotation Validator
這部分直接從[大牛][1]那拷貝過來的.
除了JSR-303原生支持的限制類型之外我們還可以定義自己的限制類型。定義自己的限制類型首先我們得定義一個該種限制類型的注解,而且該注解需要使用@Constraint標(biāo)注。現(xiàn)在假設(shè)我們需要定義一個表示金額的限制類型,那么我們可以這樣定義:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import com.xxx.xxx.constraint.impl.MoneyValidator;
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=MoneyValidator.class)
public @interface Money {
String message() default"不是金額形式";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
我們可以看到在上面代碼中我們定義了一個Money注解,而且該注解上標(biāo)注了@Constraint注解,使用@Constraint注解標(biāo)注表明我們定義了一個用于限制的注解。@Constraint注解的validatedBy屬性用于指定我們定義的當(dāng)前限制類型需要被哪個ConstraintValidator進行校驗。在上面代碼中我們指定了Money限制類型的校驗類是MoneyValidator。另外需要注意的是我們在定義自己的限制類型的注解時有三個屬性是必須定義的,如上面代碼所示的message、groups和payload屬性。
在定義了限制類型Money之后,接下來就是定義我們的限制類型校驗類MoneyValidator了。限制類型校驗類必須實現(xiàn)接口javax.validation.ConstraintValidator,并實現(xiàn)它的initialize和isValid方法。我們先來看一下MoneyValidator的代碼示例:
import java.util.regex.Pattern;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.xxx.xxx.constraint.Money;
public class MoneyValidator implements ConstraintValidator<Money, Double> {
private String moneyReg = "^\\d+(\\.\\d{1,2})?$";//表示金額的正則表達(dá)式
private Pattern moneyPattern = Pattern.compile(moneyReg);
public void initialize(Money money) {
// TODO Auto-generated method stub
}
public boolean isValid(Double value, ConstraintValidatorContext arg1) {
// TODO Auto-generated method stub
if (value == null)
return true;
return moneyPattern.matcher(value.toString()).matches();
}
}
從上面代碼中我們可以看到ConstraintValidator是使用了泛型的。它一共需要指定兩種類型,第一個類型是對應(yīng)的initialize方法的參數(shù)類型,第二個類型是對應(yīng)的isValid方法的第一個參數(shù)類型。從上面的兩個方法我們可以看出isValid方法是用于進行校驗的,有時候我們在校驗的過程中是需要取當(dāng)前的限制類型的屬性來進行校驗的,比如我們在對@Min限制類型進行校驗的時候我們是需要通過其value屬性獲取到當(dāng)前校驗類型定義的最小值的,我們可以看到isValid方法無法獲取到當(dāng)前的限制類型Money。這個時候initialize方法的作用就出來了。
我們知道initialize方法是可以獲取到當(dāng)前的限制類型的,所以當(dāng)我們在校驗?zāi)撤N限制類型時需要獲取當(dāng)前限制類型的某種屬性的時候,我們可以給當(dāng)前的ConstraintValidator定義對應(yīng)的屬性,然后在initialize方法中給該屬性賦值,接下來我們就可以在isValid方法中使用其對應(yīng)的屬性了。針對于這種情況我們來看一個代碼示例,現(xiàn)在假設(shè)我要定義自己的@Min限制類型和對應(yīng)的MinValidator校驗器,那么我可以如下定義:
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=MinValidator.class)
public @interface Min {
int value() default 0;
String message();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
MinValidator校驗器
public class MinValidator implements ConstraintValidator<Min, Integer> {
private int minValue;
public void initialize(Min min) {
// TODO Auto-generated method stub
//把Min限制類型的屬性value賦值給當(dāng)前ConstraintValidator的成員變量minValue
minValue = min.value();
}
public boolean isValid(Integer value, ConstraintValidatorContext arg1) {
// TODO Auto-generated method stub
//在這里我們就可以通過當(dāng)前ConstraintValidator的成員變量minValue訪問到當(dāng)前限制類型Min的value屬性了
return value >= minValue;
}
}
繼續(xù)來說一下ConstraintValidator泛型的第二個類型,我們已經(jīng)知道它的第二個類型是對應(yīng)的isValid的方法的第一個參數(shù),從我給的參數(shù)名稱value來看也可以知道isValid方法的第一個參數(shù)正是對應(yīng)的當(dāng)前需要校驗的數(shù)據(jù)的值,而它的類型也正是對應(yīng)的我們需要校驗的數(shù)據(jù)的數(shù)據(jù)類型。這兩者的數(shù)據(jù)類型必須保持一致,否則spring會提示找不到對應(yīng)數(shù)據(jù)類型的ConstraintValidator。建立了自己的限制類型及其對應(yīng)的ConstraintValidator后,其用法跟標(biāo)準(zhǔn)的JSR-303限制類型是一樣的。以下就是使用了上述自己定義的JSR-303限制類型——Money限制和Min限制的一個實體類:
public class User {
private int age;
private Double salary;
@Min(value=8, message="年齡不能小于8歲")
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Money(message="標(biāo)準(zhǔn)的金額形式為xxx.xx")
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
}
4.配合ajax驗證
最近寫的項目,感覺直接使用validator不太好用,主要是返回時會刷新整個頁面才會出來錯誤信息,體驗相當(dāng)不好,驗證還是用ajax體驗比較好,所以配合ajax
思路:驗證還是使用springMVC來驗證,只是這次發(fā)現(xiàn)錯誤的話,把錯誤取出,存放到一個map中,然后ajax返回,頁面根據(jù)ajax返回值來判斷,從而顯示不同的信息
主要代碼:
if (br.hasErrors()){//判斷是否有錯誤
//對錯誤集合進行遍歷,有的話,直接放入map集合中
br.getFieldErrors().forEach(p->{
maps.put(p.getField(),p.getDefaultMessage());
});
return maps;
}
這樣的話 maps里面存放的就是 錯誤變量名,錯誤信息,例如 username -‘用戶名不能為空'
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 使用SpringMVC的@Validated注解驗證的實現(xiàn)
- springMVC引入Validation的具體步驟詳解
- Spring MVC+FastJson+hibernate-validator整合的完整實例教程
- JSP中springmvc配置validator的注意事項
- springmvc的validator數(shù)據(jù)校驗的實現(xiàn)示例代碼
- SpringMVC 使用JSR-303進行校驗 @Valid示例
- 詳解SpringMVC驗證框架Validation特殊用法
- SpringMVC使用@Valid注解進行數(shù)據(jù)驗證的方法
- SpringMvc @Valid如何拋出攔截異常
相關(guān)文章
Java中JDK14的新特性之JFR,JMC和JFR事件流(推薦)
JFR是一個基于事件的低開銷的分析引擎,具有高性能的后端,可以以二進制格式編寫事件,而JMC是一個GUI工具,用于檢查JFR創(chuàng)建的數(shù)據(jù)文件。本文給大家介紹Java中JDK14的新特性之JFR,JMC和JFR事件流的相關(guān)知識,感興趣的朋友一起看看吧2020-05-05
List集合中對數(shù)據(jù)實現(xiàn)多重規(guī)則進行排序的案例
今天小編就為大家分享一篇關(guān)于List集合中對數(shù)據(jù)實現(xiàn)多重規(guī)則進行排序的案例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12
關(guān)于idea2020.3升級lombok不能使用的問題
這篇文章主要介紹了關(guān)于idea2020.3升級lombok不能使用的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12
SpringBoot?使用?Sa-Token?完成注解鑒權(quán)功能(權(quán)限校驗)
Sa-Token?是一個輕量級?java?權(quán)限認(rèn)證框架,主要解決登錄認(rèn)證、權(quán)限認(rèn)證、單點登錄、OAuth2、微服務(wù)網(wǎng)關(guān)鑒權(quán)?等一系列權(quán)限相關(guān)問題,這篇文章主要介紹了SpringBoot使用Sa-Token完成注解鑒權(quán)功能,需要的朋友可以參考下2023-05-05
SpringBoot+MyBatis+Redis實現(xiàn)分布式緩存
本文主要介紹了SpringBoot+MyBatis+Redis實現(xiàn)分布式緩存,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01
java 中Comparable與Comparator詳解與比較
這篇文章主要介紹了java 中Comparable與Comparator詳解與比較的相關(guān)資料,需要的朋友可以參考下2017-04-04

