全局异常处理需按环境区分错误详情:开发环境返回完整堆栈供调试,生产环境隐藏技术细节、仅展示友好提示,并通过日志(含traceid)记录关键信息;响应体结构一致,debuginfo等字段按profile条件填充,严禁生产响应暴露敏感信息。

在全局异常处理中区分生产与开发环境,核心是控制错误详情的暴露程度:开发环境需要完整堆栈和原始信息辅助调试,生产环境必须隐藏技术细节、只返回用户友好的提示,同时确保关键信息仍能被日志系统捕获用于排查。
通过 Spring Profile 动态切换响应内容
Spring Boot 支持基于 profile 的条件化配置,可在同一个 @ExceptionHandler 方法中根据当前环境决定返回哪些字段:
- 使用
@Profile("dev")或@Profile("!prod")标记开发专用逻辑(如打印堆栈) - 在统一响应体(如
ApiResponse)中,对stackTrace或detail字段做条件赋值:开发时填充,生产时置为null或空字符串 - 避免用
if (env.equals("dev"))硬编码判断,优先使用@ConditionalOnProperty或 profile-aware bean 注入
日志级别与输出渠道分离
错误详情不靠 HTTP 响应传递,而靠日志系统承载:
- 开发环境:
log.error("业务异常", e)输出完整异常链,含堆栈和 cause - 生产环境:仅记录关键标识(如 traceId、错误码、简要消息),堆栈写入独立 error 日志文件,不进标准输出或监控大盘
- 借助 MDC(Mapped Diagnostic Context)注入请求唯一 ID,让日志可追溯,无需把堆栈塞进 API 响应
自定义错误响应体的环境感知字段
响应结构本身保持一致,但内部字段按环境填充:
- 始终返回
code(业务错误码)、message(用户可见提示)、timestamp - 增加可选字段
debugInfo:开发环境填入e.toString()或e.getStackTrace()的前几行;生产环境直接忽略该字段或设为null - 前端只读取
message展示,运维通过 traceId 查日志,无需解析响应体中的技术细节
禁止在生产响应中返回敏感信息
这是硬性安全边界,不能依赖“约定”,需代码级拦截:
- 检查异常消息是否含数据库表名、SQL 片段、文件路径、用户名、密钥关键词等,自动过滤或替换为泛化描述
- 对
SQLException、ValidationException等常见类型做白名单处理:只允许返回预设的友好提示,不透传原始 message - 使用
StringSanitizer工具类统一清洗,避免每个 handler 单独判断
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











