Tech Stack:
spring boot 2.3.
hibernate-validator
Project source code at the end of the article
catalogs
summarize
Project dependencies
Global Exception Handling Class
Basic parameter calibration
entity class
control type
beta (software)
Nested parameter validation
entity class
control type
beta (software)
Grouping parameter validation
interface class
entity class
control type
beta (software)
Difference between @Valid and @Validated
summarize
@Validation is a set of annotations that help us to continue data validation of transmitted parameters, which can be easily accomplished by configuring Validation to constrain the data.
@Validated acts on classes, methods and parameters
@Target({, , }) @Retention() @Documented public @interface Validated { Class<?>[] value() default {}; }
error status code
The recommended response code to return is 400 bad request.
Meaning of all parameter annotations
Project dependencies
Maven dependency coordinates:
Note: In the demo project all entity classes are in package ENTITY and the control layer is in package CONTROLLER.
Global Exception Handling Class
Note: Without exception handling, the default exception message for the @Validated annotation is as follows (example):
2020-09-05 21:48:38.106 WARN 9796 --- [nio-8080-exec-3] . : Resolved [: Validation failed for argument [0] in public .validatedDemo1(): [Field error in object 'useDto' on field 'username': rejected value [null]; codes [,,,NotBlank]; arguments [: codes [,username]; arguments []; default message [username]]; default message [User name cannot be empty!]] ]
So we make a global exception handling class here to handle exceptions thrown when parameter validation fails, along with logging output.
package ;
import ;
import ;
import ;
import .slf4j.Slf4j;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/**
* @author He Changjie on 2020/9/5
*/
@Slf4j
@ControllerAdvice
public class ValidatedExceptionHandler {
/**
* deal with@ValidatedParameter validation failure exception
* @param exception exception class
* @return responsive
*/
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler()
public Result exceptionHandler(MethodArgumentNotValidException exception){
BindingResult result = ();
StringBuilder stringBuilder = new StringBuilder();
if (()) {
List<ObjectError> errors = ();
if (errors != null) {
(p -> {
FieldError fieldError = (FieldError) p;
("Bad Request Parameters: dto entity [{}],field [{}],message [{}]",(), (), ());
(());
});
}
}
return (());
}
}
Basic parameter calibration
entity class
package ;
import ;
import ;
import .*;
/**
* user entity
* Data Transfer Objects
* @author He Changjie on 2020/9/5
*/
@Data
public class User1Dto {
/**
* user ID
*/
@NotBlank(message = "user ID不能为空!")
private String username;
/**
* distinguishing between the sexes
*/
@NotBlank(message = "distinguishing between the sexes不能为空!")
private String gender;
/**
* (a person's) age
*/
@Min(value = 1, message = "(a person's) age有误!")
@Max(value = 120, message = "(a person's) age有误!")
private int age;
/**
* address
*/
@NotBlank(message = "address不能为空!")
private String address;
/**
* inbox
*/
@Email(message = "inbox有误!")
private String email;
/**
* mobile telephone number
*/
@Pattern(regexp = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$",message = "mobile telephone number有误!")
private String mobile;
}
control type
package ;
import .Use1Dto;
import ;
import ;
import ;
import ;
import ;
/**
* @author He Changjie on 2020/9/5
*/
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {
@PostMapping("/insert")
public String validatedDemo1(@Validated @RequestBody Use1Dto use1Dto){
(use1Dto);
return "success";
}
}
beta (software)
1. Parameter calibration passed:
2. Parameter calibration failed:
Nested parameter validation
Validate other collections of objects in the entity that need to be validated or other objects
entity class
package ;
import ;
import ;
import ;
import ;
import ;
/**
* The queue entity
* Data transfer object
* @author He Changjie on 2020/9/5
*/
@Data
public class Team1Dto {
/**
* Team name
*/
@NotBlank(message = "Team name cannot be empty!")
private String name;
/**
* Team Personnel
*/
@NotNull(message = "Team personnel cannot be null!")
@Valid
private List<User1Dto> userList.
/**
* The person in charge of the team.
*/
@NotNull(message = "Team leader cannot be null!")
@Valid
private User1Dto user;
}
control type
package ;
import ;
import .Team1Dto;
import .Use1Dto;
import ;
import ;
import ;
import ;
import ;
import ;
/**
* @author He Changjie on 2020/9/5
*/
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {
@PostMapping("/insert")
public Result validatedDemo1(@Validated @RequestBody Use1Dto use1Dto){
return (use1Dto);
}
@PostMapping("/insert2")
public Result validatedDemo2(@Validated @RequestBody Team1Dto team1Dto){
return (team1Dto);
}
}
test (machinery etc)
1. Parameter validation is passed:
2. Parameter validation failed:
Grouping parameter validation
Distribute different checksum rules to different groups and specify different checksum rules when using the
interface class
package ;
/**
* calibration group1
* @author He Changjie on 2020/9/5
*/
public interface Group1 {
}
package ;
/**
* calibration group2
* @author He Changjie on 2020/9/5
*/
public interface Group2 {
}
entity class
package ;
import .Group1;
import .Group2;
import ;
import .*;
/**
* @author He Changjie on 2020/9/5
*/
@Data
public class User2Dto {
/**
* user ID
*/
@NotBlank(message = "user ID不能为空!", groups = {})
private String username;
/**
* distinguishing between the sexes
*/
@NotBlank(message = "distinguishing between the sexes不能为空!")
private String gender;
/**
* (a person's) age
*/
@Min(value = 1, message = "(a person's) age有误!", groups = {})
@Max(value = 120, message = "(a person's) age有误!", groups = {})
private int age;
/**
* address
*/
@NotBlank(message = "address不能为空!")
private String address;
/**
* inbox
*/
@Email(message = "inbox有误!", groups = {})
private String email;
/**
* mobile telephone number
*/
@Pattern(regexp = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$",message = "mobile telephone number有误!", groups = {})
private String mobile;
}
control type
package ;
import ;
import .Team1Dto;
import .User1Dto;
import .User2Dto;
import .Group1;
import .Group2;
import ;
import ;
import ;
import ;
import ;
import ;
/**
* @author He Changjie on 2020/9/5
*/
@RestController
@RequestMapping("/api/v1")
public class Demo1Controller {
@PostMapping("/insert")
public Result validatedDemo1(@Validated @RequestBody User1Dto user1Dto){
return (user1Dto);
}
@PostMapping("/insert2")
public Result validatedDemo2(@Validated @RequestBody Team1Dto team1Dto){
return (team1Dto);
}
@PostMapping("/insert3")
public Result validatedDemo3(@Validated @RequestBody User2Dto user2Dto){
return (user2Dto);
}
@PostMapping("/insert4")
public Result validatedDemo4(@Validated() @RequestBody User2Dto user2Dto){
return (user2Dto);
}
@PostMapping("/insert5")
public Result validatedDemo5(@Validated() @RequestBody User2Dto user2Dto){
return (user2Dto);
}
}
beta (software)
1. Passed without group calibration:
2. The ungrouped parameter calibration does not pass:
3. Subgroup 1 parameter calibration passed
4. Subgroup 1 parameter calibration failed
5. Subgroup 2 parameter calibration adopted
6. Subgroup 2 parameter calibration failed
7. Using the default grouping, the parameter checksum passes:
Description: Test the control layer/insert3 interface after adjusting it as follows
@PostMapping("/insert3")
public Result validatedDemo3(@Validated() @RequestBody User2Dto user2Dto){
return (user2Dto);
}
for interface classes contained in Validated dependencies, not custom interface classes
8. Using the default grouping, the parameter check does not pass:
Note: Same operation as point 7
Difference between @Valid and @Validated
Analyzing through the source code:
@Target({, , , , ElementType.TYPE_USE})
@Retention()
@Documented
public @interface Valid {
}
@Target({, , })
@Retention()
@Documented
public @interface Validated {
Class<?>[] value() default {};
}
@Valid: there is no grouping feature.
@Valid: can be used on methods, constructors, method parameters and member properties (fields)
@Validated: provides a grouping function that allows different validation mechanisms to be used according to different groups during inbound validation
@Validated: can be used on types, methods and method parameters. But cannot be used on member properties (fields)
Whether or not both can be used on member attributes (fields) has a direct impact on whether or not nested validation can be provided.
Code Cloud Address:/jie_harris/
It's not easy to hand-code, so please cite the source for reprinting
Thank you!