瞧瞧别人家的参数校验,那叫一个优雅!

【导航】ESP32 教学篇目录 【快速跳转】 本文章 来自原创专栏《ESP32教学专栏 (基于ESP-IDF)》,讲解如何使用 ESP-IDF 构建 ESP32 的WIFI及连接的程序,发布文章并会持续为已发布文章添加新内容! 每篇文章都经过了精打细磨! ↓↓↓通过下方 按钮 进入专栏主页↓↓↓ 专栏主页:点击进入→ESP32 教学专栏 (基于ESP-IDF) WIFI二级专栏:点击进入→ESP32 上的 WiFi ............ 阅读详情

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 

5dd62160f0838a5643b1f32ca28f25c8.gif

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、ERP、CRM、AI 大模型等等功能:

  • Boot 多模块架构:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • Cloud 微服务架构:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

【国内首批】支持 JDK 17/21 + SpringBoot 3.3、JDK 8/11 + Spring Boot 2.7 双版本 

来源:苏三说技术


对于开发人员来说,对用户输入的参数或者系统参数做校验,是日常工作之一。

很多小伙伴在写接口的时候,可能都会碰到一个问题:参数校验应该怎么写?

比如,开发一个用户注册接口,需要校验以下条件:

  • 用户名不能为空,长度在 3 到 20 个字符之间;

  • 密码不能为空,长度至少为 8 个字符;

  • 年龄必须是正整数,不能超过 120;

  • 邮箱必须符合标准格式。

乍一看,这种校验逻辑看起来很简单嘛,直接写几个 if 就完事了。

但真的这么简单吗?

接下来我们就从传统的参数校验入手,看看问题出在哪,然后再聊聊 Spring Boot 中如何优雅地实现参数校验 ,希望对你会有所帮助。

一、传统参数校验的问题

很多人可能会直接在 Controller 里手写校验逻辑,比如下面这个代码:

@RestController
@RequestMapping("/api/users")
public class UserController {

    @PostMapping("/register")
    public ResponseEntity<String> register(@RequestBody Map<String, Object> request) {
        String username = (String) request.get("username");
        if (username == null || username.length() < 3 || username.length() > 20) {
            return ResponseEntity.badRequest().body("用户名不能为空,且长度必须在3到20之间");
        }

        String password = (String) request.get("password");
        if (password == null || password.length() < 8) {
            return ResponseEntity.badRequest().body("密码不能为空,且长度至少为8个字符");
        }

        Integer age = (Integer) request.get("age");
        if (age == null || age <= 0 || age > 120) {
            return ResponseEntity.badRequest().body("年龄必须是正整数,且不能超过120");
        }

        return ResponseEntity.ok("注册成功!");
    }
}

这段代码乍一看没什么问题,但如果仔细分析,会发现一堆隐患:

  1. 代码冗余 :校验逻辑散落在 Controller 里,写起来麻烦,后期维护更是灾难。

  2. 重复劳动 :类似的校验逻辑可能会出现在多个接口里,导致代码重复度极高。

  3. 用户体验差 :返回的错误信息不统一、不规范,前端开发还得猜用户输入到底哪儿错了。

  4. 扩展性差 :万一某天需要加新的校验规则,你可能要到处改代码。

所以,这种手写参数校验的方式,在简单场景下勉强能用,但如果业务变复杂,问题会越来越多。

那么问题来了,那有没有更优雅的方式来处理这些问题呢?

答:当然是有的。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

二、Spring Boot 的参数校验机制

在 Spring Boot 中,我们可以使用 Hibernate Validator (Bean Validation 的参考实现)来实现参数校验。

它的核心思路是:把校验逻辑从业务代码里抽离出来,用注解的方式声明校验规则 。

接下来我们一步步来看怎么实现。

1. 使用注解进行参数校验

首先,定义一个用于接收用户注册参数的 DTO 对象:

@Data
public class UserRegistrationRequest {

    @NotNull(message = "用户名不能为空")
    @Size(min = 3, max = 20, message = "用户名长度必须在3到20之间")
    private String username;

    @NotNull(message = "密码不能为空")
    @Size(min = 8, message = "密码长度至少为8个字符")
    private String password;

    @NotNull(message = "年龄不能为空")
    @Min(value = 1, message = "年龄必须是正整数")
    @Max(value = 120, message = "年龄不能超过120")
    private Integer age;

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

这里我们用了几个常见的校验注解:

  • @NotNull:字段不能为空;

  • @Size:限制字符串长度;

  • @Min 和 @Max:限制数值范围;

  • @Email:校验邮箱格式。

这些注解由 Hibernate Validator 提供,基本涵盖了日常开发中的大部分校验需求。

然后,在 Controller 中这样写:

@RestController
@RequestMapping("/api/users")
public class UserController {

    @PostMapping("/register")
    public ResponseEntity<String> register(@Valid @RequestBody UserRegistrationRequest request) {
        return ResponseEntity.ok("注册成功!");
    }
}

注意这里的 @Valid 注解,它的作用是告诉 Spring:对请求参数进行校验 。

2. 统一处理校验错误

如果前端传的参数不合法,Spring 会抛出一个 MethodArgumentNotValidException 异常。默认情况下,这个异常返回的信息不太友好,可能是这样的:

{
  "timestamp": "2024-01-01T12:00:00.000+00:00",
  "status": 400,
  "error": "Bad Request",
  "message": "Validation failed for object='userRegistrationRequest'. Error count: 2",
  "path": "/api/users/register"
}

为了提升用户体验,我们可以用全局异常处理器来统一格式化错误信息:

@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(error -> {
            errors.put(error.getField(), error.getDefaultMessage());
        });
        return ResponseEntity.badRequest().body(errors);
    }
}

现在,当参数校验失败时,返回的错误信息会变成这样:

{
  "username": "用户名长度必须在3到20之间",
  "password": "密码不能为空"
}

清晰又直观,用户一看就明白自己错在哪儿了。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

三、应对复杂场景的高级技巧

1. 分组校验

有些场景下,不同的接口对参数的校验规则是不一样的,比如:

  • 注册接口要求 username 和 password 是必填项;

  • 更新接口只需要校验 email 和 age。

这种情况下,可以用 分组校验 来解决。

定义校验分组
public interface RegisterGroup {}
public interface UpdateGroup {}
在字段上指定分组
public class UserRequest {

    @NotNull(groups = RegisterGroup.class, message = "用户名不能为空")
    @Size(min = 3, max = 20, groups = RegisterGroup.class, message = "用户名长度必须在3到20之间")
    private String username;

    @NotNull(groups = RegisterGroup.class, message = "密码不能为空")
    private String password;

    @Email(groups = UpdateGroup.class, message = "邮箱格式不正确")
    private String email;

    @Min(value = 1, groups = UpdateGroup.class, message = "年龄必须是正整数")
    private Integer age;
}
在 Controller 中指定分组
@RestController
@RequestMapping("/api/users")
public class UserController {

    @PostMapping("/register")
    public ResponseEntity<String> register(@Validated(RegisterGroup.class) @RequestBody UserRequest request) {
        return ResponseEntity.ok("注册成功!");
    }

    @PutMapping("/update")
    public ResponseEntity<String> update(@Validated(UpdateGroup.class) @RequestBody UserRequest request) {
        return ResponseEntity.ok("更新成功!");
    }
}

2. 自定义校验注解

如果 Hibernate Validator 提供的注解不能满足需求,还可以自定义校验注解。例如,校验手机号格式。

定义注解
@Documented
@Constraint(validatedBy = PhoneValidator.class)
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidPhone {
    String message() default "手机号格式不正确";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
实现校验逻辑
public class PhoneValidator implements ConstraintValidator<ValidPhone, 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);
    }
}
使用自定义注解
public class UserRequest {
    @ValidPhone
    private String phone;
}

四、总结

优雅的参数校验不仅能提高代码的可维护性,还能显著提升用户体验。

在 Spring Boot 中,通过使用 Hibernate Validator 提供的注解,配合分组校验、自定义校验和统一异常处理。

我们可以轻松实现简洁、高效、可扩展的参数校验机制。

优雅的参数校验的秘籍是:

  1. 注解优先:能用注解解决的校验,就不要手写逻辑代码。

  2. 分离校验逻辑:参数校验应该集中在 DTO 层,避免散落在业务代码中。

  3. 全局统一异常处理:确保错误信息规范化、友好化。

  4. 合理使用分组校验:根据接口需求灵活调整校验规则。

  5. 覆盖边界条件:通过单元测试验证校验逻辑,确保没有漏网之鱼。

如果看了这篇文章有些收获,记得给我点赞和转发喔。


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,“长按”或“扫描”下方二维码噢:

ff3cf36cd02cad342cee29c86491de71.png

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

77818397264d612c5abdd371ec59f9fb.png

a8e5830fd28ac5a547b06890f05734b9.pnga4e2463a394458b5de6af89087428339.pngd010dd759f055a51f5c23aa39f3710ae.pnge2922ea1949edb85bb18356c694b4435.png

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
【流复制环境PostgreSQL-14.1到PostgreSQL-16.1大版本升级】 PostgreSQL大版本会定期添加新特性,这些新特性通常会改变系统表的布局,但内部数据存储格式很少改变。pg_upgrade通过创建新的系统表和重用旧的用户数据文件来执行快速升级。pg_upgrade升级主要有三种用法:1、使用pg_upgrade拷贝升级。2、使用pg_upgrade链接升级(带有- -link选项),- -link较快,但是启动新版本后修改了数据文件,再启动旧版本可能数据损坏,回滚较麻烦,所以尽量避免使用link参数进行升级。 阅读详情

相关推荐

华为海思IC前端中后端(COT&XPU)岗位笔试机考题

华为海思COT和XPU部门IC前端,IC中端,IC后端岗位笔试真题分享

weixin_37584728的博客 3362

瞧瞧别人家的 API 接口,那叫一个优雅!

在实际工作中,我们需要经常跟第三方平台打交道,可能会对接第三方平台API接口,或者提供API接口给第三方平台调用。那么问题来了,如何设计一个优雅的API接口,能够满足:安全性、可重复调用、稳定性、好定位问题等多方面需求?今天跟大家一起聊聊设计API接口时,需要注意的一些地方,希望对你会有所帮助。

20年码农 9229

万达电影 com.wandafilm.app headers check

万达电影 安卓逆向 抓包 逆向 check

weixin_43786514的博客 1438

瞧瞧别人家的API接口,那叫一个优雅

在实际工作中,我们需要经常跟第三方平台打交道,可能会对接第三方平台API接口,或者提供API接口给第三方平台调用。那么问题来了,如果设计一个优雅的API接口,能够满足:安全性、可重复调用、稳定性、好定位问题等多方面需求?今天跟大家一起聊聊设计API接口时,需要注意的一些地方,希望对你会有所帮助。

mxt51220的博客 3万+

Star CCM+ 202206 (17.04) 详细安装步骤

StarCCM+ 17.04 安装包和详细安装步骤

薛定谔的alpha狗 3万+

代数拓扑与AI架构:AI应用架构师深入探索数学研究如何分析复杂系统的结构特性

随着人工智能技术的飞速发展,AI系统变得越来越复杂。AI应用架构师需要有效的工具和方法来理解、设计和优化这些复杂系统。代数拓扑作为数学的一个分支,提供了独特的视角和技术来分析复杂系统的结构特性。本文旨在帮助AI应用架构师深入了解代数拓扑,以及如何将其应用于AI架构设计中,提升对复杂系统的分析能力。首先,我们会介绍代数拓扑和AI架构相关的核心概念及其联系,通过有趣的故事引入主题,让读者轻松理解复杂概念。接着,深入探讨代数拓扑的核心算法原理,结合具体的编程语言代码示例详细阐述。

大模型应用工坊 671

瞧瞧别人的Controller,那叫一个优雅!

在实际工作中,我们需要经常跟第三方平台打交道,可能会对接第三方平台Controller接口,或者提供Controller接口给第三方平台调用。那么问题来了,如果设计一个优雅的Controller接口,能够满足:安全性、可重复调用、稳定性、好定位问题等多方面需求?今天跟大家一起聊聊设计Controller接口时,需要注意的一些地方,希望对你会有所帮助。如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下,您的支持是我坚持写作最大的动力。

4308

基于非接触式微波雷达设计的睡眠监控系统_323

本项目设计了一种基于非接触式微波雷达的睡眠监控系统,通过高精度的生理信号采集与分析,帮助用户全面了解自身的睡眠状态和健康状况。系统采用60GHz频段的R60ABD1毫米波雷达模块,实现对人体呼吸频率、心率、活动状态、体动幅度等参数的非接触式测量;结合MLX90614红外体温传感器,能够实时监测人体体温。此外,系统通过蜂鸣器报警和数据上云功能,及时向用户反馈异常生理指标,确保健康风险早期预警。数据通过ESP8266-WIFI模块上传至华为云物联网平台,用户可通过Android手机APP和Windows上位机远

500

瞧瞧别人家的Controller,那叫一个优雅

在实际工作中,我们需要经常跟第三方平台打交道,可能会对接第三方平台Controller接口,或者提供Controller接口给第三方平台调用。那么问题来了,如果设计一个优雅的Controller接口,能够满足:安全性、可重复调用、稳定性、好定位问题等多方面需求?今天跟大家一起聊聊设计Controller接口时,需要注意的一些地方,希望对你会有所帮助。

IT_1024的博客 988

学Simulink--人形机器人控制场景实例:基于Simulink的多连杆人形机器人拉格朗日动力学建模仿真

matlab编辑% 连杆长度 (m)% 躯干(髋到CoM)% 大腿% 小腿% 质量 (kg)% 转动惯量(绕质心,简化为杆)matlab编辑% 躯干CoM(假设在髋上方L_body/2处)% 左大腿CoM% 左小腿CoM% (右腿类似,略)本文完成了基于Simulink的多连杆人形机器人拉格朗日动力学建模仿真,实现了:✅ 定义7-DOF平面人形结构✅ 使用Symbolic Math Toolbox自动推导动力学方程✅ 生成。

amy_mhd的博客 398

YOLOv11改进-卷积-引入小波卷积WTConv 解决多尺度小目标问题

1.首先,WTConv利用二维Haar小波变换对输入图像进行多级分解。低频分量 (LL):捕捉图像的低频信息,如整体形状或轮廓。水平高频分量 (LH):捕捉图像中的水平边缘信息。垂直高频分量 (HL):捕捉图像中的垂直边缘信息。对角线高频分量 (HH):捕捉图像的对角线细节。在每一级的小波变换中,图像被下采样(空间分辨率减半),但频率信息得到了更细的分解。递归地执行小波变换(称为多级分解)可以得到不同尺度下的频率分量。

qq_64693987的博客 1万+

瞧瞧别人家的 Controller,那叫一个优雅!

前言在实际工作中,我们需要经常跟第三方平台打交道,可能会对接第三方平台Controller接口,或者提供Controller接口给第三方平台调用。那么问题来了,如果设计一个优雅的Controller接口,能够满足:安全性、可重复调用、稳定性、好定位问题等多方面需求?今天跟大家一起聊聊设计Controller接口时,需要注意的一些地方,希望对你会有所帮助。1. 签名为了防止Controller接口中...

方志朋的博客 148

OpenClaw用户必看:每天0成本使用OpenClaw!NVIDIA NIM免费大模型接入教程

🚀 OpenClaw接入NVIDIA NIM免费API!glm5、minimax-m2.5等大量模型任选,0成本升级AI助手!💰

XiaoqiangClub的博客 5579

瞧瞧人家用SpringBoot写的后端API接口,那叫一个优雅

日常工作中,我们开发接口时,一般都会涉及到参数校验、异常处理、封装结果返回等处理。如果每个后端开发在参数校验、异常处理等都是各写各的,没有统一处理的话,代码就不优雅,也不容易维护。所以,作为一名合格的后端开发工程师,我们需要统一校验参数,统一异常处理、统一结果返回,让代码更加规范、可读性更强、更容易维护。假设小田螺实现一个注册用户的功能,在controller 层,他会先进行校验参数,如下: 以上代码有什么问题嘛?其实没什么问题,就是校验有点辣眼睛。正常的添加用户业务还没写,参数校验就一大堆啦。假设后来

m0_67645544的博客 2288

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

瞧瞧人家写的API接口代码,那叫一个优雅!

点击上方“芋道源码”,选择“设为星标”管她前浪,还是后浪?能浪的浪,才是好浪!每天 10:33更新文章,每天掉亿点点头发...源码精品专栏原创 | Java 2021超神之路,很肝~中文详细注释的开源项目RPC 框架 Dubbo 源码解析网络应用框架 Netty 源码解析消息中间件 RocketMQ 源码解析数据库中间件 Sharding-JDBC 和 MyCAT 源码解析作业调度中间件 E...

芋艿V 739

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

上一篇: 一款优秀的轻量级任务管理工具
下一篇: MyBatis-Plus内置的主键生成策略有大坑,要注意!
公众号-芋道源码
博客等级 码龄10年 1634粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值