SpringBoot利用validation实现数据校验完整指南

 更新时间:2025年09月03日 08:48:20   作者:Micro麦可乐  
Spring Boot 提供的 Validation(基于 JSR 303/380 规范)让我们能通过注解的方式优雅地完成参数校验,极大地提升了开发效率和代码可读性,下面我们就来看看具体实现吧

1. 前言

在我们日常开发中,后端经常需要对请求参数进行校验。比如注册用户时,用户名不能为空、密码长度要在 6~16 之间、邮箱必须符合格式等等,如果我们不做校验,脏数据就可能进入数据库,造成业务问题;如果校验方式不合理,代码又会变得臃肿

相信很多小伙伴还在 Controller 代码中写大量重复的 if-else 判断,既冗余又难维护!(如果你也是这样操作,那一定要看完本篇文章)

下面博主介绍一下Spring Boot 提供的 Validation(基于 JSR 303/380 规范)让我们能通过注解的方式优雅地完成参数校验,极大地提升了开发效率和代码可读性

2. 没有使用 Validation 的传统写法

下面我们先看看没用 Validation 的“土法校验”,再对比一下用了注解后的优雅写法。当不使用数据校验框架时,我们通常会在 Controller 中手动校验参数,代码会像这样:

场景:创建用户接口

定义接受参数对象UserDto

// UserDTO实体类
class UserDto {
    private String name;
    private Integer age;
    private String email;
    
    // getter和setter省略
}

要求:用户名不能为空,长度5-10;邮箱格式必须正确;年龄在18-60之间

@RestController
@RequestMapping("/user")
public class UserController {
    
    @PostMapping("/add")
    public String addUser(UserDto user) {
        // 手动校验参数
        if (user.getName() == null || user.getName().trim().isEmpty()) {
            return "用户名不能为空";
        }
        if (user.getName().length() < 5 || user.getName().length() > 10) {
            return "用户名长度必须在5-10之间";
        }
        if (user.getAge() == null) {
            return "年龄不能为空";
        }
        if (user.getAge() < 18 || user.getAge() > 60) {
            return "年龄必须在18-60之间";
        }
        if (user.getEmail() == null || user.getEmail().trim().isEmpty()) {
            return "邮箱不能为空";
        }
        if (!user.getEmail().matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$")) {
            return "邮箱格式不正确";
        }
        
        // 业务逻辑处理
        return "用户添加成功";
    }
}

可以看出上述写法的缺点:

  • 代码冗长,不利于维护
  • 每个接口都要写重复的校验逻辑
  • 校验逻辑和业务逻辑耦合,不够优雅

3. 使用 Validation 的优雅写法

我们可以在实体类上加注解,把校验规则声明在模型上,让 Spring 自动完成校验

Maven 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

UserDto对象加上注解

import javax.validation.constraints.*;

public class UserDto {

    @NotBlank(message = "用户名不能为空")
    @Size(min = 2, max = 10, message = "用户名长度必须在{min}-{max}之间")
    private String username;

    @NotBlank(message = "邮箱不能为空")
    @Email(message = "邮箱格式不正确") // 自带邮箱格式校验,无需自己写正则!
    private String email;

    @NotNull(message = "年龄不能为空")
    @Min(value = 0, message = "年龄最小为{value}")
    @Max(value = 150, message = "年龄最大为{value}")
    private Integer age;

    // 省略 Getter 和 Setter...
}

在Controller参数前加@Valid或@Validated注解

import javax.validation.Valid;

@RestController
@RequestMapping("/user")
public class UserController {

    @PostMapping("/add")
    // 关键一步:在 @RequestBody 前加上 @Valid 注解
    public String addUser(@Valid @RequestBody UserDto user) {
        // 只需关注核心业务
        System.out.println("用户创建成功: " + user);
        return "success";
    }
}

通过上述使用 validation 改造,Spring 会自动对 UserDto 的字段进行校验,当请求参数不满足规则时,Spring Boot 会自动抛出 MethodArgumentNotValidException 异常,不会进入这个方法体。但我们不能直接给用户返回异常栈,需要统一处理

4. 全局异常处理(友好返回错误信息)

刚才我们已经说过了参数校验不满足规则,系统会抛出MethodArgumentNotValidException ,那么我们就可以通过 @RestControllerAdvice 捕获 MethodArgumentNotValidException,来实现统一返回错误信息

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;
import java.util.Objects;

@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理实体校验异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Map<String, Object> handleValidException(MethodArgumentNotValidException e) {
        Map<String, Object> errorResult = new HashMap<>();
        errorResult.put("code", 400);
        errorResult.put("message", "参数校验失败");
        // 从异常对象中拿到具体的错误信息
        // 这里只取第一个错误信息,也可以全部返回
        String defaultMessage = Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage();
        errorResult.put("data", defaultMessage);
        return errorResult;
    }
}

最后我们可以使用Postman或curl测试,观察接口返回的JSON异常数据

5. 常用校验注解

注解功能说明
@NotNull值不能为null
@NotBlank字符串不能为空(trim后长度>0)
@NotEmpty集合、数组、Map、String不能为空
@Size(min=, max=)检查字符串、集合、数组大小
@Min(value)数字最小值
@Max(value)数字最大值
@Email校验邮箱格式
@Pattern(regexp=)正则表达式匹配
@Positive正数
@Future日期必须在未来
@Past日期必须在过去

6. 分组校验

当同一个实体类在不同场景下有不同的校验规则时,比如新增时ID应为空,而更新时ID不能为空,这时就需要分组校验

定义分组接口(标记接口)

public interface CreateGroup {} // 创建分组
public interface UpdateGroup {} // 更新分组

在实体上指定分组
继续改造一下我们的UserDto,这时候需要增加id字段

public class UserDto {
    @Null(groups = CreateGroup.class, message = "创建时ID必须为空")
    @NotNull(groups = UpdateGroup.class, message = "更新时ID不能为空")
    private Long id;

    @NotBlank(message = "用户名不能为空", groups = {CreateGroup.class, UpdateGroup.class})
    private String username;
    // ... 其他字段
}

在Controller中使用@Validated指定分组

@PostMapping("/create")
public String create(@Validated(CreateGroup.class) @RequestBody UserDto user) {
    // ... 创建逻辑
}

@PostMapping("/update")
public String update(@Validated(UpdateGroup.class) @RequestBody UserDto user) {
    // ... 更新逻辑
}

7. 结语

通过使用 Spring Boot Validation,我们可以告别繁琐的手动参数校验,让代码更加简洁、优雅、易维护。希望本文能帮助你在项目中更好地应用数据校验机制,提升开发效率和代码质量,是开发中必不可少的利器!

到此这篇关于SpringBoot利用validation实现数据校验完整指南的文章就介绍到这了,更多相关SpringBoot validation校验内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Scala中Array和List的区别说明

    Scala中Array和List的区别说明

    这篇文章主要介绍了Scala中Array和List的区别说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • 解决idea找不到类could not find artifact问题

    解决idea找不到类could not find artifact问题

    本文总结了解决Java项目中找不到类的问题的常见解决方案,包括刷新Maven项目、清理IDEA缓存、Maven Clean Install、重新Package、解决依赖冲突和手动导入依赖包等方法
    2025-01-01
  • Java设置httponly cookie的实现示例

    Java设置httponly cookie的实现示例

    本文主要介绍了Java设置httponly cookie的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • Java中的适配器原理解析

    Java中的适配器原理解析

    这篇文章主要介绍了Java中的适配器原理解析,当实现接口时,为了使所用的类中只实现需要的方法,使代码更加简洁,可以定义一个抽象类实现接口,将所需要的方法定义为 抽象方法,然后让类继承此抽象方法即可,需要的朋友可以参考下
    2023-11-11
  • Java中常见的对象转换工具

    Java中常见的对象转换工具

    对象进行对象的转换是一个操作重复且繁琐的工作,于是市面上就有许多的对象转换工具来解决这个问题,下面我们就来看看几个比较常用的工具(mapstruct,Spring BeanUtils,Apache BeanUtils)使用方式及其性能
    2023-04-04
  • 基于Hutool的图片验证码功能模块实现

    基于Hutool的图片验证码功能模块实现

    为了提高系统的安全性,防止接口被暴力刷新,验证码是个好的手段,图片验证码没有短信验证码的费用,其是个人开发者学习的重点,这篇文章主要介绍了基于Hutool的图片验证码功能模块实现,需要的朋友可以参考下
    2022-10-10
  • 一文浅析Java金额计算用long还是BigDecimal

    一文浅析Java金额计算用long还是BigDecimal

    在Java后端开发中处理与钱有关的业务时,确保金额计算的准确性和避免错误非常重要,这篇文章主要给大家介绍了关于Java中处理金额计算之使用Long还是BigDecimal的相关资料,希望对大家有所帮助
    2025-12-12
  • Java实现的计算最大下标距离算法示例

    Java实现的计算最大下标距离算法示例

    这篇文章主要介绍了Java实现的计算最大下标距离算法,涉及java针对数组的遍历、运算等相关操作技巧,需要的朋友可以参考下
    2018-02-02
  • Java实现马踏棋盘算法

    Java实现马踏棋盘算法

    这篇文章主要为大家详细介绍了Java实现马踏棋盘算法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • eclipse如何搭建Springboot项目详解

    eclipse如何搭建Springboot项目详解

    今天带大家学习eclipse如何搭建Spring boot项目,文中有非常详细的图文解说,对正在学习java的小伙伴们有很好地帮助,需要的朋友可以参考下
    2021-05-05

最新评论