I. Background
Without going into the importance of parameter legitimacy validation, even if the front-end does basic validation of the parameters, the back-end still needs to validate them as well to prevent non-compliant data from going directly to the server, and if it's not intercepted, theSevere cases can even cause an outright system crash!
In this paper, we combine our practical experience in using the projectThe main focus is practical, to do a summary of the data legitimacy verificationIf you don't know it, you can learn it, and at the same time, you can immediately practice it on your projects.
Here we have a few examples to demonstrate how to determine whether the parameter is legal or not, without further ado, directly jack up!
II. Assertion Validation
For validating the legitimacy of parameters, it was initially simpler to customize an exception class.
public class CommonException extends RuntimeException {
private Integer code;
public Integer getCode() {
return code;
}
public CommonException(String message) {
super(message);
= 500;
}
public CommonException(Integer code, String message) {
super(message);
= code;
}
}
When a parameter is checked to be illegal, an exception is thrown directly!
@RestController
public class HelloController {
@RequestMapping("/upload")
public void upload(MultipartFile file) {
if (file == null) {
throw new CommonException("Please choose to upload a file!");
}
//.....
}
}
Finally, write a unified exception blocker that underpins the logic that throws exceptions.
This approach is simpler and more intuitive.If the current parameter has to determine both if it is null and if the length exceeds the maximum limit, the code is bloated and has poor reusability!
So, the programmers thought of a more elegant and code-saving way to create an assertion class tool class, specifically used to determine the legitimacy of the parameter, and if it is not legitimate to throw an exception, the example is as follows:
/**
* Assertion Tool Class
*/
public abstract class LocalAssert {
public static void isTrue(boolean expression, String message) throws CommonException {
if (!expression) {
throw new CommonException(message);
}
}
public static void isStringEmpty(String param, String message) throws CommonException{
if((param)) {
throw new CommonException(message);
}
}
public static void isObjectEmpty(Object object, String message) throws CommonException {
if (object == null) {
throw new CommonException(message);
}
}
public static void isCollectionEmpty(Collection coll, String message) throws CommonException {
if (coll == null || (() == 0)) {
throw new CommonException(message);
}
}
}
When we need to validate the parameters, we can do it directly through this class, the example is as follows:
@RestController
public class HelloController {
@RequestMapping("/save")
public void save(String name, String email) {
(name, "User name cannot be empty!");
(email, "Mailbox cannot be empty!");
//.....
}
}
Compared to the above implementation, this processing logic, the code is significantly more concise!
There are many more tool classes like this, such asspring
also provides a function calledAssert
The assertion toolkit class of the
III. Annotation Validation
Here we are going to introduce another more concise parameter validation logic, using annotations to validate the legitimacy of the data, not only will the code become very concise, but also very pleasing to read!
Using the Spring Boot project as an example, let's take a look at how this is practiced.
3.1 Adding dependency packages
first inintroduced in
spring-boot-starter-web
Dependency packages are sufficient, and it will automatically type the annotation validation related dependency packages into the project!
<!-- spring boot web -->
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
3.2. Write annotations to verify the request object
Then create an entityUser
which is used to encapsulate the request parameters for user registration.and add the corresponding annotation validation rules to the parameter properties!
import ;
import ;
import ;
public class User {
@NotBlank(message = "User name can't be empty!")
private String userName;
@Email(message = "Mailbox format is incorrect!")
@NotBlank(message = "Mailbox cannot be empty!")
private String email;
@NotBlank(message = "Password cannot be empty!")
@Size(min = 8, max = 16,message = "Please enter a password with a length between 8 and 16 digits")
private String userPwd;
@NotBlank(message = "Confirm password cannot be empty!")
private String confirmPwd;
// set, get methods, etc...
}
3.3 Writing the request interface
existweb
layer creates aregister()
Register the interface method and also add the request parameters to the@Valid
annotation, an example is shown below:
import ;
@RestController
public class UserController {
@RequestMapping("/register")
public ResultMsg register(@RequestBody @Valid User user){
if(!().equals(())){
throw new CommonException(4001, "Confirmation password is not the same as the password,please confirm!");
}
//business processing...
return ();
}
}
3.4. Write a global exception handler
Finally customize an exception global handler for exception logic as follows:
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger LOGGER = ();
/**
* interdictionControllerLayer Exception
* @param e
* @return
*/
@ExceptionHandler(value = {})
@ResponseBody
public Object exceptionHandler(HttpServletRequest request, Exception e){
("【统一异常interdiction】request address:{}, error message:{}", (), ());
// Annotation validation of thrown exceptions
if(e instanceof MethodArgumentNotValidException){
// 获取error message
String error = ((MethodArgumentNotValidException) e).getBindingResult().getFieldError().getDefaultMessage();
return (500, error);
}
// Customizing thrown exceptions
if(e instanceof CommonException){
return (((CommonException) e).getCode(), ());
}
return (999, ());
}
}
Uniform Response Object (URO)ResultMsg
, as follows:
public class ResultMsg<T> {
/**status code**/
private int code;
/**Description of results**/
private String message;
/**result set**/
private T data;
/**timestamp**/
private long timestamp;
// set、getmethodologies...
}
3.5 Service testing
To start the project, use thepostman
Let's verify that the code is correct and see how it works.
- Test if a field is empty
- Test the legitimacy of the mailbox
- Test that the password length meets the requirements
- Test password is the same as the confirmation password
It can be seen that the validation results are as expected!
IV. Custom annotation validation
In fact, those familiar with the SpringMVC source code may know that Spring Boot has a built-inhibernate-validator
The validation component, which was used above to accomplish the validation of the annotations on the incoming parameters at the time of the request.
By default, the dependency package already gives us a very large number of checksum annotations as follows!
- JSR-provided validation annotations!
- Validation annotations provided by Hibernate Validator
But some cases, such as the parameter gender, may require us to manually validate it ourselves.
For this case, we can also customize an annotation to complete the parameter verification, but also facilitate further understanding of the principle of annotation validation.
Custom annotation validation, implemented as follows!
First, create aSex
Annotation.
@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = )
@Documented
public @interface Sex {
String message() default "Gender values are not optional";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Then, create aSexValidator
class, which implements a class from theConstraintValidator
connector
public class SexValidator implements ConstraintValidator<Sex, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
Set<String> sexSet = new HashSet<String>();
("male");
("women");
return (value);
}
}
Finally, in theUser
Add a gender parameter on the entity class and use a custom annotation for validation!
public class User {
@NotBlank(message = "User name can't be empty!")
private String userName;
@Email(message = "Mailbox format is incorrect!")
@NotBlank(message = "Mailbox cannot be empty!")
private String email;
@NotBlank(message = "Password cannot be empty!")
@Size(min = 8, max = 16,message = "Please enter a password with a length between 8 and 16 digits")
private String userPwd;
/**
* Customized annotation checksum
*/
@Sex(message = "The gender was entered incorrectly!")
private String sex;
// set, get methods, etc...
}
Start the service, re-request it, and run it as follows:
The results were consistent with expectations!
V. Summary
Parameter validation, which is used very frequently in development, and how to do it elegantly and make the code more readable, is a goal that industry gurus have been pursuing!
This article is mainly around the realization of the parameters in Spring Boot unified validation of the relevant knowledge summary and introduction, if there is a description of the wrong place, welcome to leave a message of support.
Sample code:spring-boot-example-valid