spring-boot-starter-validation字段数据校验

validation

概述

spring-boot-starter-validation 是 Spring Boot 官方提供的用于数据校验的启动器,它基于 Bean Validation API (JSR 380) 标准,并默认使用 Hibernate Validator 作为其实现。这个框架能让你通过声明式的注解,轻松地对控制器接收的参数、服务层的方法参数以及任何 Java Bean 进行校验,确保数据的完整性和有效性。

添加依赖

java 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

常用注解

注解 适用类型 说明 示例
基础校验
@NotNull 任意类型 校验字段值不能为 null @NotNull(message = "ID不能为空")
@NotEmpty String/Collection/Array/Map 校验对象不能为 null 且长度/大小必须大于 0 @NotEmpty(message = "列表不能为空")
@NotBlank String 校验字符串不能为 null 且去首尾空格后长度大于 0 @NotBlank(message = "名称不能为空")
@Null 任意类型 (新增) 校验字段值必须为 null @Null(message = "创建时ID必须为空")
@Size String/Collection/Array/Map 校验长度或大小是否在指定范围内 @Size(min=6, max=20, message="长度需在6-20之间")
数值校验
@Min / @Max 数值类型 校验数值是否大于等于/小于等于指定值 @Min(value=18, message="年龄需大于18")
@DecimalMin / @DecimalMax (新增) BigDecimal/String/数值 类似于 Min/Max,但支持字符串值,适用于高精度数值(如金额) @DecimalMin(value="0.01", message="金额不能小于0.01")
@Digits (新增) BigDecimal/数值/String 校验数值必须符合指定的整数位和小数位长度 @Digits(integer=5, fraction=2, message="金额格式错误")
@Positive (新增) 数值类型 校验数值必须为正数(> 0) @Positive(message = "数量必须为正数")
@PositiveOrZero (新增) 数值类型 校验数值必须为正数或 0(>= 0) @PositiveOrZero(message = "数量不能为负")
@Negative (新增) 数值类型 校验数值必须为负数(< 0) @Negative(message = "数值必须为负")
@NegativeOrZero (新增) 数值类型 校验数值必须为负数或 0(<= 0) @NegativeOrZero(message = "数值不能为正")
逻辑校验
@AssertTrue (新增) Boolean 校验字段值必须为 true @AssertTrue(message = "必须同意协议")
@AssertFalse (新增) Boolean 校验字段值必须为 false @AssertFalse(message = "逻辑状态必须为假")
日期校验
@Future / @Past 日期时间类型 校验日期是否在未来/过去 @Future(message = "活动日期必须是未来")
@FutureOrPresent (新增) 日期时间类型 校验日期是否在未来或当前时刻 @FutureOrPresent(message = "日期不能早于现在")
@PastOrPresent (新增) 日期时间类型 校验日期是否在过去或当前时刻 @PastOrPresent(message = "出生日期不能在未来")
格式校验
@Email String 校验是否为有效的邮箱格式 @Email(message = "邮箱格式不正确")
@Pattern String 校验字符串是否符合指定的正则表达式 @Pattern(regexp="^1[3-9]\\d{9}$", message="手机号格式错误")

自定义注解

定义注解

java 复制代码
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneValidator.class) // 指定校验器
public @interface Phone {
    String message() default "手机号格式不正确";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

实现校验逻辑

java 复制代码
public class PhoneValidator implements ConstraintValidator<Phone, String> {
    private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && value.matches(PHONE_REGEX);
    }
}

使用自定义注解

java 复制代码
public class UserDTO {
    @Phone
    private String phoneNumber;
}

实战开发步骤

在DTO中定义校验规则

将校验注解直接添加到数据传输对象(DTO)的字段上,并可以通过 message 属性自定义错误信息。

java 复制代码
public class UserCreateRequest {
    @NotBlank(message = "用户名不能为空")
    @Size(max = 50, message = "用户名长度不能超过50")
    private String name;

    @Email(message = "邮箱格式不正确")
    private String email;

    @Min(value = 18, message = "年龄必须大于等于18")
    private Integer age;
    // getters and setters...
}

在Controller层触发校验

在控制器方法的参数前使用 @Valid@Validated 注解,即可触发对该参数的校验。

java 复制代码
@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    public ResponseEntity<String> createUser(@RequestBody @Valid UserCreateRequest request) {
        // 如果校验通过,代码会执行到这里
        return ResponseEntity.ok("用户创建成功");
    }
}
@Valid@Validated 的区别
特性 @Valid (JSR-303/349 标准) @Validated (Spring 扩展)
分组校验 不支持 支持
方法级校验 不支持 支持 (需配合 @Validated 在类上)
嵌套对象校验 支持 (需在字段上使用) 支持 (需在字段上使用)

统一处理校验异常

校验失败会抛出 MethodArgumentNotValidException 异常。通常使用 @RestControllerAdvice 进行全局统一处理,向客户端返回结构化的错误信息。

java 复制代码
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationException(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        // 收集所有字段错误信息
        ex.getBindingResult().getFieldErrors().forEach(err ->
            errors.put(err.getField(), err.getDefaultMessage())
        );
        return ResponseEntity.badRequest().body(errors);
    }
}

分组校验

分组校验允许你在不同场景下应用不同的校验规则,例如创建(Create)和更新(Update)操作。

定义分组接口

java 复制代码
public class UserGroups {
    public interface Create {}
    public interface Update {}
}

在DTO中指定分组

java 复制代码
public class UserDTO {
    // 创建时ID必须为null,更新时ID不能为null
    @Null(groups = UserGroups.Create.class)
    @NotNull(groups = UserGroups.Update.class)
    private Long id;

    @NotBlank(groups = {UserGroups.Create.class, UserGroups.Update.class})
    private String username;
    // getters and setters...
}

在Controller中使用指定分组

java 复制代码
@PostMapping("/create")
public String create(@RequestBody @Validated(UserGroups.Create.class) UserDTO user) { ... }

@PutMapping("/update")
public String update(@RequestBody @Validated(UserGroups.Update.class) UserDTO user) { ... }
相关推荐
阿Y加油吧1 小时前
堆 / 优先队列专题二刷笔记:前 K 个高频元素 & 数据流的中位数
java·笔记·算法
凯尔萨厮1 小时前
创建Springboot空项目
java·spring boot
深邃-2 小时前
【Web安全】-Kali,Linux配置(2):Java环境配置,Python环境配置,Conda使用,PIP配置使用,SSH远程登录
java·linux·python·安全·web安全·网络安全·php
jjjava2.02 小时前
Java多线程编程:从入门到实战
java·开发语言
Seven972 小时前
Tomcat 线程池的设计与实现:StandardThreadExecutor
java
爱笑的Sunday2 小时前
Linux Java前后端项目 企业级0-1完整部署手册
java·linux·运维·服务器
xyx-3v2 小时前
FreeRTOS队列通信
java·服务器·网络
存在的五月雨2 小时前
uniapp 一些组件的使用
java·前端·uni-app
我命由我123452 小时前
Kotlin 开发 - 双冒号操作符(引用顶层函数、引用成员函数、引用构造函数、引用属性、引用类)
android·java·开发语言·kotlin·android studio·android jetpack·android-studio