当前位置: 代码网 > it编程>编程语言>Java > SpringBoot接口参数校验从入门到精通的完整指南

SpringBoot接口参数校验从入门到精通的完整指南

2026年08月20日 Java 我要评论
写接口时,你是不是还在用一堆 if 判断参数是否为空、格式对不对?这篇文章带你用更优雅的方式搞定一切。示例小张 刚入职时,负责开发一个用户注册接口。他非常认真,编写了如下代码:@postmapping

写接口时,你是不是还在用一堆 if 判断参数是否为空、格式对不对?这篇文章带你用更优雅的方式搞定一切。

示例

小张 刚入职时,负责开发一个用户注册接口。他非常认真,编写了如下代码:

@postmapping("/register")
public string register(user user) {
    // 手动校验每个字段
    if (user.getusername() == null || user.getusername().isempty()) {
        return "用户名不能为空";
    }
    if (user.getpassword() == null || user.getpassword().length() < 6) {
        return "密码长度不能小于6位";
    }
    if (user.getemail() == null || !user.getemail().contains("@")) {
        return "邮箱格式不正确";
    }
    if (user.getage() == null || user.getage() < 0 || user.getage() > 150) {
        return "年龄不合法";
    }
    // ... 继续业务逻辑
}

这样写有什么问题?

问题说明
代码臃肿校验代码比业务逻辑还多
重复劳动每个接口都要写一遍类似的校验
难以维护新增字段要改多处代码
不统一不同人写的校验格式五花八门

专业做法是:使用 java 的 bean validation(又叫 jsr-303)规范,通过注解优雅地完成参数校验。

五分钟快速入门

第一步:引入依赖

spring boot 2.3+ 需要手动引入校验依赖(老版本自带):

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-validation</artifactid>
</dependency>

第二步:在实体类上加注解

import javax.validation.constraints.*;
public class userregisterdto {
@notblank(message = "用户名不能为空")
private string username;

@notblank(message = "密码不能为空")
@size(min = 6, max = 20, message = "密码长度必须在6-20位之间")
private string password;

@notblank(message = "邮箱不能为空")
@email(message = "邮箱格式不正确")
private string email;

@notnull(message = "年龄不能为空")
@min(value = 1, message = "年龄最小为1岁")
@max(value = 150, message = "年龄最大为150岁")
private integer age;

// getter / setter 省略
}

第三步:在controller中使用@valid

@restcontroller
@requestmapping("/api/user")
public class usercontroller {
@postmapping("/register")
public result register(@valid @requestbody userregisterdto dto) {
    // 如果校验不通过,根本不会执行到这里
    // 这里只管写业务逻辑
    userservice.register(dto);
    return result.success("注册成功");
}
}

就这样简单三步,所有 if 校验都不需要写了! 当参数不符合规则时,spring boot 会自动抛出异常,并返回400错误。

常用校验注解大全(新人必看)

空值校验

注解适用类型说明
@notnull任意类型不能为 null
@notblankstring不能为 null、空字符串、纯空格
@notemptystring、collection、map、数组不能为 null 或空

使用建议

  • 字符串字段优先用 @notblank
  • 集合/map 字段用 @notempty
  • 包装类型(如 integerlong)用 @notnull

数值校验

注解适用类型说明
@min(value)数值类型最小值(含)
@max(value)数值类型最大值(含)
@decimalmin(value)数值类型最小值(支持小数)
@decimalmax(value)数值类型最大值(支持小数)
@digits(integer, fraction)数值类型整数位数和小数位数限制
@positive数值类型正数(>0)
@positiveorzero数值类型正数或0
@negative数值类型负数
@negativeorzero数值类型负数或0

示例

@min(value = 1, message = "数量至少为1")
@max(value = 999, message = "数量不能超过999")
private integer quantity;
@decimalmin(value = "0.01", message = "金额至少为0.01")
@decimalmax(value = "999999.99", message = "金额不能超过999999.99")
private bigdecimal amount;

字符串校验

注解说明
@size(min, max)字符串长度范围
@email邮箱格式
@pattern(regexp)正则表达式匹配
@urlurl格式

示例

@past(message = "生日必须是过去的时间")
private localdate birthday;
@future(message = "有效期必须晚于当前时间")
private localdatetime expiretime;
@asserttrue(message = "必须同意用户协议")
private boolean agreeprotocol;

分组校验:同一个对象,不同场景不同规则

同一个 dto 可能在不同接口中使用,校验规则不一样。比如:新增用户时密码必填,更新用户时密码可选。

第一步:定义分组接口(只是两个空接口)

public interface creategroup {}   // 新增分组
public interface updategroup {}   // 更新分组

第二步:在注解中指定分组

public class userdto {
@notnull(message = "id不能为空", groups = updategroup.class)
private long id;

@notblank(message = "用户名不能为空", groups = {creategroup.class, updategroup.class})
private string username;

@notblank(message = "密码不能为空", groups = creategroup.class)  // 新增时必填
@size(min = 6, max = 20, message = "密码长度6-20位")
private string password;

@email(message = "邮箱格式不正确")
private string email;  // 没指定分组,默认在所有分组都生效
}

第三步:在 controller 中指定使用的分组

@restcontroller
@requestmapping("/api/user")
public class usercontroller {
@postmapping("/create")   // 新增时使用 creategroup
public result create(@validated(creategroup.class) @requestbody userdto dto) {
    // 此时会校验:id(不校验,因为没有在creategroup中标记)、username(校验)、password(校验)
    userservice.create(dto);
    return result.success();
}

@putmapping("/update")    // 更新时使用 updategroup
public result update(@validated(updategroup.class) @requestbody userdto dto) {
    // 此时会校验:id(校验)、username(校验)、password(不校验,因为没有在updategroup中标记)
    userservice.update(dto);
    return result.success();
}
}

注意: 分组校验时要用 @validated 而不是 @valid@validated 才能指定分组。

高级技巧:自定义校验注解

第一步:定义注解

import javax.validation.constraint;
import javax.validation.payload;
import java.lang.annotation.*;
@documented
@constraint(validatedby = gendervalidator.class)  // 指定校验器
@target({elementtype.field})
@retention(retentionpolicy.runtime)
public @interface gender {
string message() default "性别只能是 male 或 female";

class&lt;?&gt;[] groups() default {};

class&lt;? extends payload&gt;[] payload() default {};
}

第二步:实现校验器

import javax.validation.constraintvalidator;
import javax.validation.constraintvalidatorcontext;
public class gendervalidator implements constraintvalidator<gender, string> {
@override
public boolean isvalid(string value, constraintvalidatorcontext context) {
    if (value == null) {
        return true;  // 允许为空,由 @notnull 控制是否必填
    }
    return "male".equals(value) || "female".equals(value);
}
}

第三步:使用

public class userdto {
    @gender(message = "性别只能填 male 或 female")
    private string gender;
}

全局统一处理校验异常

默认情况下,校验失败会返回400错误和默认的报错信息。为了让前端收到统一格式的响应,需要全局异常处理。

import org.springframework.http.httpstatus;
import org.springframework.validation.fielderror;
import org.springframework.web.bind.methodargumentnotvalidexception;
import org.springframework.web.bind.annotation.exceptionhandler;
import org.springframework.web.bind.annotation.responsestatus;
import org.springframework.web.bind.annotation.restcontrolleradvice;
import java.util.hashmap;
import java.util.map;
@restcontrolleradvice
public class globalexceptionhandler {
/**
 * 处理 @valid 校验失败异常
 */
@exceptionhandler(methodargumentnotvalidexception.class)
@responsestatus(httpstatus.bad_request)
public result handlevalidationexception(methodargumentnotvalidexception e) {
    // 收集所有字段的校验失败信息
    map&lt;string, string&gt; errors = new hashmap&lt;&gt;();
    e.getbindingresult().getallerrors().foreach(error -&gt; {
        string fieldname = ((fielderror) error).getfield();
        string errormessage = error.getdefaultmessage();
        errors.put(fieldname, errormessage);
    });
    return result.error(400, "参数校验失败", errors);
}
}

返回给前端的格式

{
    "code": 400,
    "message": "参数校验失败",
    "data": {
        "username": "用户名不能为空",
        "password": "密码长度必须在6-20位之间"
    }
}

常见问题与避坑指南

坑一:@valid 不生效

原因: 没有引入 spring-boot-starter-validation 依赖(spring boot 2.3+ 需要手动引入)。

解决方案: 检查 pom.xml 是否有该依赖。

坑二:对 list 集合校验无效

错误写法:

@postmapping("/batch")
public result batch(@valid @requestbody list<userdto> userlist) {  // list 不支持 @valid
    // ...
}

正确写法: 用包装类

@data
public class userlistdto {
    @valid
    private list<userdto> userlist;
}
@postmapping("/batch")
public result batch(@valid @requestbody userlistdto dto) {
// ...
}

坑三:嵌套对象校验失效

错误写法:

public class orderdto {
    @notnull
    private long userid;
    // 没有加 @valid,address 内部的校验不生效
    private addressdto address;
}

正确写法:

public class orderdto {
    @notnull
    private long userid;
@valid  // 必须加 @valid 才能触发嵌套校验
private addressdto address;
}

坑四:整数类型的 @notnull 无法校验 0

@notnull 只校验是否为 null,不校验值的大小。如果要排除 0,需要配合 @min(1) 使用。

坑五:日志记录时泄露敏感信息

校验失败时如果直接把整个dto对象打印到日志,可能泄露密码等信息。

错误做法:

logger.error("校验失败,参数:{}", dto);  // 可能包含密码

正确做法:

logger.error("校验失败,用户:{},字段:{}", dto.getusername(), errors);

检查清单

为了帮助你快速检查自己的项目是否已正确使用校验功能,这里提供一个检查清单表格:

检查项说明
项目中已引入 spring-boot-starter-validation 依赖spring boot 2.3+ 需要手动引入
所有接口参数都用 dto 接收,配合 @valid@validated 校验避免在 controller 中写大量 if 判断
同一个 dto 在不同接口有不同校验规则时,使用了分组校验通过 @validated(group.class) 指定分组
内置注解无法满足时,写了自己的自定义注解实现 constraintvalidator 接口
全局异常处理器统一处理 methodargumentnotvalidexception返回统一格式的错误响应
嵌套对象校验用了 @valid确保嵌套对象内部的注解生效
list 集合校验用了包装类直接对 list<t> 使用 @valid 无效
没有在日志中记录密码等敏感信息避免泄露用户隐私

最后

从手动写 if 校验到使用注解校验,代码量减少 80% 以上,可读性和维护性却大幅提升。这就是用好工具的价值——把时间花在真正的业务逻辑上,而不是重复的校验劳动上。

以上就是springboot接口参数校验从入门到精通的完整指南的详细内容,更多关于springboot接口参数校验的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com