本文目录导读:

在Java中实现数据校验有多种方式,下面我从简单到复杂,整理几个最实用的实现方案。
手动校验(最基本方式)
最直接的方式,适合简单场景或学习理解。
public class User {
private String name;
private int age;
private String email;
// 手动校验方法
public String validate() {
if (name == null || name.trim().isEmpty()) {
return "用户名不能为空";
}
if (name.length() > 50) {
return "用户名长度不能超过50";
}
if (age < 0 || age > 150) {
return "年龄必须在0-150之间";
}
if (email != null && !email.contains("@")) {
return "邮箱格式不正确";
}
return null; // null表示校验通过
}
}
使用Jakarta Bean Validation(JSR 380)
这是Java官方标准的校验框架,最推荐的方式。
添加依赖(Maven)
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.1.Final</version>
</dependency>
定义校验规则
import jakarta.validation.constraints.*;
import jakarta.validation.constraints.Email;
public class User {
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 50, message = "用户名长度在2-50之间")
private String name;
@NotNull(message = "年龄不能为空")
@Min(value = 0, message = "年龄不能小于0")
@Max(value = 150, message = "年龄不能大于150")
private Integer age;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不正确")
private String email;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
}
执行校验
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import java.util.Set;
import jakarta.validation.ConstraintViolation;
public class ValidationDemo {
public static void main(String[] args) {
// 创建校验器
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
// 创建测试对象
User user = new User();
user.setName("张"); // 太短了
user.setAge(200); // 太大了
user.setEmail("abc"); // 不是邮箱
// 执行校验
Set<ConstraintViolation<User>> violations = validator.validate(user);
// 输出错误信息
for (ConstraintViolation<User> violation : violations) {
System.out.println(violation.getMessage());
}
}
}
Spring Boot中的集成校验
如果在Spring Boot项目中使用,可以更加方便。
在Controller中使用
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping
public Result addUser(@Valid @RequestBody User user) {
// 如果校验失败,会自动抛出MethodArgumentNotValidException
// 不会执行到这里
return Result.success("添加成功");
}
}
全局异常处理
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleValidationException(MethodArgumentNotValidException ex) {
// 获取第一个错误信息
String message = ex.getBindingResult()
.getAllErrors()
.get(0)
.getDefaultMessage();
return Result.error(message);
}
}
分组校验
有时同一个对象在不同的场景下需要不同的校验规则。
// 定义分组接口
public interface CreateGroup {}
public interface UpdateGroup {}
public class User {
@NotBlank(message = "ID不能为空", groups = UpdateGroup.class)
private String id;
@NotBlank(message = "用户名不能为空", groups = {CreateGroup.class, UpdateGroup.class})
private String name;
@NotNull(message = "年龄不能为空", groups = CreateGroup.class)
private Integer age;
}
// 使用分组校验
@PostMapping
public Result createUser(@Validated(CreateGroup.class) @RequestBody User user) {
// ...
}
@PutMapping
public Result updateUser(@Validated(UpdateGroup.class) @RequestBody User user) {
// ...
}
自定义校验注解
当内置注解不能满足需求时,可以创建自己的校验注解。
定义注解
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
public @interface Phone {
String message() default "手机号格式不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
实现校验器
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
public class PhoneValidator implements ConstraintValidator<Phone, String> {
@Override
public boolean isValid(String phone, ConstraintValidatorContext context) {
if (phone == null) {
return true; // 允许为空,由@NotNull控制
}
return phone.matches("^1[3-9]\\d{9}$");
}
}
使用自定义注解
public class User {
@Phone(message = "请输入正确的手机号")
private String phone;
}
实用最佳实践
结合Service层校验
@Service
public class UserService {
@Autowired
private Validator validator;
public User createUser(User user) {
// 手动触发校验
Set<ConstraintViolation<User>> violations = validator.validate(user);
if (!violations.isEmpty()) {
String message = violations.iterator().next().getMessage();
throw new ValidationException(message);
}
// 业务处理...
return userRepository.save(user);
}
}
链式校验工具类
public class ValidationUtils {
private static Validator validator;
static {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
public static <T> void validate(T obj) {
Set<ConstraintViolation<T>> violations = validator.validate(obj);
if (!violations.isEmpty()) {
StringBuilder sb = new StringBuilder();
for (ConstraintViolation<T> violation : violations) {
sb.append(violation.getMessage()).append("; ");
}
throw new IllegalArgumentException(sb.toString());
}
}
}
总结与建议
- 小型项目:手动校验够用,但难以维护
- 中型项目:推荐使用Bean Validation注解,清晰明确
- 大型项目:结合分组校验、自定义注解,配合全局异常处理
- Spring项目:利用@Valid + 全局异常处理,开发效率最高
选择哪种方式取决于你的项目规模和团队习惯,对于新项目,建议直接使用Spring Boot + Bean Validation这套组合,既规范又高效。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播