Validation快速上手

在 Java 开发中,Validation 通常指的是数据验证,即对输入的数据进行合法性检查,确保数据符合业务规则和预期。Spring 框架集成了 Java Bean Validation API(JSR 380,通常称为 Bean Validation 2.0,其实现如 Hibernate Validator),提供了强大且便捷的验证功能。以下为你详细介绍:

核心概念与注解

  • 注解驱动的验证:Bean Validation 定义了一系列注解,可直接应用于 Java Bean 的字段、方法参数、返回值等,实现声明式验证。常见注解如下:
    • @NotNull:验证注解元素值不为 null,但可以为空字符串。
    • @NotEmpty:验证注解元素值不为 null 且不为空(字符串长度不为 0、集合大小不为 0 等)。
    • @NotBlank:专门用于字符串,验证字符串不为 null 且去除首尾空格后长度不为 0。
    • @Size:验证元素的大小,如字符串长度、集合大小等,可指定 minmax 属性。
    • @Min@Max:分别用于验证数字类型(如 intlong 等)的最小值和最大值。
    • @Pattern:使用正则表达式验证字符串格式。
    • @Email:验证字符串是否为有效的电子邮件地址。

Spring 中使用 Validation

1. 添加依赖

如果你使用的是 Spring Boot 项目,在 pom.xml 中添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2. 创建需要验证的 Java Bean

import jakarta.validation.constraints.*;

public class User {
    @NotBlank(message = "用户名不能为空")
    private String username;

    @Size(min = 6, max = 20, message = "密码长度必须在 6 到 20 之间")
    private String password;

    @Email(message = "请输入有效的电子邮件地址")
    private String email;

    // 构造函数、Getter 和 Setter 方法
    public User() {}

    public User(String username, String password, String email) {
        this.username = username;
        this.password = password;
        this.email = email;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

3. 在控制器中使用验证

import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
    @PostMapping("/users")
    public ResponseEntity<String> createUser(@Valid @RequestBody User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return new ResponseEntity<>(bindingResult.getAllErrors().get(0).getDefaultMessage(), HttpStatus.BAD_REQUEST);
        }
        // 处理用户创建逻辑
        return new ResponseEntity<>("用户创建成功", HttpStatus.CREATED);
    }
}

在上述代码中:

  • @Valid 注解用于触发对 User 对象的验证。
  • BindingResult 用于存储验证结果,可通过 hasErrors() 方法判断是否存在验证错误。

4. 自定义验证注解

除了使用内置的验证注解,还可以自定义验证注解。步骤如下:

  • 定义注解:
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CustomValidator.class)
@Documented
public @interface CustomValidation {
    String message() default "自定义验证失败";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
  • 实现验证器:
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

public class CustomValidator implements ConstraintValidator<CustomValidation, String> {
    @Override
    public void initialize(CustomValidation constraintAnnotation) {
        // 初始化逻辑
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        // 自定义验证逻辑
        return value != null && value.startsWith("custom");
    }
}
  • 使用自定义注解:
public class MyClass {
    @CustomValidation
    private String customField;

    // Getter 和 Setter 方法
}

分组验证

在某些情况下,需要根据不同的业务场景对同一对象进行不同的验证。可以使用分组验证来实现,步骤如下:

  • 定义分组接口:
public interface GroupA {}
public interface GroupB {}
  • 在注解中指定分组:
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.groups.Default;

public class User {
    @NotBlank(message = "用户名不能为空", groups = {Default.class, GroupA.class})
    private String username;

    // 其他字段和方法
}
  • 在控制器中指定分组进行验证:
import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
    @PostMapping("/users")
    public ResponseEntity<String> createUser(@Valid(groups = GroupA.class) @RequestBody User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return new ResponseEntity<>(bindingResult.getAllErrors().get(0).getDefaultMessage(), HttpStatus.BAD_REQUEST);
        }
        // 处理用户创建逻辑
        return new ResponseEntity<>("用户创建成功", HttpStatus.CREATED);
    }
}

验证消息国际化

可以通过配置资源文件实现验证消息的国际化。在 src/main/resources 目录下创建 ValidationMessages.properties(默认语言)和 ValidationMessages_zh_CN.properties(中文语言)等文件,在文件中定义验证消息:

  • ValidationMessages.properties
user.username.notblank = Username cannot be blank
  • ValidationMessages_zh_CN.properties
user.username.notblank = 用户名不能为空

在注解中引用消息键:

import jakarta.validation.constraints.NotBlank;

public class User {
    @NotBlank(message = "{user.username.notblank}")
    private String username;

    // 其他字段和方法
}

通过以上介绍,你可以全面了解 Java 中的数据验证机制,以及如何在 Spring 项目中使用 Bean Validation 进行数据验证。

Spring 文章被收录于专栏

Spring 生态是以 Spring Framework 为核心,衍生出的一系列相互关联、功能互补的技术和工具集合,用于简化企业级应用开发,覆盖从单体应用到分布式微服务、从 Web 开发到数据处理等诸多场景。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务