1. 程式人生 > >在SpringMVC中使用數據驗證組件——hibernate-validator

在SpringMVC中使用數據驗證組件——hibernate-validator

SpringMVC hibernate-validator 數據驗證 數據驗證框架

在做web開發的時候,經常需要對客戶端發送過來的數據進行一個驗證,以防數據不合法。而SpringMVC支持的數據校驗是JSR303的標準,通過在bean的屬性上打上annotation @NotNull @Max等註解進行驗證。JSR303提供有很多annotation借口,而SpringMVC對於這些驗證是使用hibernate的實現,所以我們需要添加hibernate的一個validator包:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.4.1.Final</version>
</dependency>

Spring配置文件內容如下:

<?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" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:annotation-config/>
    <context:component-scan base-package="org.zero01"/>
    <mvc:annotation-driven/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/" p:suffix=".jsp"
    />

</beans>

hibernate除了JSR303的標準之外還額外提供了其他的驗證註解。下表是JSR303支持的驗證註解:
技術分享圖片

Hibernate Validator 附加的註解:
技術分享圖片

下面我們來寫個小demo,具體演示一下如何使用。例如,我要驗證一些字段不能為空,那麽就可以使用@NotNull這個註解,如下示例:

package org.zero01.test;

import javax.validation.constraints.NotNull;

public class UserRegister {

    @NotNull(message = "用戶名不能為空")
    private String userName;
    @NotNull(message = "密碼不能為空")
    private String password;
    @NotNull(message = "聯系地址不能為空")
    private String address;
    @NotNull(message = "電話號碼不能為空")
    private String phone;
    ...getter and setter...

在控制器的方法參數中,需要通過聲明BindingResult參數來獲得驗證出錯的信息,然後使用@Valid註解來配置哪個pojo對象需要校驗,控制器代碼如下:

package org.zero01.test;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.validation.Valid;

@Controller
public class Test {

    @RequestMapping(value = "/test.do", method = RequestMethod.GET)
    // 註意,@Valid和BindingResult是配對出現,並且形參順序是固定的(一前一後),不然就會返回400狀態碼
    public String test(@Valid UserRegister userRegister, BindingResult bindingResult, Model model) {
        // 判斷是否有異常
        if (bindingResult.hasErrors()) {
            System.out.println("客戶端的請求數據異常,所有的異常如下:");
            // 取出所有的異常對象
            for (FieldError fieldError : bindingResult.getFieldErrors()) {
                // 打印異常的字段以及異常信息
                System.out.println(fieldError.getField() + " : " + fieldError.getDefaultMessage());
            }
            return "register";
        }
        return "index";
    }
}

使用Postman進行訪問,什麽參數都不寫:
技術分享圖片

控制臺輸出結果如下:

客戶端的請求數據異常,所有的異常如下:
address : 聯系地址不能為空
userName : 用戶名不能為空
password : 密碼不能為空
phone : 電話號碼不能為空

下面再來演示一下其他常用的註解:

package org.zero01.test;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

public class UserRegister {

    @NotNull(message = "用戶名不能為空")
    private String userName;

    @NotNull(message = "密碼不能為空")
    @Length(max = 12, min = 6, message = "密碼長度需在6-12位之間")
    private String password;

    @NotNull(message = "聯系地址不能為空")
    private String address;

    @NotNull(message = "電話號碼不能為空")
    // 指定正則表達式驗證格式
    @Pattern(regexp = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\\\d{8}$", message = "電話號碼格式錯誤")
    private String phone;

    @Email(message = "郵箱格式錯誤")
    private String email;

    @Size(max = 10, min = 1, message = "成績單列表長度需在1-10之間")
    public List resultList;
    ...getter and setter...

控制器代碼和之前一致,略。

使用Postman進行訪問,如下:
技術分享圖片

控制臺輸出結果如下:

客戶端的請求數據異常,所有的異常如下:
address : 聯系地址不能為空
userName : 用戶名不能為空
password : 密碼長度需在6-12位之間
phone : 電話號碼格式錯誤
email : 郵箱格式錯誤
resultList : 成績單列表長度需在1-10之間

以上我們都是對所有的字段進行驗證,如果我希望有些字段不被驗證或者分開驗證該怎麽辦呢?這時候我們就需要到分組驗證了,首先編寫一個接口:

package org.zero01.test;

public interface Group {
}

然後在需要分組的字段上的註解中加上groups屬性,該屬性的值為以上我們所定義的接口類,如下示例:

package org.zero01.test;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

public class UserRegister {

    // groups 屬性用於指定分組,值為一個接口類
    @NotNull(message = "用戶名不能為空", groups = Group.class)
    private String userName;

    @NotNull(message = "密碼不能為空", groups = Group.class)
    @Length(max = 12, min = 6, message = "密碼長度需在6-12位之間", groups = Group.class)
    private String password;

    @NotNull(message = "聯系地址不能為空")
    private String address;

    @NotNull(message = "電話號碼不能為空")
    @Pattern(regexp = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\\\d{8}$", message = "電話號碼格式錯誤")
    private String phone;

    @Email(message = "郵箱格式錯誤")
    private String email;
    ...getter and setter...

控制器代碼如下:

package org.zero01.test;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.validation.Valid;

@Controller
public class Test {

    @RequestMapping(value = "/test.do", method = RequestMethod.GET)
    // 分組的情況下需要使用Validated註解來指定接口
    public String test(@Validated(Group.class) UserRegister userRegister, BindingResult bindingResult, Model model) {

        if (bindingResult.hasErrors()) {
            System.out.println("客戶端的請求數據異常,所有的異常如下:");

            for (FieldError fieldError : bindingResult.getFieldErrors()) {
                System.out.println(fieldError.getField() + " : " + fieldError.getDefaultMessage());
            }
            return "register";
        }
        return "index";
    }
}

訪問方式和之前一致,略。

控制臺輸出結果如下:

客戶端的請求數據異常,所有的異常如下:
password : 密碼長度需在6-12位之間
userName : 用戶名不能為空

如上,從控制臺的打印結果中,可以看到只有password以及userName兩個字段受到了驗證,這是因為我們只在這兩個字段上的註解中指定了groups 屬性。所以分組驗證就是只驗證指定組的字段,而這個組的劃分是以接口來劃分的。

在SpringMVC中使用數據驗證組件——hibernate-validator