参数校验与全局异常处理:统一错误码体系设计
参数校验与全局异常处理统一错误码体系设计用户体验最差的接口是什么传错参数返回一个java.lang.NullPointerException堆栈。用户一脸懵前端一脸懵运维一脸懵。这篇把参数校验和异常处理搭成体系让错误信息清清楚楚。一、参数校验的重要性垃圾输入导致垃圾输出Garbage In, Garbage Out。不校验参数用户的手机号传个abc你也存进去年龄传个-999你也信。等数据脏了再清理成本翻十倍。参数校验的原则在数据进入业务逻辑之前把住关卡。二、JSR303校验注解JSR303Bean Validation是一套Java标准校验规范Hibernate Validator是其实现。SpringBoot自带引入spring-boot-starter-validation即可。2.1 常用校验注解注解作用适用类型NotNull不能为null任意类型NotEmpty不能为null且不能为空串字符串、集合NotBlank不能为null且必须含非空白字符字符串Size(min,max)长度范围字符串、集合Min/Max最小值/最大值数字Range(min,max)数值范围数字Pattern(regexp)正则匹配字符串Email邮箱格式字符串Past/Future必须是过去/未来日期日期2.2 DTO校验示例DatapublicclassUserDTO{NotBlank(message用户名不能为空)Size(min3,max20,message用户名长度3-20个字符)privateStringusername;NotBlank(message密码不能为空)Pattern(regexp^(?.*[a-z])(?.*[A-Z])(?.*\\d).{8,}$,message密码至少8位需包含大小写字母和数字)privateStringpassword;NotBlank(message邮箱不能为空)Email(message邮箱格式不正确)privateStringemail;NotNull(message年龄不能为空)Min(value0,message年龄不能小于0)Max(value150,message年龄不能大于150)privateIntegerage;Pattern(regexp^1[3-9]\\d{9}$,message手机号格式不正确)privateStringphone;}Controller中使用RestControllerRequestMapping(/api/user)publicclassUserController{PostMappingpublicResultVoidaddUser(RequestBodyValidatedUserDTOdto){userService.add(dto);returnResult.success(null);}}三、Validated vs Valid这两个注解都能触发校验但有关键区别对比项ValidValidated来源JSR303标准Spring扩展分组校验不支持支持嵌套校验支持加在属性上支持用在方法参数上支持支持用在类级别不支持支持方法级校验3.1 分组校验新增时不传id修改时必须传id。同一个DTO不同场景校验规则不同——这就需要分组校验。定义分组接口publicinterfaceAddGroup{}publicinterfaceUpdateGroup{}DTO标注分组DatapublicclassUserDTO{NotNull(message修改时id不能为空,groupsUpdateGroup.class)privateLongid;// 新增时不校验修改时校验NotBlank(message用户名不能为空,groups{AddGroup.class,UpdateGroup.class})privateStringusername;NotBlank(message密码不能为空,groupsAddGroup.class)privateStringpassword;// 新增时必填修改时选填}Controller指定分组PostMappingpublicResultVoidadd(RequestBodyValidated(AddGroup.class)UserDTOdto){userService.add(dto);returnResult.success(null);}PutMappingpublicResultVoidupdate(RequestBodyValidated(UpdateGroup.class)UserDTOdto){userService.update(dto);returnResult.success(null);}3.2 嵌套校验对象内部还有对象时用Valid触发嵌套校验DatapublicclassOrderDTO{NotBlank(message订单号不能为空)privateStringorderNo;NotNull(message收货地址不能为空)Valid// 触发内部对象的校验privateAddressDTOaddress;}DatapublicclassAddressDTO{NotBlank(message省不能为空)privateStringprovince;NotBlank(message市不能为空)privateStringcity;}四、统一错误码体系设计4.1 错误码设计原则好的错误码体系需要可读、可扩展、能定位问题。推荐用5位数字编码前两位标识模块编码段模块示例00000成功0000010xxx通用错误10001 参数校验失败20xxx用户模块20001 用户不存在30xxx订单模块30001 订单已取消40xxx商品模块40001 库存不足50xxx系统错误50001 数据库异常4.2 错误码枚举实现GetterAllArgsConstructorpublicenumErrorCode{SUCCESS(00000,操作成功,HttpStatus.OK),// 通用错误 10xxxPARAM_ERROR(10001,参数校验失败,HttpStatus.BAD_REQUEST),UNAUTHORIZED(10002,未登录或登录已过期,HttpStatus.UNAUTHORIZED),FORBIDDEN(10003,无权限访问,HttpStatus.FORBIDDEN),NOT_FOUND(10004,资源不存在,HttpStatus.NOT_FOUND),// 用户模块 20xxxUSER_NOT_FOUND(20001,用户不存在,HttpStatus.BAD_REQUEST),USER_PASSWORD_ERROR(20002,密码错误,HttpStatus.BAD_REQUEST),USER_EXISTS(20003,用户名已存在,HttpStatus.BAD_REQUEST),// 系统错误 50xxxSYSTEM_ERROR(50001,系统开小差了请稍后重试,HttpStatus.INTERNAL_SERVER_ERROR);privatefinalintcode;privatefinalStringmessage;privatefinalHttpStatushttpStatus;}五、自定义业务异常GetterpublicclassBusinessExceptionextendsRuntimeException{privatefinalErrorCodeerrorCode;publicBusinessException(ErrorCodeerrorCode){super(errorCode.getMessage());this.errorCodeerrorCode;}publicBusinessException(ErrorCodeerrorCode,Stringmessage){super(message);this.errorCodeerrorCode;}}业务代码中直接抛publicUserlogin(LoginDTOdto){UseruseruserMapper.findByUsername(dto.getUsername());if(usernull){thrownewBusinessException(ErrorCode.USER_NOT_FOUND);}if(!passwordEncoder.matches(dto.getPassword(),user.getPassword())){thrownewBusinessException(ErrorCode.USER_PASSWORD_ERROR);}returnuser;}六、全局异常处理6.1 RestControllerAdvice ExceptionHandler用AOP思想统一拦截异常Controller里不写try-catchSlf4jRestControllerAdvicepublicclassGlobalExceptionHandler{/** 业务异常 */ExceptionHandler(BusinessException.class)publicResultVoidhandleBusinessException(BusinessExceptione){log.warn(业务异常: {},e.getMessage());returnResult.error(e.getErrorCode().getCode(),e.getMessage());}/** 参数校验异常 - RequestBody Validated */ExceptionHandler(MethodArgumentNotValidException.class)publicResultVoidhandleValidException(MethodArgumentNotValidExceptione){Stringmessagee.getBindingResult().getFieldErrors().stream().map(error-error.getField(): error.getDefaultMessage()).collect(Collectors.joining(; ));log.warn(参数校验失败: {},message);returnResult.error(ErrorCode.PARAM_ERROR.getCode(),message);}/** 参数校验异常 - RequestParam/PathVariable */ExceptionHandler(ConstraintViolationException.class)publicResultVoidhandleConstraintViolationException(ConstraintViolationExceptione){Stringmessagee.getConstraintViolations().stream().map(violation-violation.getMessage()).collect(Collectors.joining(; ));log.warn(参数校验失败: {},message);returnResult.error(ErrorCode.PARAM_ERROR.getCode(),message);}/** 其他未捕获异常 */ExceptionHandler(Exception.class)publicResultVoidhandleException(Exceptione){log.error(系统异常,e);returnResult.error(ErrorCode.SYSTEM_ERROR.getCode(),ErrorCode.SYSTEM_ERROR.getMessage());}}6.2 异常处理优先级ExceptionHandler匹配规则精确匹配优先异常继承关系就近原则。比如BusinessException extends RuntimeException如果同时注册了两个ExceptionHandlerExceptionHandler(BusinessException.class)// 精确匹配优先ExceptionHandler(RuntimeException.class)// 兜底抛出BusinessException时走第一个抛出其他RuntimeException走第二个。6.3 常见校验异常类型异常类型触发场景MethodArgumentNotValidExceptionRequestBody Validated 校验失败ConstraintViolationExceptionRequestParam/PathVariable Validated 校验失败BindException表单参数校验失败HttpMessageNotReadableException请求体JSON格式错误要注意类级别Validated 方法参数RequestParam上加NotBlank触发的是ConstraintViolationException不是MethodArgumentNotValidException。这是最常踩的坑之一。RestControllerValidated// 类级别开启方法参数校验publicclassCommonController{GetMapping(/check)publicResultStringcheck(RequestParamNotBlank(messagename不能为空)Stringname){returnResult.success(ok);}}6.4 完整调用链路前端请求 → 参数校验(Validated触发) → 校验失败 → MethodArgumentNotValidException → GlobalExceptionHandler捕获 → 返回错误信息 → 校验通过 → Controller → Service业务逻辑 → 业务异常 → throw BusinessException → GlobalExceptionHandler捕获 → 返回错误码 → 系统异常 → throw Exception → GlobalExceptionHandler兜底 → 返回500整个链路中Controller层零try-catch代码干干净净异常处理逻辑全部收敛到GlobalExceptionHandler一处。后期维护加异常类型只需要改这一个类这就是体系化设计的价值。

相关新闻

为什么你的AI培训材料学员完课率不到35%?揭秘神经科学验证的3层注意力锚定设计法

为什么你的AI培训材料学员完课率不到35%?揭秘神经科学验证的3层注意力锚定设计法

更多请点击: https://kaifayun.com 第一章:AI培训材料完课率困局的神经科学本质 当学习者在AI课程中频繁中断、跳过视频、跳转章节甚至永久弃课时,问题往往不在于内容难度或平台故障,而深植于人类大脑的信息处理机制之中。神经科…

2026/7/30 0:27:01阅读更多 →
AI简历初筛准确率从61%跃升至89.3%的7步落地法,含可即插即用的Python评估脚本

AI简历初筛准确率从61%跃升至89.3%的7步落地法,含可即插即用的Python评估脚本

更多请点击: https://codechina.net 第一章:AI简历初筛准确率跃升的核心洞察 AI简历初筛系统近年准确率显著提升,并非单纯依赖模型参数规模扩张,而是源于多维度协同优化的底层范式转变。关键突破点集中在语义对齐精度、领域知识注…

2026/7/30 0:27:01阅读更多 →
【图像检测】基于形态学实现红细胞的识别和放大后的边缘检测matlab代码

【图像检测】基于形态学实现红细胞的识别和放大后的边缘检测matlab代码

1 简介根据微生物显微图像中微生物形态各异,容易重叠,边缘灰度接近等特性,利用数学形态学方法的思想,用灰度形态学作初步边缘处理,用二值形态学的方法进行边缘修复.并对原始图像用其它微分算子进行边缘检测,实验结果表明基于数学形态学的边缘提取算法对于微生物显微图像边缘检测…

2026/7/30 0:25:00阅读更多 →
MFC画图工具实战:从GDI绘图到双缓冲与文档视图架构

MFC画图工具实战:从GDI绘图到双缓冲与文档视图架构

1. 项目概述:为什么选择MFC来打造一个画图工具?如果你是一个有几年C开发经验的程序员,尤其是经历过Windows桌面应用开发,那么“MFC”这三个字母对你来说,可能意味着一段复杂的情感:它古老、庞大&#xff0c…

2026/7/30 5:19:51阅读更多 →
【扣子循环流程设计终极 checklist】:覆盖12类边界场景,已验证于日均500万+流程实例

【扣子循环流程设计终极 checklist】:覆盖12类边界场景,已验证于日均500万+流程实例

更多请点击: https://codechina.net 第一章:扣子循环流程设计的核心原理与架构定位 扣子(Coze)平台中的循环流程设计并非传统编程意义上的 for/while 控制结构,而是一种基于事件驱动、节点编排与状态持久化的低代码工…

2026/7/30 5:19:51阅读更多 →
企业级AGI全栈实力获认可!奇点智能入选《2026 爱分析·Data+AI厂商全景报告》

企业级AGI全栈实力获认可!奇点智能入选《2026 爱分析·Data+AI厂商全景报告》

7月29日,爱分析正式发布《2026爱分析DataAI厂商全景报告》。奇点智能凭借在企业级AGI基础设施方向的持续深耕,入选通用Data Agent、决策智能平台、DataOps、本体平台、湖仓一体五大细分市场,在本次报告中横跨数据底座、开发运维与应用层三大层…

2026/7/30 5:19:51阅读更多 →
5步搞定!指纹浏览器批量管理账号实战教程

5步搞定!指纹浏览器批量管理账号实战教程

5步搞定!指纹浏览器批量管理账号实战教程做跨境电商的朋友都知道,多账号管理是个大难题。账号一多,关联问题就来了。很多卖家因为账号关联被平台封禁,损失惨重。今天这篇文章教你用指纹浏览器批量管理账号,5步搞定。什…

2026/7/30 5:19:51阅读更多 →
回溯法与分支限界法:从暴力搜索到智能剪枝的算法跃迁

回溯法与分支限界法:从暴力搜索到智能剪枝的算法跃迁

1. 项目概述:从“暴力穷举”到“智慧剪枝”的跃迁在算法设计的工具箱里,面对那些需要在一大堆可能性中寻找最优解或可行解的问题时,新手最容易想到的就是“暴力穷举”——把所有情况都试一遍。但稍微有点规模的问题,这种方法的计算…

2026/7/30 5:19:51阅读更多 →
铜质徽章手工制作全流程:从设计到抛光完整指南

铜质徽章手工制作全流程:从设计到抛光完整指南

这次我们来看一个关于铜质徽章制作的项目,特别适合喜欢手工制作的女孩子。这个项目主要涉及使用铜材料制作个性化徽章,整个过程结合了传统手工艺和现代设计元素,让每个人都能打造出独一无二的饰品。从项目描述来看,核心亮点在于它…

2026/7/30 5:17:50阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/29 9:47:45阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/29 7:00:19阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/29 7:58:51阅读更多 →
3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 [特殊字符]

3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 [特殊字符]

3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 🚀 【免费下载链接】TrollInstallerX A TrollStore installer for iOS 14.0 - 16.6.1 项目地址: https://gitcode.com/gh_mirrors/tr/TrollInstallerX 你是否曾经因为iOS系统的严格…

2026/7/30 0:00:58阅读更多 →
[GESP202606 四级] 扫雷

[GESP202606 四级] 扫雷

B4557 [GESP202606 四级] 扫雷 https://www.luogu.com.cn/problem/B4557 中国计算机学会(CCF)2026年6月C四级讲解——扫雷 https://www.bilibili.com/video/BV1MCMg6AEXR/ B4557 [GESP202606 四级] 扫雷 https://www.bilibili.com/video/BV1ZKTj6ZEVh/ 2…

2026/7/30 0:00:58阅读更多 →
Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:58阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/30 0:27:26阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/30 4:47:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/29 14:26:42阅读更多 →