惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
博客园_首页
罗磊的独立博客
云风的 BLOG
云风的 BLOG
J
Java Code Geeks
Last Week in AI
Last Week in AI
D
DataBreaches.Net
Jina AI
Jina AI
博客园 - Franky
大猫的无限游戏
大猫的无限游戏
Apple Machine Learning Research
Apple Machine Learning Research
V
V2EX
D
Docker
MongoDB | Blog
MongoDB | Blog
B
Blog RSS Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
Engineering at Meta
Engineering at Meta
The Cloudflare Blog
博客园 - 三生石上(FineUI控件)
有赞技术团队
有赞技术团队
人人都是产品经理
人人都是产品经理
H
Help Net Security
T
The Blog of Author Tim Ferriss

博客园 - JackYang

I walk alone句子结构中 alone 后置的原因及同类用法解析 《用了3个月Cursor后,我删掉了自己写了10年的工具库》:从“造轮子自豪”到“承认AI写得更好”的心理崩塌与重建 2026年AI Agent时代下如何打造新一代研发体系:从熵增困境到智能工厂的范式重构(基于2025年底文章重写) AgentScope-Java 深度实践:构建企业级生产就绪的智能体应用 传统软件的AI重生:大模型时代下的系统重构与智能升级(2026实践指南)——从代码理解到数据交互,构建安全、高效、可落地的企业级AI集成架构 浅析英文复合名词“X Recording / X Logging”的翻译逻辑与本地化策略——兼论“How + 复合名词 + Works”句式的处理 浅析英文句式“How + 名词 + Works”的翻译逻辑与应用场景 会员契约论新观察:从身份标签到价值博弈——解构与评估现代会员体系 深度剖析akshare-data:OpenClaw生态中的金融数据Skill构建之道——手把手教你用akshare-data搭建个人AI量化系统 DeepSeek-V4:中国大模型的新范式革命—— 万字深度技术全景解析 深入 Java I/O 核心:BufferedInputStream 全景式源码解析与工程实践——2026 高并发时代下的性能基石,从 JDK 源码到虚拟线程(Project Loom)的协同优化 2026年前端工程化的新纪元:从Rust工具链革命到AI Agent原生架构演进 万字详文:解构 SessionBindingService —— AI智能体的“会话粘合剂” Windows 本地部署 Hermes Agent 安装教程 + 飞书接入,会自我进化AI Agent 智能体(全程避坑,亲测有效) 2026年最新、最全、可用的Docker 国内镜像源加速(截至 2026 年 4月14日 亲测可用) Java 中Jar包冲突问题及解决方案 如何自定义Spring Boot的错误页面显示? This application has no explicit mapping for /error “no main manifest attribute, in app.jar” 错误详解与解决方案 深度拆解三大 AI 核心协议:MCP、ACP、A2A,读懂智能代理全域通信底层逻辑—— 从技术原理、架构设计、落地场景到生态未来,全面揭秘 AI 智能体协作的底层标准 The Java® Virtual Machine Specification Java SE 26 Edition 中文版简介第二小节:The Java Virtual Machine The Java® Virtual Machine Specification Java SE 26 Edition 中文版简介第一小节:A Bit of History Java 中 “Error: Could not find or load main class” 错误详解与全面解决方案 云原生时代,Docker和虚拟机谁才是王者?K8s架构下的终极选型指南 2026年全网最新、最全、最好用的Excel快捷键大全:提升工作效率的必备技巧 2026年全网最新、最全的Word快捷键大全:从入门到精通 WPS快捷键大全及使用技巧 2026年最新版IntelliJ IDEA 2026.1下载、安装与配置教程: IDEA 2026.1新手使用教程(万字详解) OpenClaw源码大揭秘:WhatsApp登录工具如何用50行代码破解AI智能体的移动端困局? 2026AI Agent:AI Agent从“工具箱”到“操作系统”——深度解构AI聚合化(Aggregation)、自动化(Automation)与普惠化(Democratization
Spring Boot的全局异常处理器如何配置?
JackYang · 2026-04-13 · via 博客园 - JackYang

在 Spring Boot 中配置全局异常处理器,是实现统一错误响应、提升系统健壮性和可维护性的关键手段。核心使用两个注解:@ControllerAdvice@ExceptionHandler

下面从 原理、步骤、完整示例、最佳实践 四个方面详细说明。


一、核心原理

  • @ControllerAdvice
    是一个组合注解(包含 @Component),作用于类上,表示该类是一个全局的控制器增强器。它会自动被 Spring 容器扫描并注册为 Bean,并对所有 @Controller@RestController 中抛出的异常进行拦截。

  • @ExceptionHandler
    作用于方法上,用于指定该方法处理哪些类型的异常。可以精确到具体异常类(如 NullPointerException),也可以处理通用异常(如 Exception)。

💡 执行流程:
Controller 抛出异常 → Spring MVC 的 DispatcherServlet 捕获 → 查找匹配的 @ControllerAdvice 中的 @ExceptionHandler 方法 → 执行并返回结果。


二、配置步骤(5 步)

✅ 第 1 步:创建全局异常处理类

package com.example.demo.exception;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

// @RestControllerAdvice = @ControllerAdvice + @ResponseBody
@RestControllerAdvice
public class GlobalExceptionHandler {

    // 处理特定异常
    @ExceptionHandler(NullPointerException.class)
    public Result handleNpe(NullPointerException e) {
        return Result.error("空指针异常: " + e.getMessage());
    }

    // 处理自定义业务异常
    @ExceptionHandler(BusinessException.class)
    public Result handleBusiness(BusinessException e) {
        return Result.error(e.getCode(), e.getMessage());
    }

    // 兜底处理所有未捕获异常
    @ExceptionHandler(Exception.class)
    public Result handleGeneral(Exception e) {
        // 生产环境建议不暴露具体异常信息
        return Result.error(500, "服务器内部错误");
    }
}

🔔 注意:

  • 使用 @RestControllerAdvice 而不是 @ControllerAdvice,是为了让返回值自动转为 JSON(相当于每个方法都加了 @ResponseBody)。
  • 如果你返回的是 HTML 页面,则用 @ControllerAdvice

✅ 第 2 步:定义统一返回格式(推荐)

package com.example.demo.common;

import lombok.Data;

@Data
public class Result<T> {
    private int code;
    private String message;
    private T data;

    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<>();
        result.code = 200;
        result.message = "success";
        result.data = data;
        return result;
    }

    public static <T> Result<T> error(String message) {
        return error(500, message);
    }

    public static <T> Result<T> error(int code, String message) {
        Result<T> result = new Result<>();
        result.code = code;
        result.message = message;
        return result;
    }
}

✅ 第 3 步:(可选)定义自定义业务异常

package com.example.demo.exception;

public class BusinessException extends RuntimeException {
    private int code;

    public BusinessException(int code, String message) {
        super(message);
        this.code = code;
    }

    // getter...
}

在业务代码中抛出:

if (user == null) {
    throw new BusinessException(1001, "用户不存在");
}

✅ 第 4 步:确保包路径被扫描到

  • 全局异常处理类必须位于 Spring Boot 主启动类所在包或其子包下
  • 否则需显式指定扫描路径:
@SpringBootApplication(scanBasePackages = "com.example")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

✅ 第 5 步:(重要)启用异常转发(处理 404)

默认情况下,访问不存在的 URL 不会抛出异常,而是返回 404 页面。若想让 404 也被全局处理器捕获,需在 application.properties 中添加:

# 当没有找到处理器时,抛出 NoHandlerFoundException
spring.mvc.throw-exception-if-no-handler-found=true
# 禁用静态资源映射(避免干扰)
spring.web.resources.add-mappings=false

然后在全局处理器中添加:

@ExceptionHandler(NoHandlerFoundException.class)
public Result handle404() {
    return Result.error(404, "接口不存在");
}

三、完整示例结构

src/main/java/com/example/demo/
├── DemoApplication.java
├── controller/
│   └── UserController.java
├── exception/
│   ├── GlobalExceptionHandler.java
│   └── BusinessException.java
└── common/
    └── Result.java

四、最佳实践建议

场景建议
开发阶段 可在 handleGeneral 中返回 e.getMessage() 便于调试
生产环境 隐藏具体异常信息,只返回友好提示,避免信息泄露
异常分类 优先处理具体异常(如 ValidationException, IllegalArgumentException),最后用 Exception 兜底
日志记录 @ExceptionHandler 方法中加入 log.error("异常:", e);
HTTP 状态码 可结合 ResponseEntity 返回不同状态码:
return ResponseEntity.status(400).body(Result.error(...));

五、常见问题排查

  1. 全局异常处理器没生效?

    • 检查是否被 Spring 扫描到(包路径问题)
    • 检查是否缺少 spring-boot-starter-web 依赖
  2. 404 无法被捕获?

    • 必须配置 spring.mvc.throw-exception-if-no-handler-found=true
  3. 返回的是 HTML 而不是 JSON?

    • 确保使用的是 @RestControllerAdvice,而不是 @ControllerAdvice

✅ 总结

通过 @RestControllerAdvice + @ExceptionHandler,你可以:

  • 统一错误格式
  • 避免在每个 Controller 中写 try-catch
  • 提升 API 友好性和安全性
  • 集中记录异常日志

这是 Spring Boot 项目必备的基础配置之一。