1. Introduction
One thing that is very annoying when doing web development is that it needs to verify the front-end input parameters. Basically, each interface needs to verify the parameters, such as some non-empty verification, format verification, etc. If there are fewer parameters, it is still easy to deal with. If there are more parameters, a large number of if-else statements will appear in the code.
Although using this method is simple and direct, there are also disadvantages. First, it reduces development efficiency, because the parameters we need to verify will exist in many places, and there will be repeated verifications in different places. Second, it reduces the readability of the code, because there is too much extra work code in the business code.
So we can use the validator component to perform unnecessary coding operations instead of us. This article is based on the introduction information of validator and also summarizes it based on my actual experience in the project. I hope it can help everyone.
1 What is validator
Bean Validation is a set of annotation-based data verification specifications defined by Java. It has been upgraded from version 1.0 of JSR 303 to version 1.1 of JSR 349, and then to version 2.0 of JSR 380 (2.0 was completed in 2017.08), and has experienced three versions. It should be noted that JSR is just a standard, which stipulates some specifications for verification annotation, but is not implemented, such as @Null, @NotNull, @Pattern, etc., which are located under this package. The hibernate validator is an implementation of this specification and adds some other verification annotations, such as @NotBlank, @NotEmpty, @Length, etc., which are located under this package.
If our project uses Spring Boot, the hibernate validator framework is already integrated in spring-boot-starter-web, so no need to add any other dependencies. If it is not a Spring Boot project, you need to add the following dependencies.
<dependency> <groupId></groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.</version> </dependency>
2. Annotation introduction
1. Validator built-in annotations
annotation | illustrate |
@Null | The annotated element must be null |
@NotNull | The annotated element cannot be null |
@AssertTrue | The annotated element must be true |
@AssertFalse | The annotated element must be false |
@Min(value) | The commented element must be a number, and its value must be greater than or equal to the specified minimum value. |
@Max(value) | The commented element must be a number, and its value must be less than or equal to the specified maximum value. |
@DecimalMin(value) | The commented element must be a number, and its value must be greater than or equal to the specified minimum value. |
@DecimalMax(value) | The commented element must be a number, and its value must be less than or equal to the specified maximum value. |
@Size(max,min) | The size of the annotated element must be within the specified range |
@Digits(integer, fraction) | The annotated element must be a number and its value must be within an acceptable range. |
@Past | The commented element must be a past date |
@Future | The commented element must be a future date |
@Pattern(value) | The annotated element must comply with the specified regular expression |
The extension in hibernate validator defines the following annotations:
annotation | illustrate |
@NotBlank | The annotated element cannot be null and must be greater than 0. It can only be used to annotate strings. |
The annotated element must be an email address | |
@Length(min=,max=) | The commented string must be within the specified range |
@NotEmpty | The annotated element value is not null and not empty, and supports string, collection, map and array types. |
@Range | The annotated element must be within the specified range |
3. Use
It is relatively simple to use, and it is all used with annotation. Specifically, it is divided into single-parameter verification and object parameter verification. Single-parameter verification means that the controller interface receives the front-end value according to single parameters, and does not have an encapsulated object for reception. If there is an encapsulated object, it is object parameter verification.
1 Single parameter verification
Single parameter verification only requires adding annotations before the parameters, as shown below:
public Result deleteUser(@NotNull(message = "id cannot be empty") Long id) { // do something }
But one thing to note is that if you use single parameter verification, the @Validated annotation must be added to the controller class, as shown below:
@RestController @RequestMapping("/user") @Validated // Annotations required for single parameter verificationpublic class UserController { // do something }
2 Object parameter verification
When using object parameter verification, you need to add annotation to the object's verification properties first, and then add an @Validated annotation before the object parameters of the Controller method, as shown below:
public Result addUser(@Validated UserAO userAo) { // do something } public class UserAO { @NotBlank private String name; @NotNull private Integer age; …… }
Annotation grouping
In the object parameter verification scenario, there is a special scenario where the same parameter object has different verification rules in different scenarios. For example, when creating an object, you do not need to pass in the id field (the id field is the primary key, generated by the system, and not specified by the user), but when modifying the object, you must pass in the id field. In such a scenario, annotations need to be grouped.
1) The component has a default group, so we can create another group as shown below:
public interface UpdateAction { }
2) To the attributes that need to be checked in the parameter class, add groups attributes to the annotation:
public class UserAO { @NotNull(groups = , message = "id cannot be empty") private Long id; @NotBlank private String name; @NotNull private Integer age; …… }
As shown above, it means that the id field is only checked under the UpdateAction group, and the name field and the age field will be checked by default.
Then in the controller method, just specify which scenario in the @Validated annotation. If there is no specification, it means adoption. If other groups are used, the specification needs to be displayed. The following code indicates that parameters are checked according to the default in the addUser() interface, and parameters are checked according to the default in the updateUser() interface according to the default in the updateUser() interface.
public Result addUser(@Validated UserAO userAo) { // do something }
public Result updateUser(@Validated({, }) UserAO userAo) { // do something }
Object nesting
If there is an object attribute nested in the parameter object that needs to be checked, and the nested object attribute also needs to be checked, then you need to add the @Valid annotation to the object attribute.
public class UserAO { @NotNull(groups = , message = "id cannot be empty") private Long id; @NotBlank private String name; @NotNull private Integer age; @Valid private Phone phone; …… } public class Phone { @NotBlank private String operatorType; @NotBlank private String phoneNum; }
3. Capture of error messages
An exception will be thrown after the parameter verification fails. We only need to catch the failed exception of the parameter verification in the global exception handling class, and then add the error message to the return value. The method of catching exceptions is as follows. The return value Result is a custom return value class our system has.
@RestControllerAdvice(basePackages= {"",""}) public class GlobalExceptionHandler { @ExceptionHandler(value = {}) Result handleException(Throwable e, HttpServletRequest request){ // Exception handling } }
It should be noted that if the exception thrown by missing parameters is MissingServletRequestParameterException, the exception thrown after the single parameter verification fails is ConstraintViolationException, the exception thrown after the object parameter verification failed is BindException, and the exception thrown after the object parameter verification failed is MethodArgumentNotValidException. Different exception objects have different structures, so the extraction method of exception messages is also different. As shown in the figure below:
1)MissingServletRequestParameterException
if(e instanceof MissingServletRequestParameterException){ Result result = (ErrorCodeEnum.PARAM_ILLEGAL); String msg = ("Missing parameters{0}", ((MissingServletRequestParameterException) e).getParameterName()); (msg); return result; }
2) ConstraintViolationException exception
if(e instanceof ConstraintViolationException){ // Single parameter verification abnormality Result result = (ErrorCodeEnum.PARAM_ILLEGAL); Set<ConstraintViolation<?>> sets = ((ConstraintViolationException) e).getConstraintViolations(); if((sets)){ StringBuilder sb = new StringBuilder(); (error -> { if (error instanceof FieldError) { (((FieldError)error).getField()).append(":"); } (()).append(";"); }); String msg = (); msg = (msg, 0, () -1); (msg); } return result; }
3) BindException exception
if (e instanceof BindException){ // The object parameter verification abnormality of get request Result result = (ErrorCodeEnum.PARAM_ILLEGAL); List<ObjectError> errors = ((BindException) e).getBindingResult().getAllErrors(); String msg = getValidExceptionMsg(errors); if ((msg)){ (msg); } return result; }
private String getValidExceptionMsg(List<ObjectError> errors) { if((errors)){ StringBuilder sb = new StringBuilder(); (error -> { if (error instanceof FieldError) { (((FieldError)error).getField()).append(":"); } (()).append(";"); }); String msg = (); msg = (msg, 0, () -1); return msg; } return null; }
4) MethodArgumentNotValidException
if (e instanceof MethodArgumentNotValidException){ // The object parameter verification abnormality requested by post Result result = (ErrorCodeEnum.PARAM_ILLEGAL); List<ObjectError> errors = ((MethodArgumentNotValidException) e).getBindingResult().getAllErrors(); String msg = getValidExceptionMsg(errors); if ((msg)){ (msg); } return result; }
Summarize
This is the article about Spring Boot parameter verification and group verification. For more relevant Spring Boot parameter verification and group verification, please search for my previous articles or continue browsing the related articles below. I hope you will support me in the future!