Java数据验证:库与工具完整指南
数据验证是开发可靠Java应用程序的关键方面之一。没有它,就无法保证输入数据的正确性,防止用户输入错误或与外部系统集成时出错。在本文中,我们将从标准的Bean Validation开始,到现代解决方案,分析Java中数据验证的主要库和方法。
为什么需要验证?
验证可以:
- 在早期阶段过滤掉不正确的数据
- 减少业务逻辑中的错误数量
- 提高应用程序安全性(防止SQL注入、XSS)
- 改善用户体验(清晰的错误消息)
1. Jakarta Bean Validation(原JSR 380)
这是Java中使用注解验证对象的标准。主要实现是Hibernate Validator。从Jakarta EE 9和Java SE 8+开始支持。
主要注解
@NotNull— 值不能为null@NotEmpty— 字符串、集合或数组不能为空@Size(min, max)— 限制字符串长度或集合大小@Pattern(regexp)— 根据正则表达式检查@Email— 有效的电子邮件地址@Min/@Max— 数值边界
使用示例
import jakarta.validation.constraints.*;
public class User { @NotNull(message = "名称不能为null") @Size(min = 2, max = 50, message = "名称长度必须在2到50个字符之间") private String name;
@Email(message = "电子邮件格式不正确") @NotEmpty(message = "电子邮件为必填项") private String email;
@Min(value = 18, message = "年龄必须至少为18") @Max(value = 120, message = "年龄不能超过120") private int age;
// getters and setters}运行验证
import jakarta.validation.*;import java.util.Set;
public class ValidationExample { public static void main(String[] args) { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator();
User user = new User(); user.setName("A"); // 名称太短 user.setEmail("invalid-email"); user.setAge(15); // 小于18
Set<ConstraintViolation<User>> violations = validator.validate(user); for (ConstraintViolation<User> violation : violations) { System.out.println(violation.getMessage()); } }}2. Hibernate Validator — 扩展实现
Hibernate Validator是Bean Validation的参考实现。它增加了额外的功能:
- 自定义验证注解
- 验证组(用于不同场景)
- 支持
@ScriptAssert进行复杂检查
自定义注解示例
import jakarta.validation.*;import java.lang.annotation.*;
@Target({ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = PasswordValidator.class)public @interface ValidPassword { String message() default "密码必须包含字母和数字"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {};}public class PasswordValidator implements ConstraintValidator<ValidPassword, String> { @Override public boolean isValid(String value, ConstraintValidatorContext context) { if (value == null) return false; return value.matc