This is the 23rd day of my participation in the August More Text Challenge.More challenges in August
We are using Hibernate-Validator as an object parameter validator, so before we introduce SpringBoot parameter validation, we need to take a quick look at hibernate-Validator.
Hibernate – Validator is basically used
Introduction of depend on
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.17. The Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
Copy the code
Write the required validation object
Validation requires that the user name of the Person object be non-empty and between the ages of 1 and 150.
@Data
public class Person {
@NotBlank(message = "username must not be null")
private String username;
@Min(value = 1, message = "age must be >= 1")
@Max(value = 150, message = "age must be < 150")
private Integer age;
}
Copy the code
Verify that the object properties meet the requirements
/** * Object validator */
public Validator validator(a) {
ValidatorFactory validatorFactory =
Validation
.byProvider(HibernateValidator.class)
.configure()
// When validating attributes, if one of the validations fails, it is returned without validating all attributes
.addProperty("hibernate.validator.fail_fast"."true")
.buildValidatorFactory();
return validatorFactory.getValidator();
}
@Test
public void test(a) throws Exception {
Person person = new Person();
Set<ConstraintViolation<Person>> validate = validator().validate(person);
validate.forEach(errorParam -> {
System.out.println(errorParam.getMessage());
});
}
Copy the code
- We only need the verified object instance to complete the object validation. If the validation succeeds, an empty collection is returned, and if the validation fails, the specific failed attribute information is returned.
- We output the following error message for validation failure:
username must not be null
Copy the code
The validation rules
Validator provides a large number of validation annotations to use, mainly in the following categories:
Null/non-null validation
@Null
The element must be empty@NotNull
Element cannot be empty, empty string""
Is empty
All of the following validation rules only validate if the element is not empty, and if the element passed is empty, the validation will pass.
bool
@AssertTrue
The element must be true@AssertFalse
The element must be false
time
@Future
The element must be some time in the future.@FutureOrPresent
The element must be some time in the future or present.@Past
The element must be some time in the past.@PastOrPresent
The element must be some time in the past or present.
mathematics
The numeric types can be BigDecimal, BigInteger, CharSequence, byte, short, int, long, and their respective wrapper types
@Digits
The element must be within the range of acceptable values for the numeric type.@Negative
The element must be negative@NegativeOrZero
The element must be less than or equal to 0@Positive
The element must be greater than 0@PositiveOrZero
The element must be greater than or equal to 0@Max
.@Min
The size of the element must match the specified size
string
@Email
Mailbox format verification@NotBlack
Verify that string is not empty, empty string""
Also belong to empty@Pattern
String regular validation
Template is a regular
Validator provides annotations for string template regulars. Here is a list of common regular expressions that you can use directly in your project as a constant utility class
public interface ValidatorPattern {
/** * Regular expression: verify the user name * 1. The length is 5-17 * 2. The value consists of uppercase and lowercase letters */
String REGEX_USERNAME = "^ \ w [a zA - Z] {5} in 2 $";
/** * Regular expression: Verify password * The password can contain only 6 to 12 digits, letters, and common symbols. * /
String REGEX_PASSWORD = "^ (? =.*[a-zA-Z])(? =. * [0-9]) [A - Za - z0-9. _ ~! @ # $^ & *] {6, 12} $";
/** * Regular expression: verify mobile phone number */
String REGEX_MOBILE = "^[1][34578]\d{9}$";
/** * Regular expression: verify mailbox */
String REGEX_EMAIL = "^.+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)? \.) +[a-zA-Z]{2,}$";
/** * Regular expressions: verify Chinese characters */
String REGEX_CHINESE = "^[\u4e00-\u9fa5],*$";
/** * Regular expression: verify id */
String REGEX_ID_CARD = "(^\d{18}$)|(^\d{15}$)";
/** * Regular expression: validate URL */
String REGEX_URL = "http(s)? ://([\w-]+\.) +[\w-]+(/[\w- ./?%&=]*)?";
/** * Regular expression: verify the IP address */
String REGEX_IP_ADDR = "(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]? \d)";
/** * the license plate is regular */
String LICENSE_NO = "^[a-z][a-z][a-z0-9]{4,5}[a-z0-9 hang students Hong Kong and Macao]$";
/** * Name verification * 1 to 15 characters * The name supports Spaces and periods (*/)
String NAME = "[\ u4e00 - \ u9fa5 \ u00b7 \ sA - Za - z] {2} 1 $";
/** ** */
String EMOJI = "[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]";
/** ** digital regular */
String NUMBER = "^ [0-9] * $";
/** * n digits */
String N_NUMS = "^\d{n}$";
}
Copy the code
SpringBoot integrate hibernate validator
Introduction of depend on
This will not be repeated, directly copy the dependency information above
Configure the Hibernate-Validator object
Add a Hibernate-Validator object to the configuration class
@Bean
@Primary
public Validator validator(a) {
ValidatorFactory validatorFactory =
Validation
.byProvider(HibernateValidator.class)
.configure()
.addProperty("hibernate.validator.fail_fast"."true")
.buildValidatorFactory();
return validatorFactory.getValidator();
}
Copy the code
With SpringMVC unified exception handling, parameter verification results are processed
Once configured, Spring automatically validates the parameters and throws a BindException that gets the Set
> that we just manually validated. We can handle this exception by leveraging SpringMVC’s ability to unify exception handling
@Slf4j
@RestControllerAdvice
public class BaseExceptionHandler {
/** * Spring Validation automatically validates an invalid parameter **@param e BindException
* @return R<Void>
*/
@ResponseStatus(org.springframework.http.HttpStatus.PAYMENT_REQUIRED)
@ExceptionHandler(BindException.class)
public R<Void> handler(BindException e) {
String defaultMsg = e.getBindingResult().getAllErrors()
.stream()
.map(ObjectError::getDefaultMessage)
.collect(Collectors.joining(":"));
log.warn(defaultMsg);
returnR.of(IRespCode.PARAMETERS_ANOMALIES.getCode(), e.getMessage()); }}Copy the code
Checking with parameters
We only need to mark @Valid or @Validated on the method pass parameter
@PostMapping("register")
public R<Void> register(@Valid @RequestBody Person person) {
// todo
return R.ok();
}
Copy the code
Packet check
So what’s the difference between @Valid and @Validated? “Validated” contains one more attribute than “Valid”. This attribute is used for group verification
public @interface Valid {
}
public @interfaceValidated { Class<? >[] value()default {};
}
Copy the code
What is grouping check?
Attributes are attributes in an entity class that require different attributes in different methods. For example, the Person class has three attributes: a user name, a mailbox, and an age. In the register user interface, the user name, email address, and age cannot be empty, but in the Change user information interface, the user’s age and email address can be empty, but the user name cannot be empty. At this point, we can group the attributes according to the verification requirements.
- Create a new
RegisterGroup
A group, which is just an empty interface, used only to mark the validation requirement
public interface RegisterGroup {}Copy the code
- Group verification requirements
@Data
public class Person {
@NotBlank(message = "username must not be null")
private String username;
@Min(value = 1, message = "age must be >= 1")
@Max(value = 150, message = "age must be < 150")
@NotNull(message = "age must not be null", groups = RegisterGroup.class)
private Integer age;
@Email(message = "email format error")
@NotBlank(message = "email must not be null",groups = RegisterGroup.class)
private String email;
}
Copy the code
- Add a grouping requirement when a method is called
@PostMapping("register")
public R<Void> register(@Validated(value = RegisterGroup.class) @RequestBody Person person) {
// todo
return R.ok();
}
Copy the code
Actually don’t recommend using this way, when I was in the title, also has been marked as “outdated”, because, we can for the two different interfaces to create two different entity class, instead of using the grouping in isolation to check request, because the actual production environment, the group may have very many, this will set a dangerous precedent for readability of our programs, Late developer maintenance is difficult and not friendly to automatically generating API documentation. You only need to know about groupings and they are not recommended for use in project development.