1, Parameter verification of SpringBoot
1. Parameter verification annotation provided by SpringBoot
Except that @ NotEmpty and @ NotBlank consider null values illegal, other annotations such as @ Size, @ Max, @ Min, etc. consider null as valid. If null values are not allowed, additional @ NotNull annotations need to be added.
annotation | explain |
@NotEmpty | String, collection, Map, array, etc. cannot be null or empty |
@NotBlank | The string cannot be null and contains at least one non empty character |
@NotNull | Any type cannot be null |
@Size | The number of string, set, Map, array and other elements must be within the specified min and max range |
| The string is a valid mailbox |
@Digits | String, integer and floating point number are numbers. The parameter integer represents the number of integer digits and fraction represents the number of decimal digits |
@CreditCardNumber | The string is a valid credit card number. The validity of the credit card itself is not verified |
@AssertTrue | Boolean type must be true, null value is considered valid |
@Max | Integer and floating point numbers must be less than or equal to the specified maximum value |
@Min | Integer and floating point numbers must be greater than or equal to the specified minimum value |
@Range | The string and number must be within the specified min and max range |
@Pattern | The string must match the specified regular expression |
@Data public class Employee implements Serializable { private static final long serialVersionUID = -8224860450904540019L; @NotEmpty(message = "Name cannot be empty") @UTF8Size(max = 16, message = "name should be short than 128") private String name; @Email private String email; @NotBlank(message = "city is required") @Size(max = 128, message = "city should be short than 128") private String city; @CreditCardNumber(message = "invalid credit card number") private String ccNumber; @Pattern(regexp = "^(0[1-9]|1[0-2])([\\\\/])([1-9][0-9])$", message = "required format MM/YY") private String ccExpiration; @Digits(integer = 3, fraction = 0, message = "invalid CVV") private String ccCVV; }
2. Custom verification annotation
@Size cannot support Chinese characters. You can customize the following, and then use @ UTF8Size on the fields that need to verify characters (Chinese and English).
@Documented @Constraint(validatedBy = Utf8SizeValidator.class) @Target({METHOD, FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface UTF8Size { String message() default "{javax.validation.constraints.Size.message}"; int min() default 0; int max() default Integer.MAX_VALUE; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } public class Utf8SizeValidator implements ConstraintValidator<UTF8Size, String> { private int maxCharSize; @Override public void initialize(UTF8Size constraintAnnotation) { this.maxCharSize = constraintAnnotation.max(); } @Override public boolean isValid(String value, ConstraintValidatorContext context) { if (Objects.isNull(value)) { return true; } return value.getBytes(Charset.forName("GB18030")).length <= maxCharSize; } }
2, Use of field verification
Use the @ Valid annotation of the Bean Validation API or the @ Validated annotation provided by Spring Context to enable Bean validation. The main difference is that @ Validated is a variant of @ Valid and supports validation groups.
1. This method will throw the exception information to the global exception handler
@PostMapping("/emp") public String addEmploy(@RequestBody @Valid Employee employee) { log.info("employee to create: {}", employee); String employeeId = UUID.randomUUID().toString(); return employeeId; }
2. If you need to capture the abnormal result of parameter verification, write it as follows
This method does not return the result of exception handling to global exception handling
@PostMapping() UserInfo addUser(@RequestBody @Valid UserInfo userInfo, BindingResult bindingResult) { userService.addUser(userInfo); return userInfo; }
3, Global exception handling for field verification
package com.example.springboot.exception; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import java.util.stream.Collectors; @Slf4j @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) public String handleMethodArgumentNotValidException( MethodArgumentNotValidException exception) { log.error("method argument not valid: {}", exception.getMessage()); String errorMessage = "field error"; BindingResult bindingResult = exception.getBindingResult(); if (bindingResult.hasErrors()) { errorMessage = bindingResult.getFieldErrors().stream() .map(FieldError::getDefaultMessage) .collect(Collectors.joining(" | ")); } return errorMessage; } }
4, Group check
The same field requires different verification strategies in different scenarios
1. Group interface
public class GroupVaildDTO { public interface SaveGroup extends Default {} public interface UpdateGroup extends Default {} }
2. Checked JavaBean properties
public class GroupsValidForm { @Null(message = "id Must be null", groups = {GroupVaildDTO.SaveGroup.class}) @NotNull(message = "id Cannot be null", groups = {GroupVaildDTO.UpdateGroup.class}) private Integer id; @NotBlank(message = "User name cannot be empty") private String userName; @Override public String toString() { final StringBuffer sb = new StringBuffer("GroupsValidForm{"); sb.append("id=").append(id); sb.append(", userName='").append(userName).append('\''); sb.append('}'); return sb.toString(); } }
3. Use of Controller layer group verification
The same field requires different verification strategies in different scenarios
@PostMapping(value = "update") public ServerResponse update(@RequestBody @Validated(value = GroupVaildDTO.UpdateGroup.class) GroupsValidForm groupsValidForm, BindingResult results) { if (results.hasErrors()) { return ServerResponse.createByErrorMessage(results.getFieldError().getDefaultMessage()); } return ServerResponse.createBySuccess(); }