SpringBoot配合Hibernate-Validator參數校驗(學習筆記2020.3.25)

SpringBoot配合Hibernate-Validator參數校驗(學習筆記2020.3.25)

Hibernate-Validator(官網)

前言:

RESTful Web Services的接口服務中,會有各種各樣的入參,我們不可能完全不做任何校驗就直接進入到業務處理的環節,通常我們會有一個基礎的數據驗證的機制,待這些驗證過程完畢,結果無誤後,參數纔會進入到正式的業務處理中。而數據驗證又分爲兩種,一種是無業務關聯的規則性驗證,一種是根據現有數據進行的聯動性數據驗證(簡單來說,參數的合理性,需要查數據庫)。而Hibernate-Validator則適合做無業務關聯(不需要對比數據庫)的規則性驗證。

1. 快速入門

1.1 引入依賴

創建springboot工程,如果是SpringBoot工程的話,Hibernate-Validator已經包含在spring-boot-starter-web裏面。

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
8jU7uT.png

如果是普通Spring工程,則引入:

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

Hibernate-Validator的主要使用的方式就是註解的形式,並且是“零配置”的,無需配置也可以使用。

1.2方法參數的校驗

@RestController
@Validated //加上開啓驗證器
public class UserController {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @GetMapping("/getUser")
    public User getUser(@NotNull(message = "名字不能爲空") String name,
                        @NotNull(message = "年齡不能爲空")@Min(value = 1L,message = "年齡最小1") Integer age, @NotNull(message = "性別不能爲空") String sex){
        log.info("成功訪問到了,參數是{},{},{}",name,age,sex);
        return new User(name, age, sex);
    }
}

然後啓動項目,進行訪問。 效果爲下圖。

8jWxG6.png

這樣的效果並不好,後端會輸出大量錯誤日記,並且前臺提示會亂碼。

1.3 使用全局異常處理器

使用全局異常處理器來捕獲ConstraintViolationException

@RestControllerAdvice
public class ViolationException {

    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseStatus(code = HttpStatus.BAD_REQUEST)
    public ExceptionResult exceptionResult(ConstraintViolationException exception){
        StringBuilder builder = new StringBuilder();
        for (ConstraintViolation<?> violation : exception.getConstraintViolations()) {
            String[] split = violation.getPropertyPath().toString().split("\\.");
            builder.append(split[1])
                    .append(violation.getMessage()).append(",");
        }
        return new ExceptionResult(builder.deleteCharAt(builder.length()-1).toString(), HttpStatus.BAD_REQUEST.value());
    }
}

請求過去後返回的結果:{"message":"age年齡不能爲空,name名字不能爲空,sex性別不能爲空","code":400}

如果想返回自定義錯誤頁面, 加上模板依賴:

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>參數錯誤頁面error.html</title>
</head>
<body>
    <div>
        <span>
            錯誤信息:  <span th:text="${message}"></span>
        </span> </p>
        <span>
            錯誤狀態碼:  <span th:text="${code}"></span>
        </span>
    </div>
</body>
</html>

異常處理器:

	@ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseStatus(code = HttpStatus.BAD_REQUEST)
    public ModelAndView ResultErrorHtml(ConstraintViolationException exception,
                                        HttpServletResponse response){
        StringBuilder builder = new StringBuilder();
        for (ConstraintViolation<?> violation : exception.getConstraintViolations()) {
            String[] split = violation.getPropertyPath().toString().split("\\.");
            builder.append(split[1])
                    .append(violation.getMessage()).append(",");
        }
        ModelAndView view = new ModelAndView();
        view.setViewName("error");
        view.addObject("message", builder.deleteCharAt(builder.length()-1).toString());
        view.addObject("code", HttpStatus.BAD_REQUEST.value());
        return view;
    }

1.4 實體類的校驗

方法參數校驗,少參數的情況下還是很方便的,但是做多參數的情況下就要用到實體類來進行校驗了。

public class User implements Serializable {

    @NotNull(message = "名字不能爲空")
    private String name;

    @NotNull(message = "年齡不能爲空")
    private Integer age;

    @NotNull(message = "性別不能爲空")
    private String sex;

    @NotNull(message = "生日不能爲空")
    private String birthday;
    .......省略
}

控制層api方法使用註解@Valid來進行校驗標記好的實體類

	@GetMapping("/getUsers")
    public User getUsers(@Valid User user){
        log.info("成功訪問到了,參數是{}",user);
        return user;
    }

訪問後控制檯會出現以下信息。

Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 4 errors

Field error in object 'user' on field 'sex': rejected value [null]; codes [NotNull.user.sex,NotNull.sex,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.sex,sex]; arguments []; default message [sex]]; default message [性別不能爲空]

這個時候叫需要在全局異常處理器進行添加一個異常類型BindException

注意別導錯異常類型包。

	@ExceptionHandler(value = BindException.class)
    @ResponseStatus(code = HttpStatus.BAD_REQUEST)
    public ExceptionResult bindExceptionResult(BindException exception){
        StringBuilder builder = new StringBuilder();
        for (FieldError fieldError : exception.getFieldErrors()) {
            builder.append(fieldError.getField())
                    .append(fieldError.getDefaultMessage()).append(",");
        }
        return new ExceptionResult(builder.deleteCharAt(builder.length()-1).toString(), HttpStatus.BAD_REQUEST.value());
    }

註解說明:

  • @NotNull : 註釋元素一定不能null 。

  • @Null : 帶註釋的元素必須爲null 。

  • @NotBlank : 該註釋元素不能爲null ,且必須含有至少一個非空白字符。 接受CharSequence

  • @NotEmpty : 註釋元素不能是null也不空。支持的類型包括 CharSequence , Collection , Map, 數組

  • @Size : 該註釋元素大小必須在指定的邊界之間(含), 支持的類型包括 CharSequence , Collection , Map, 數組

  • @Max : 帶註釋的元素必須是一個數字,其值必須小於或等於指定的最大值。支持的類型包括:

    BigDecimal
    BigInteger
    byte , short , int , long,和他們各自的包裝
    需要注意的是double和float不支持,由於舍入誤差(有些供應商可能提供一些近似的支持)。

  • @Min : 帶註釋的元素必須是一個數字,其值必須大於或等於指定的最小值。支持的類型與@Max一樣

  • @Email : 該字符串必須是一個結構完整的電子郵件地址。 是什麼使一個有效的電子郵件地址確切的語義留給Bean驗證

  • @Past : 註釋元素必須是在過去的瞬間,日期或時間。 null元素被認爲是有效的。

  • @PastOrPresent : 帶註釋的元素必須是在過去或在現在瞬間,日期或時間。

  • @AssertFalse :註釋元素一定是假的 @AssertTrue : 註釋元素一定是真的。

  • @Range(min = 18,max = 60,message = "只能填報年齡在18~60歲的")

其他的註解解析

項目代碼

1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章