How does Spring Boot use the @Validated annotation for data validation

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 @Validatedannotations . This article will introduce how to use @Validatedannotations for data validation, and provide some sample codes to help you better understand.

insert image description here

Introduction to @Validated

@Validatedis an annotation in Spring Boot for validating method parameters, request parameters and request bodies. It javax.validationis @Validan extension of the annotations in , but provides more features, such as group validation and parameter validation order.

When using @Validatedannotations , spring-boot-starter-validationa dependency needs to be added to the Spring Boot application in order to use the validator. A validator is an implementation in javax.validationthe package that validates objects and properties.

Use @Validated on method parameters

When using @Validatedannotations , 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, @Validatedthe annotation is used to @RequestBodyverify Userwhether the object passed in the annotation is valid. If Userthe object is invalid, MethodArgumentNotValidExceptionan exception will be thrown. If you need a custom exception handler to handle this exception, you can use @ExceptionHandlerannotations .

You can also use BindingResultthe 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, BindingResultthe 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 @Validatedannotations to validate request parameters. In this example, we'll use @RequestParamannotations to get request parameters:

@GetMapping("/users")
public User getUser(@RequestParam("id") @Min(1) Long id) {
    // 处理获取用户逻辑
}

In the above code, @Validatedthe annotation is used to @RequestParamverify idwhether the parameters passed in the annotation are valid. If idinvalid , MethodArgumentNotValidExceptiona exception will be thrown.

Use @Validated in the request body

You can use @Validatedannotations to validate objects in the request body. In this example, we will use @RequestBodyannotations to get the request body:

@PostMapping("/users")
public User createUser(@RequestBody @Validated User user) {
    // 处理用户创建逻辑
}

In the above code, @Validatedthe annotation is used to @RequestBodyverify Userwhether the object passed in the annotation is valid. If Userthe object is invalid, MethodArgumentNotValidExceptionan 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.Defaultannotations for default groups and custom annotations to define other groups. In the example below, we Createdefine Updatetwo 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.nameemailgroupsnameCreateemailCreateUpdate

To specify a group when using @Validatedan annotation , pass the group as the second argument to @Validatedthe annotation. In the example below, we pass Createthe group to @Validatedthe annotation:

@PostMapping("/users")
public User createUser(@RequestBody @Validated(Create.class) User user) {
    // 处理用户创建逻辑
}

In the code above, @Validatedthe annotation only validates the annotations in Createthe group , and thus only namethe 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.ConstraintValidatorthe 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. ConstraintValidatorThe 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 valuethat 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, trueelse 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 @UniqueUsernameannotation :

@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 @Constraintannotations to associate UniqueUsernameValidatorwith @UniqueUsernameannotations . We also define default error messages, and groupsand payloadattributes that can be used for grouping and metadata.

Now, we can use @UniqueUsernamethe annotation :

public class User {
    @NotNull
    @UniqueUsername
    private String username;

    // getters/setters omitted
}

In the above code, usernamewe have used @UniqueUsernamethe 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 @Validatedannotations for data validation. We also covered how to use @Validatedannotations , and how to define grouping and custom validators. By using @Validatedannotations , you can easily validate data in your application and ensure data integrity and consistency.

Guess you like

Origin blog.csdn.net/2302_77835532/article/details/131341704