Hibernate-Validator


1.Hibernate-Validator 簡介

​ hibernate-validator是Hibernate項目中的一個數據校驗框架,它能夠將數據校驗從業務代碼中脫離出來,增加代碼可讀性,同時也讓數據校驗變得更加方便、簡單。

官網地址:

http://hibernate.org/validator/documentation

2 項目中為什么要用校驗框架

Java程序開發中,當你要處理一個程序的業務邏輯時,請求參數的數據校驗是必須要處理的。當請求參數格式不正確的時候,需要程序監測到,並且返回對應的錯誤提示,以此來達到數據校驗的目的。對於前后端分離開發過程中,數據校驗還需要返回對應的狀態碼和錯誤提示信息。

3. 添加依賴

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

如果使用了springboot,則不需要引用任何依賴,因為spring-boot-starter-web包中已經包含了Hibernate-Validator 依賴。

4.在實體類上添加對應注解

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {

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

    @NotBlank(message = "郵箱不能為空")
    private String email;
}

5. POST方法中應用

@RestController
public class StudentController {

    @RequestMapping(value = "/addStudent",method = RequestMethod.POST)
    public String addStudent(@Valid @RequestBody Student student){
        System.out.println("student = [" + student + "]");
        return "ok";
    }

POST請求必須要加@Valid

@RequestBody 和 @RequestParam區別

@RequestBody獲取的是請求體里面的數據,一般是前端傳給后端的JSON字符串。

@RequestParam 接收的是url里面的查詢參數(比如xxxxxxx?name=admin)

以上面代碼為例,如果去掉@RequestBody那student的屬性就會從查詢參數獲取。

下面以PostMan演示以上兩個注解在調用時的區別

如果方法上面添加@RequestParam注解,應該這樣傳遞傳遞參數。

如果方法上面添加@RequestBody 注解,應該這樣傳遞傳遞參數。

6. GET方法中應用

@RestController
@Validated
public class StudentController {

    @RequestMapping(value = "/addStudent1",method = RequestMethod.GET)
    public String addStudent1(@NotBlank(message = "name不能為空") String name){
        System.out.println("name = [" + name + "]");
        return "ok addStudent1";
    }
}

Get請求需要在類上添加@Validated

7.利用PostMan調用接口

看到這個結果發現我們添加的校驗框架起作用了,響應信息中存在了"郵箱不能為空"的信息,但是前端用戶一般只關心一個校驗結果和校驗失敗信息,現在返回的這個信息太多了很難讓人接受。所以我們需要定義統一的效驗失敗后返回的格式,這個格式中只包含狀態碼和失敗原因。

7.定義優雅的返回信息

7.1 定義全局異常處理

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResultEntity handleBindException(MethodArgumentNotValidException ex) {
        FieldError fieldError = ex.getBindingResult().getFieldError();
        // 記錄日志。。。
        return ResultEntity.faill(211,fieldError.getDefaultMessage(),null);
    }

7.2 定義校驗失敗返回模板

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultEntity<T> {

    private Integer code;

    private String message;

    private T data;

    public  static <T> ResultEntity<T> faill(Integer code,String msg,T t){
        return new ResultEntity<T>(code,msg,t);
    }
}

7.3 測試

8.常用注解

注解 說明
@Nul 被注釋的元素必須為 null
@NotNull 被注釋的元素必須不為 null
@AssertTrue 被注釋的元素必須為 true
@AssertFalse 被注釋的元素必須為 false
@Min(value) 被注釋的元素必須是一個數字,其值必須大於等於指定的最小值
@Max(value) 被注釋的元素必須是一個數字,其值必須小於等於指定的最大值
@DecimalMin(value) 被注釋的元素必須是一個數字,其值必須大於等於指定的最小值
@DecimalMax(value) 被注釋的元素必須是一個數字,其值必須小於等於指定的最大值
@Size(max, min) 被注釋的元素的大小必須在指定的范圍內,元素必須為集合,代表集合個數
@Pattern(regexp = ) 正則表達式校驗
@Digits (integer, fraction) 被注釋的元素必須是一個數字,其值必須在可接受的范圍內
@Past 被注釋的元素必須是一個過去的日期
@Future 被注釋的元素必須是一個將來的日期
@Email 被注釋的元素必須是電子郵箱地址
@Length(min=, max=) 被注釋的字符串的大小必須在指定的范圍內,必須為數組或者字符串,若微數組則表示為數組長度,字符串則表示為字符串長度
@NotEmpty 被注釋的字符串的必須非空
@Range(min=, max=) 被注釋的元素必須在合適的范圍內
@NotBlank 被注釋的字符串的必須非空
@URI 字符串是否是一個有效的URL

注意

  • @NotEmpty 用在集合類上面
  • @NotBlank 用在String上面
  • @NotNull 用在基本類型上

9.Hibernate-Validator校驗模式

普通模式

校驗完所有的屬性,然后返回所有的驗證失敗信息,默認是這個模式

快速失敗返回模式

只要有一個失敗就立馬返回

開啟快速失敗返回模式

@Configuration
public class HibernateValidatorConfiguration {
    @Bean
    public Validator validator(){
        ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
                .configure()
                // true  快速失敗返回模式    false 普通模式
                .addProperty( "hibernate.validator.fail_fast", "true" )
                .buildValidatorFactory();
        Validator validator = validatorFactory.getValidator();

        return validator;
    }
}

測試驗證不通過就會拋出 ConstraintViolationException異常,和之前普通模式下拋出的異常不一樣,所以為了格式統一我還需要自定義的異常處理。

全局異常處理

    // 開啟快速失敗返回模式,GET請求校驗不通過會拋出如下異常,在這對它處理
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public ResultEntity handle(ValidationException exception) {
        if (exception instanceof ConstraintViolationException) {
            ConstraintViolationException exs = (ConstraintViolationException) exception;

            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            for (ConstraintViolation<?> item : violations) {
                System.out.println(item.getMessage());
                return ResultEntity.faill(212, item.getMessage(), null);
            }
        }
        return ResultEntity.faill(212, "abc", null);
    }

10.對象級聯校驗

Student

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {

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

    @Max(150)
    @Min(10)
    @NotNull(message = "年齡不能為空")
    private Integer age;

    @Email
    private String email;

    @NotNull(message = "user不能為空")
    @Valid
    private User user;
}

User

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private Integer id;

    @NotNull(message = "user對象中的username不能為空")
    private String username;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM