Spring Boot 参数校验全指南

在 Web 开发中,参数校验是保障接口安全性和数据合法性的关键环节。手动编写校验逻辑不仅繁琐,还容易遗漏边界情况。Spring Boot 整合了 validation 工具,提供了一套简洁高效的参数校验方案,可快速实现对简单数据类型、对象类型的校验,并支持自定义异常处理。

一、参数校验入门:简单数据类型校验

1. 引入依赖

Spring Boot 提供了 spring-boot-starter-validation 起步依赖,内置了参数校验所需的核心组件:

<!-- 参数校验依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2. 开启参数校验

在控制器类上添加 @Validated 注解,开启参数校验功能:

@Validated // 开启参数校验
@Controller
public class TestController {// 接口方法...
}

3. 常用校验注解

对简单数据类型(如字符串、数字)的校验,可直接在方法参数上添加校验注解。常用注解如下:

注解作用示例
@NotBlank字符串不为 null 且去除空格后不为空串@NotBlank String username
@NotNull对象不为 null(适用于包装类)@NotNull Integer age
@NotEmpty集合不为 null 且不为空@NotEmpty List<String> ids
@Min数字最小值@Min(0) Integer score
@Max数字最大值@Max(150) Integer age
@Email字符串符合邮箱格式@Email String email
@Length字符串长度在指定范围内@Length(min=2, max=10) String name

4. 简单类型校验示例

@Validated
@Controller
public class TestController {@RequestMapping("/user")@ResponseBodypublic String addUser(@NotBlank(message = "用户名不能为空") String username, // 非空校验@NotNull(message = "年龄不能为空") @Min(0) @Max(150) Integer age, // 非空+范围校验@Email(message = "邮箱格式不正确") String email // 格式校验) {return "参数校验通过:" + username + ", " + age + ", " + email;}
}
  • message 属性用于自定义校验失败时的提示信息。
  • 当参数不符合校验规则时,会抛出 ConstraintViolationException 异常。

二、异常处理:统一响应错误信息

参数校验失败后,Spring Boot 会默认抛出异常并返回 400 错误,但默认的错误信息不够友好。我们可以通过以下两种方式统一处理校验异常:

1. 自定义错误页面(适用于前后端不分离)

Spring Boot 会自动跳转至 src/main/resources/templates/error.html 页面,可在该页面展示友好的错误提示:

<!-- error.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>错误提示</title>
</head>
<body><h1>参数错误</h1><p>请检查输入的参数是否符合要求</p>
</body>
</html>

2. 全局异常处理器(适用于前后端分离)

通过 @ControllerAdvice 定义全局异常处理器,捕获校验异常并返回 JSON 格式的错误信息:

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {// 处理简单类型参数校验异常@ExceptionHandler(ConstraintViolationException.class)public Map<String, String> handleConstraintViolationException(ConstraintViolationException e) {Map<String, String> errorMap = new HashMap<>();// 获取所有校验失败的信息e.getConstraintViolations().forEach(violation -> {String field = violation.getPropertyPath().toString(); // 参数名String message = violation.getMessage(); // 错误信息errorMap.put(field, message);});return errorMap;}
}

当参数校验失败时,会返回类似以下的 JSON 响应:

{"username": "用户名不能为空","email": "邮箱格式不正确"
}

三、对象类型参数校验

对于复杂业务场景,接口通常接收对象类型的参数(如用户注册信息、订单信息)。此时需对对象的每个属性进行校验,步骤如下:

1. 定义实体类并添加校验注解

在实体类的字段上添加校验注解,指定校验规则和错误提示:

public class User {@NotNull(message = "ID不能为空")private Integer id;@NotBlank(message = "姓名不能为空")@Length(min = 2, max = 10, message = "姓名长度必须在2-10之间")private String name;@NotNull(message = "年龄不能为空")@Min(value = 0, message = "年龄不能为负数")@Max(value = 150, message = "年龄不能超过150")private Integer age;// getter + setter(必须存在,否则校验不生效)
}

2. 在控制器中校验对象

在控制器方法的对象参数前添加 @Validated 注解,并通过 BindingResult 捕获校验结果:

@Controller
public class UserController {@RequestMapping("/addUser")@ResponseBodypublic String addUser(@Validated User user, // 开启对象校验BindingResult result // 用于接收校验结果) {// 判断是否有校验失败if (result.hasErrors()) {// 收集所有错误信息StringBuilder errorMsg = new StringBuilder();result.getAllErrors().forEach(error -> {FieldError fieldError = (FieldError) error;errorMsg.append(fieldError.getField()).append(":").append(fieldError.getDefaultMessage()).append("; ");});return "参数错误:" + errorMsg.toString();}// 校验通过,处理业务逻辑return "用户添加成功:" + user.getName();}
}
  • @Validated 用于开启对象的属性校验。
  • BindingResult 必须紧跟在被校验对象之后,用于接收校验结果,避免异常直接抛出。

四、常见问题与最佳实践

1. 校验注解不生效?

  • 确保已添加 spring-boot-starter-validation 依赖。
  • 控制器类上是否添加 @Validated 注解(简单类型校验必需)。
  • 对象类型校验时,是否在参数前添加 @Validated 注解,且实体类有 getter/setter 方法。

2. 如何自定义校验规则?

除了内置注解,还可通过 @Pattern 注解自定义正则校验,例如校验手机号:

@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;

3. 全局异常处理器的优势

使用 @ControllerAdvice 定义全局异常处理器,可统一处理所有校验异常,避免在每个接口中重复编写错误处理逻辑,提高代码复用性。

总结

Spring Boot 的参数校验机制通过注解化的方式,极大简化了数据合法性校验的实现。本文介绍了简单类型、对象类型的校验方法,以及异常处理方案,涵盖了从基础到实战的核心场景。合理使用参数校验,不仅能减少手动校验代码,还能提高接口的健壮性和安全性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/94497.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/94497.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/94497.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用技术资料链接

1.team技术 https://zhuanlan.zhihu.com/p/11389323664 https://blog.csdn.net/Lucky_Lu0/article/details/121697151 2.bond切换主备 https://www.xgss.net/3306.html 3.ssh详解&#xff1a; https://cloud.tencent.com/developer/news/105165 https://blog.huochengrm.c…

【Spring Cloud】-- 注册中心

文章目录1. 什么是注册中心2. CPA理论1. 什么是注册中心 注册中心有三种角色&#xff1a; 服务提供者&#xff08;Server&#xff09; &#xff1a;提供接口给其他微服务的程序。服务消费者&#xff08;Client&#xff09;&#xff1a;调用其他微服务提供的接口。**服务注册中…

go-zero 详解

go-zero 详解 go-zero 是一个基于 Go 语言的微服务框架&#xff0c;由字节跳动团队开发并开源&#xff0c;旨在帮助开发者快速构建高可用、高性能的微服务架构。它集成了丰富的组件&#xff0c;简化了微服务开发中的常见问题&#xff08;如服务注册发现、配置管理、限流熔断等&…

接口自动化框架封装之统一请求封装及通过文件实现接口关联

接口自动化测试框架封装目的:简化自动化框架的落地,提高投入和产出比,只要一个人封装好框架,另外的测试通过写yaml测试用例即可实现接口自动化1.统一请求的封装去除多余重复的代码可跨py文件实现通过一个session来自动关联有cookie的接口设置统一公共参数,统一文件处理,统一异常…

Vue 最佳实践:如何利用唯一 key 值保证 el-table 动态渲染的稳定性

&#x1f4cb; 问题描述 在Vue 2.0 ElementUI项目的偏置条件管理页面中&#xff0c;每次切换到"内规拉偏"菜单时&#xff0c;表格样式会发生崩溃&#xff0c;导致表格布局异常、列宽错乱、固定列显示不正确等问题。 &#x1f50d; 问题分析 通过深入分析代码&#x…

popen开启进程,写入数据

通过管道&#xff08;popen&#xff09;启动 SDIWAN_WEB 进程并写入 JSON 数据的过程可以分为以下步骤&#xff0c;结合代码示例和关键注意事项进行说明&#xff1a;1. 核心代码示例 #include <stdio.h> #include <json-c/json.h>int main() {// 1. 创建 JSON 对象…

计算机视觉的四项基本任务辨析

计算机视觉是使计算机能理解采集设备采集的图像视频的一门学科&#xff0c;目的是让计算机实现人的视觉功能——对客观世界的三维场景的感知、识别和理解。换句话说&#xff0c;要让计算机具备通过二维图像认识三维环境的能力。 目录 三个阶段 视觉层级 基本任务 技术难点…

iostat 系统IO监控命令学习

一、iostat 命令描述 “iostat”命令用于监测系统输入/输出设备的负载情况&#xff0c;其通过观察设备处于活跃状态的时间与平均传输速率之间的关系来实现这一目的。该命令会生成报告&#xff0c;这些报告可用于调整系统配置&#xff0c;以更好地平衡物理磁盘之间的输入/输出负…

jenkins使用ssh方式连接gitee 公钥、私钥配置、指纹

前言 Gitee 提供了基于 SSH 协议的 Git 服务&#xff0c;jenkins可使用ssh方式连接gitee&#xff0c;拉取代码、提交tag等&#xff1b;使用ssh 连接&#xff0c;相比用户名密码方式&#xff0c;可省去因密码变更而引起的jenkins关联修改。 gitee生成、添加 SSH 公钥 生成SSH…

如何在Android设备上删除多个联系人(3种方法)

如果您想清理安卓手机&#xff0c;或者只是想删除旧的、不需要的联系人&#xff0c;或者删除多个联系人&#xff0c;有三种有效的方法可供选择。无论您是想手动删除安卓手机上的联系人&#xff0c;还是使用专用工具&#xff0c;都可以按照以下步骤操作。方法1&#xff1a;如何通…

Angular进阶之十三:Angular全新控制流:革命性的模板语法升级

随着Angular v17的发布&#xff0c;框架带来了革命性的控制流语法&#xff0c;彻底改变了我们编写模板的方式。这些改进不仅仅是语法糖——它们提升了性能、开发体验和代码可维护性。 为什么我们需要新的控制流&#xff1f; 在之前的Angular版本中&#xff0c;我们使用结构指令…

【Redis】string字符串

目录 一.常见命令 1.1.SET 1.2.GET 1.3.MGET 1.4.MSET 1.5.SETNX 二.计数命令 2.1.INCR 2.2.INCRBY 2.3.DECR 2.4.DECYBY 2.5.INCRBYFLOAT 三 . 其他命令 3.1.APPEND 3.2.GETRANGE 3.3.SETRANGE 3.4.STRLEN 四. 字符串类型内部编码 五. 典型使用场…

Nginx 学习

通过网盘分享的文件&#xff1a;Nginx 链接: https://pan.baidu.com/s/1dCc7FoND90H_x7rvRUXJqg 提取码: yyds 通过网盘分享的文件&#xff1a;Tomcat 链接: https://pan.baidu.com/s/1nj_5j_66gS_YHUAX1C25jg 提取码: yyds Nginx安装、启动 安装依赖库 #安装C编译器 yum insta…

Java、Android及计算机基础面试题总结

1. String、StringBuffer、StringBuilder区别特性StringStringBufferStringBuilder可变性不可变可变可变线程安全是是(synchronized)否性能低(频繁操作时)中等高场景字符串常量多线程字符串操作单线程字符串操作2. 接口和抽象类的区别特性接口(Interface)抽象类(Abstract Class…

数据集相关类代码回顾理解 | sns.distplot\%matplotlib inline\sns.scatterplot

【PyTorch】单目标检测项目 目录 os.path.join sns.distplot adjust_brightness os.path.join fullPath2imgos.path.join(path2data,"Training400",prefix,imgName[id_]) 使用os.path.join函数&#xff0c;智能地处理不同操作系统中的路径分隔符问题&#xff0…

JavaScript:链式调用

概念 链式调用&#xff08;Method Chaining&#xff09;是 JavaScript 中一种常见的编程模式&#xff0c;允许通过连续调用对象的方法来简化代码。这种模式的核心在于每个方法返回调用对象本身&#xff08;通常是 this&#xff09;&#xff0c;从而可以继续调用其他方法。 链式…

龙芯(loongson) ls2k1000 openwrt

PC环境&#xff1a;Linux Mint 21.3安装依赖sudo apt install build-essential clang flex bison g gawk gcc-multilib g-multilib gettext git libncurses-dev libssl-dev python3-distutils rsync unzip zlib1g-dev file wget下载源码&#xff1a;git clone https://gitee.co…

算法438. 找到字符串中所有字母异位词

给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。示例 1:输入: s "cbaebabacd", p "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "abc&…

Go语言中的闭包详解

闭包在Go语言中是一个能够访问并操作其外部作用域变量的函数&#xff0c;即使外部函数已经执行完毕。闭包由函数体和其引用的环境&#xff08;外部变量&#xff09;组成&#xff0c;及&#xff1a;闭包 函数 环境。闭包的特性&#xff1a;捕获外部变量&#xff1a;内部函数可…

【DL学习笔记】Dataset类功能以及自定义

文章目录一、Dataset 与 DataLoader 功能介绍抽象类Dataset的作用DataLoader 作用两者关系二、自定义Dataset类Dataset的三个重要方法__len__()方法_getitem__()方法__init__ 方法三、现成的torchvision.datasets模块MNIST举例COCODetection举例torchvision.datasets.MNIST使用…