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
:验证元素的大小,如字符串长度、集合大小等,可指定min
和max
属性。@Min
和@Max
:分别用于验证数字类型(如int
、long
等)的最小值和最大值。@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 开发到数据处理等诸多场景。