深入浅出 Javax.Validation:校验注解全解析与实战指南
javax.validation
是 Java 提供的一套验证框架,基于 Bean Validation 规范(如 JSR 303 和 JSR 380)。它主要用于对 Java Bean 的属性值进行校验,广泛应用于 Spring、Hibernate 等框架中。
以下是使用 javax.validation
的指南及示例:
1. 引入依赖
如果使用 Maven 项目,可以添加以下依赖:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
如果是 Spring Boot 项目,通常通过 spring-boot-starter-validation
自动引入:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2. 常用注解
注解 | 功能 |
---|---|
@NotNull | 验证值不为 null |
@NotEmpty | 验证字符串不为 null 且长度 > 0 |
@NotBlank | 验证字符串不为 null 且有内容 |
@Size(min, max) | 验证字符串、集合的长度范围 |
@Min | 验证值大于等于指定值 |
@Max | 验证值小于等于指定值 |
@Pattern | 验证值符合正则表达式 |
@Email | 验证邮箱格式 |
@Past / @PastOrPresent | 验证日期在过去或现在 |
@Future / @FutureOrPresent | 验证日期在未来或现在 |
3. 示例代码
3.1 Bean 定义
import javax.validation.constraints.*;
import java.util.Date;
public class UserDTO {
@NotNull(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 20, message = "密码长度必须在 6 到 20 个字符之间")
private String password;
@Email(message = "邮箱格式不正确")
private String email;
@Min(value = 18, message = "年龄必须大于等于 18 岁")
@Max(value = 60, message = "年龄必须小于等于 60 岁")
private Integer age;
@Past(message = "生日必须是过去的日期")
private Date birthday;
// Getter 和 Setter 方法
}
3.2 手动验证
使用 javax.validation.Validator
进行验证。
import javax.validation.*;
import java.util.Set;
public class ValidationExample {
public static void main(String[] args) {
// 创建验证器
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
// 创建待验证对象
UserDTO user = new UserDTO();
user.setUsername(null);
user.setPassword("123");
user.setEmail("invalid-email");
user.setAge(17);
// 执行验证
Set<ConstraintViolation<UserDTO>> violations = validator.validate(user);
// 输出验证结果
for (ConstraintViolation<UserDTO> violation : violations) {
System.out.println(violation.getPropertyPath() + " " + violation.getMessage());
}
}
}
输出:
username 用户名不能为空
password 密码长度必须在 6 到 20 个字符之间
email 邮箱格式不正确
age 年龄必须大于等于 18 岁
3.3 集成 Spring Boot
- 在 Controller 中使用
@Valid
注解。
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping("/user")
@Validated
public class UserController {
@PostMapping("/register")
public String register(@RequestBody @Valid UserDTO userDTO) {
return "用户注册成功!";
}
}
- 自定义全局异常处理器捕获验证错误。
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Map<String, String> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage())
);
return errors;
}
}
示例请求:
POST /user/register
Content-Type: application/json
{
"username": "",
"password": "12345",
"email": "invalid-email",
"age": 17
}
响应:
{
"username": "用户名不能为空",
"password": "密码长度必须在 6 到 20 个字符之间",
"email": "邮箱格式不正确",
"age": "年龄必须大于等于 18 岁"
}
4. 扩展功能
- 自定义校验注解:通过实现
ConstraintValidator
接口,自定义验证逻辑。 - 国际化支持:将验证消息配置在
messages.properties
文件中。 - 分组校验:使用校验组(Groups)进行条件性验证。