在Java里如何设计统一的异常处理方案_Java异常封装思路说明

发布时间 - 2026-01-29 00:00:00    点击率:
@ControllerAdvice是统一异常处理的主流选择,Filter仅适用于非Spring MVC流量或底层异常;业务异常应继承RuntimeException,系统异常继承Exception;ResponseBodyAdvice负责成功响应包装,@ControllerAdvice处理异常响应。

统一异常处理该用@ControllerAdvice还是Filter

Spring Boot项目里,@ControllerAdvice 是拦截 Controller 层异常的主流选择,它天然适配 Spring MVC 的异常传播链,能捕获 @ExceptionHandler 显式声明的异常类型,也能配合 @ResponseStatus 返回对应 HTTP 状态码。而 Filter 在 DispatcherServlet 前就介入,拿不到 Spring 的上下文和返回值封

装能力,强行在 Filter 里做全局异常格式化会导致重复响应、状态码错乱,甚至 HttpMessageNotWritableException

真正需要 Filter 的场景只有一种:非 Spring MVC 流量(比如直接访问静态资源、Actuator 端点出错)或必须在请求头解析前就拦截的底层异常(如非法字符导致的 IllegalStateException)。日常业务异常统一走 @ControllerAdvice 就够了。

自定义异常类要不要继承RuntimeException

要,但得按语义分层。业务异常(如参数校验失败、余额不足)应继承 RuntimeException,避免强制 try-catch 干扰主流程;系统异常(如数据库连接中断、Redis 超时)建议继承 Exception,并在调用处显式捕获后转为统一业务异常返回,防止底层错误暴露给前端。

关键点:

  • 所有自定义异常必须带 errorCode 字段(String 或 int),用于前端分流或日志追踪
  • 不要重写 getMessage() 去拼接错误码——前端不需要看到“ERR_001: 用户不存在”,只要 “用户不存在”
  • 构造函数里把 errorCode 存为 final 字段,避免子类篡改

ResponseBodyAdvice 与 @ControllerAdvice 怎么分工

@ControllerAdvice 负责“出错怎么报”,ResponseBodyAdvice 负责“没出错怎么包”。后者常被误用来做统一成功响应包装(如 {“code”:0, “data”:xxx}),但它不处理异常路径——异常发生时,ResponseBodyAdvice 根本不会执行。

所以: - 成功响应统一包装用 ResponseBodyAdvice(注意排除异常类型,用 !ClassUtils.isAssignableValue(Exception.class, body) 判断) - 异常响应统一格式用 @ControllerAdvice + @ExceptionHandler - 两者共用同一套响应结构体(如 Result),避免前后端对“成功/失败”结构理解错位

日志记录和敏感信息过滤怎么做

@ExceptionHandler 方法里打日志,别在自定义异常的构造器里打——异常可能被吞掉(比如被更上层的 @ExceptionHandler 拦截),导致日志缺失。

实操要点:

  • 记录 exception.getClass().getName()exception.getMessage(),但绝不打印 exception.printStackTrace() 到业务日志(堆栈太长,干扰排查)
  • SQLExceptionHttpClientErrorException 这类带原始请求/响应的异常,提取关键字段(如 SQL 状态码、HTTP 状态码),过滤掉敏感 header(AuthorizationCookie
  • 使用 MDC(Mapped Diagnostic Context)注入 traceId,确保异常日志能和正常请求日志串联

统一异常方案最难的部分不是代码怎么写,而是异常分类边界的定义——比如“库存扣减失败”该算业务异常还是系统异常?这直接影响重试策略、告警级别和前端提示方式。边界模糊时,宁可多建一个异常子类,也不要靠 if-else 分支硬扛。


# java  # redis  # 前端  # cookie  # app  # 后端  #   # 状态码  # java异常  # spring mvc  # red  # mvc  # sql  # spring  # String  # if  # 封装  # 子类  # 构造函数 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel怎么实现微信登录_Laravel Socialite第三方登录集成  Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程  Zeus浏览器网页版官网入口 宙斯浏览器官网在线通道  Android仿QQ列表左滑删除操作  如何用IIS7快速搭建并优化网站站点?  laravel怎么通过契约(Contracts)编程_laravel契约(Contracts)编程方法  html如何与html链接_实现多个HTML页面互相链接【互相】  Angular 表单中正确绑定输入值以确保提交与验证正常工作  广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?  Laravel怎么集成Vue.js_Laravel Mix配置Vue开发环境  如何快速搭建自助建站会员专属系统?  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  潮流网站制作头像软件下载,适合母子的网名有哪些?  微信小程序 配置文件详细介绍  如何将凡科建站内容保存为本地文件?  如何在香港服务器上快速搭建免备案网站?  Laravel如何使用Livewire构建动态组件?(入门代码)  原生JS实现图片轮播切换效果  为什么php本地部署后css不生效_静态资源加载失败修复技巧【技巧】  在线教育网站制作平台,山西立德教育官网?  如何破解联通资金短缺导致的基站建设难题?  高端企业智能建站程序:SEO优化与响应式模板定制开发  Laravel怎么实现搜索高亮功能_Laravel结合Scout与Algolia全文检索【实战】  如何在Windows服务器上快速搭建网站?  弹幕视频网站制作教程下载,弹幕视频网站是什么意思?  Laravel如何生成URL和重定向?(路由助手函数)  Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理  Laravel如何配置和使用队列处理异步任务_Laravel队列驱动与任务分发实例  Laravel如何发送系统通知_Laravel Notifications实现多渠道消息通知  教你用AI润色文章,让你的文字表达更专业  免费网站制作appp,免费制作app哪个平台好?  Laravel Sail是什么_基于Docker的Laravel本地开发环境Sail入门  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程  如何快速搭建二级域名独立网站?  Laravel怎么使用artisan命令缓存配置和视图  网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  猎豹浏览器开发者工具怎么打开 猎豹浏览器F12调试工具使用【前端必备】  如何做网站制作流程,*游戏网站怎么搭建?  如何在IIS中新建站点并配置端口与物理路径?  香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧  Laravel模型关联查询教程_Laravel Eloquent一对多关联写法  独立制作一个网站多少钱,建立网站需要花多少钱?  html5源代码发行怎么设置权限_访问权限控制方法与实践【指南】  如何快速辨别茅台真假?关键步骤解析  如何快速搭建虚拟主机网站?新手必看指南  JS实现鼠标移上去显示图片或微信二维码  如何在Windows 2008云服务器安全搭建网站?  如何快速查询域名建站关键信息?  如何在搬瓦工VPS快速搭建网站?