1. 程式人生 > >Spring Boot的引數校驗

Spring Boot的引數校驗

閱讀本文需要Spring Boot、Java註解等背景知識

背景

我們通常需要驗證引數是否非法, 比如長度、非空、列舉範圍等.

  • 二逼青年的做法是寫一堆if進行校驗
if (id == null || id <= 0) {
    throw new WrongParamException("引數id錯誤");
}
  • 普通青年的做法是封裝成一個方法
public static String verifyStringOfRequire(String val, String name, int length) throws WrongParamException {
    if
(val == null) { throw new WrongParamException("請填寫" + name); } else { val = val.trim(); if (val.length() == 0) { throw new WrongParamException(name + "不能全部為空格"); } if (val.length() > length) { throw new WrongParamException(name + "長度不能超過"
+ length); } return val; } } ... String name = MyUtils.verifyStringOfRequire(requestDto.getName(), "名字", 100);

兩種程式碼都混入了與業務邏輯無關的程式碼, 因此文藝青年的做法是利用spring提供的驗證框架. 以下分幾種應用場景來介紹

RequestParam和PathVariable

spring為我們提供兩個基本的註解, RequestParamPathVariable, 可以指定我們需要的引數名、引數型別、是否必填等基本校驗, 否則返回400錯誤碼.

驗證屬性

@GetMapping("/validStringLength")
public ResponseEntity<String> validStringLength(
        @Valid
        @Size(min = 10, message = "wrong length")
        @RequestParam(value = "value") String value) {
    return ResponseEntity.ok(value);
 }

此時傳入一個長度小於10的引數, 就會報錯. 如果再配合一個全域性異常攔截, 提示message的內容, 就非常爽歪歪了.

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ResponseEntity<String> constraintViolationExceptionHandler(ConstraintViolationException e) {
        return ResponseEntity.badRequest().body(e.getConstraintViolations().stream()
                .map(ConstraintViolation::getMessageTemplate)
                .findFirst()
                .orElse(e.getMessage())
        );
    }
}

[1]:

Annotation Part of Bean Validation Specification Apply on Use Hibernate Metadata impact
@AssertFalse yes field/property Check that the annotated element is false. none
@AssertTrue yes field/property Check that the annotated element is true. none
@CreditCardNumber no field/property. The supported type is String. Check that the annotated string passes the Luhn checksum test. Note, this validation aims to check for user mistake, not credit card validity! none
@DecimalMax yes field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. The annotated element must be a number whose value must be lower or equal to the specified maximum. The parameter value is the string representation of the max value according to the BigDecimal string representation. none
@DecimalMin yes field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. The annotated element must be a number whose value must be higher or equal to the specified minimum. The parameter value is the string representation of the min value according to the BigDecimal string representation. none
@Digits(integer=, fraction=) yes field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. Check whether the property is a number having up to integer digits and fraction fractional digits. Define column precision and scale.
@Email no field/property. Needs to be a string. Check whether the specified string is a valid email address. none
@Future yes field/property. Supported types are java.util.Date and java.util.Calendar. Checks whether the annotated date is in the future. none
@Length(min=, max=) no field/property. Needs to be a string. Validate that the annotated string is between min and max included. Column length will be set to max.
@Max yes field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. Checks whether the annotated value is less than or equal to the specified maximum. Add a check constraint on the column.
@Min yes field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. Checks whether the annotated value is higher than or equal to the specified minimum. Add a check constraint on the column.
@NotNull yes field/property Check that the annotated value is not null. Column(s) are not null.
@NotBlank no field/property Check that the annotated string is not null and the trimmed length is greater than 0. The difference to @NotEmpty is that this constraint can only be applied on strings and that trailing whitespaces are ignored. none
@NotEmpty no field/property. Supported types are String, Collection, Map and arrays. Check whether the annotated element is not null nor empty. none
@Null yes field/property Check that the annotated value is null. none
@Past yes field/property. Supported types are java.util.Date and java.util.Calendar. Checks whether the annotated date is in the past. none
@Pattern(regex=, flag=) yes field/property. Needs to be a string. Checks if the annotated string matches the regular expression regex considering the given flag match. none
@Range(min=, max=) no field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. Check whether the annotated value lies between (inclusive) the specified minimum and maximum. none
@Size(min=, max=) yes field/property. Supported types are String, Collection, Map and arrays. Check if the annotated element size is between min and max (inclusive). Column length will be set to max.
@ScriptAssert(lang=, script=, alias=) no type Checks whether the given script can successfully be evaluated against the annotated element. In order to use this constraint, an implementation of the Java Scripting API as defined by JSR 223 (“Scripting for the JavaTM Platform”) must part of the class path. This is automatically the case when running on Java 6. For older Java versions, the JSR 223 RI can be added manually to the class path.The expressions to be evaluated can be written in any scripting or expression language, for which a JSR 223 compatible engine can be found in the class path. none
@URL(protocol=, host=, port=) no field/property. The supported type is String. Check if the annotated string is a valid URL. If any of parameters protocol, host or port is specified the URL must match the specified values in the according part. none
@Valid yes field/property. Any non-primitive types are supported. Performs validation recursively on the associated object. If the object is a collection or an array, the elements are validated recursively. If the object is a map, the value elements are validated recursively. none