How does Spring Boot use the @Validated annotation for data validation
Data validation is often unavoidable when developing applications. Spring Boot provides many options to validate data in an application, one of which is to use @Validated
annotations . This article will introduce how to use @Validated
annotations for data validation, and provide some sample codes to help you better understand.
Introduction to @Validated
@Validated
is an annotation in Spring Boot for validating method parameters, request parameters and request bodies. It javax.validation
is @Valid
an extension of the annotations in , but provides more features, such as group validation and parameter validation order.
When using @Validated
annotations , spring-boot-starter-validation
a dependency needs to be added to the Spring Boot application in order to use the validator. A validator is an implementation in javax.validation
the package that validates objects and properties.
Use @Validated on method parameters
When using @Validated
annotations , they can be placed on method parameters to verify the validity of method parameters.
@PostMapping("/users")
public User createUser(@RequestBody @Validated User user) {
// 处理用户创建逻辑
}
In the above code, @Validated
the annotation is used to @RequestBody
verify User
whether the object passed in the annotation is valid. If User
the object is invalid, MethodArgumentNotValidException
an exception will be thrown. If you need a custom exception handler to handle this exception, you can use @ExceptionHandler
annotations .
You can also use BindingResult
the object to get validation results:
@PostMapping("/users")
public User createUser(@RequestBody @Validated User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
// 处理验证错误
}
// 处理用户创建逻辑
}
In the above code, if there are any validation errors, BindingResult
the object will contain those errors. You can use hasErrors()
the method to check for errors, and getFieldErrors()
the and getGlobalErrors()
methods to get a list of errors.
Use @Validated on request parameters
You can use @Validated
annotations to validate request parameters. In this example, we'll use @RequestParam
annotations to get request parameters:
@GetMapping("/users")
public User getUser(@RequestParam("id") @Min(1) Long id) {
// 处理获取用户逻辑
}
In the above code, @Validated
the annotation is used to @RequestParam
verify id
whether the parameters passed in the annotation are valid. If id
invalid , MethodArgumentNotValidException
a exception will be thrown.
Use @Validated in the request body
You can use @Validated
annotations to validate objects in the request body. In this example, we will use @RequestBody
annotations to get the request body:
@PostMapping("/users")
public User createUser(@RequestBody @Validated User user) {
// 处理用户创建逻辑
}
In the above code, @Validated
the annotation is used to @RequestBody
verify User
whether the object passed in the annotation is valid. If User
the object is invalid, MethodArgumentNotValidException
an exception will be thrown.
check group
By default, the validator will validate all annotations on the object. However, sometimes you may want to separate validations into several groups. For example, you might need to validate all properties when creating an object, but only validate required properties when updating an object.
To define groupings, use @javax.validation.groups.Default
annotations for default groups and custom annotations to define other groups. In the example below, we Create
define Update
two groups, and :
public interface Create {}
public interface Update {}
public class User {
@NotNull(groups = Create.class)
private String name;
@NotNull(groups = {Create.class, Update.class})
private String email;
// getters/setters omitted
}
In the code above, the and@NotNull
attributes are marked , but their attributes are different. The attribute is only validated in the group , while the attribute is validated in the and groups.name
email
groups
name
Create
email
Create
Update
To specify a group when using @Validated
an annotation , pass the group as the second argument to @Validated
the annotation. In the example below, we pass Create
the group to @Validated
the annotation:
@PostMapping("/users")
public User createUser(@RequestBody @Validated(Create.class) User user) {
// 处理用户创建逻辑
}
In the code above, @Validated
the annotation only validates the annotations in Create
the group , and thus only name
the attribute.
Define a custom validator
Sometimes, the built-in validators don't meet your needs. For example, you might need to verify that usernames are unique, which requires access to a database. In this case you can define your own validator.
To define a custom validator, create a class that implements javax.validation.ConstraintValidator
the interface . In the following example, we'll create a validator that verifies that usernames are unique:
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {
@Autowired
private UserRepository userRepository;
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
return userRepository.findByUsername(value) == null;
}
}
In the code above, the interfaceUniqueUsernameValidator
is implemented , which has two generic parameters. ConstraintValidator
The first parameter is the type of the custom annotation, and the second parameter is the type of the value to be validated.
In isValid()
the method , we verify value
that is null
, and if not, we check to see if a user with the same username already exists in the database. Returns if not present, true
else returns false
.
After defining a custom validator, we need to create a custom annotation to use in the code. In the example below we will create an @UniqueUsername
annotation :
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {UniqueUsernameValidator.class})
public @interface UniqueUsername {
String message() default "用户名已存在";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
In the code above, we use @Constraint
annotations to associate UniqueUsernameValidator
with @UniqueUsername
annotations . We also define default error messages, and groups
and payload
attributes that can be used for grouping and metadata.
Now, we can use @UniqueUsername
the annotation :
public class User {
@NotNull
@UniqueUsername
private String username;
// getters/setters omitted
}
In the above code, username
we have used @UniqueUsername
the annotation on the attribute, which will call the custom validator we defined to verify that the username is unique.
Summarize
In this article, we introduced how to use @Validated
annotations for data validation. We also covered how to use @Validated
annotations , and how to define grouping and custom validators. By using @Validated
annotations , you can easily validate data in your application and ensure data integrity and consistency.