Spring Boot @RestControllerAdvice全局异常处理最佳实践

 更新时间:2025年07月02日 15:39:28   作者:小羊Go  
本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统一响应格式、异常分类处理及减少冗余代码的重要性,涵盖注解解析、实战代码、最佳实践,感兴趣的朋友一起看看吧

前言

在开发Spring Boot应用时,优雅地处理异常是保证系统健壮性和用户体验的关键。本文将详细介绍如何使用@RestControllerAdvice实现全局异常处理,并分享实际开发中的最佳实践。

一、为什么要使用全局异常处理?

  1. 代码复用:避免在每个Controller中重复编写try-catch

  2. 统一响应格式:标准化错误返回结构

  3. 异常分类处理:针对不同类型异常定制处理逻辑

  4. 减少样板代码:让业务逻辑更专注于核心流程

二、核心注解解析

1. @RestControllerAdvice

@RestControllerAdvice@ControllerAdvice@ResponseBody的组合注解,主要功能:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ControllerAdvice
@ResponseBody
public @interface RestControllerAdvice {
    // 可指定包路径或控制器类
    @AliasFor(annotation = ControllerAdvice.class)
    String[] value() default {};
}

2. @ExceptionHandler

用于标注处理特定异常的方法:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
    // 指定要处理的异常类数组
    Class<? extends Throwable>[] value() default {};
}

三、实战代码实现

以下是完整全局异常处理器实现:

他会对于ExceptionHandler指定的异常进行处理,底层是通过AOP的技术实现的。

import com.sheep.shrine.result.JSONResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
 * 全局异常处理器
 * @RestControllerAdvice = @ControllerAdvice + @ResponseBody
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 处理自定义业务异常
     */
    @ExceptionHandler(GlobleException.class)
    public JSONResult handleBusinessException(GlobleException e) {
        e.printStackTrace();
        return JSONResult.error(e.getMessage());
    }
    /**
     * 处理所有未捕获异常
     */
    @ExceptionHandler(Exception.class)
    public JSONResult handleSystemException(Exception e) {
        e.printStackTrace();
        return JSONResult.error("系统异常,正在殴打程序员...", "50000");
    }
}

四、进阶使用技巧

1. 异常分类处理

// 处理数据校验异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public JSONResult handleValidException(MethodArgumentNotValidException e) {
    String message = e.getBindingResult().getAllErrors()
            .stream()
            .map(DefaultMessageSourceResolvable::getDefaultMessage)
            .collect(Collectors.joining("; "));
    return JSONResult.error(message);
}
// 处理数据库异常
@ExceptionHandler(DataAccessException.class)
public JSONResult handleDataAccessException(DataAccessException e) {
    log.error("数据库操作异常", e);
    return JSONResult.error("数据库服务异常");
}

2. 响应状态码控制

@ExceptionHandler(UnauthorizedException.class)
@ResponseStatus(HttpStatus.FORBIDDEN)
public JSONResult handleUnauthorizedException(UnauthorizedException e) {
    return JSONResult.error("无权限访问", "403");
}

3. 日志记录优化

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(Exception.class)
    public JSONResult handleException(Exception e) {
        log.error("系统异常: {}", e.getMessage(), e);
        return JSONResult.error("系统繁忙");
    }
}

五、最佳实践建议

  1. 异常分类细化:不要只用一个Exception.class处理所有异常

  2. 敏感信息过滤:生产环境不要返回堆栈信息

  3. 错误码规范:制定统一的错误码体系

  4. 日志完善:关键异常必须记录完整上下文

  5. 性能考虑:异常处理逻辑应尽量轻量

六、常见问题解答

Q1:全局异常处理器不生效怎么办?

  • 检查是否在Spring扫描路径下

  • 确认没有其他异常处理器覆盖

  • 检查是否有Filter提前处理了异常

Q2:如何测试全局异常处理器?

@SpringBootTest
class GlobalExceptionHandlerTest {
    @Autowired
    private WebApplicationContext context;
    private MockMvc mockMvc;
    @BeforeEach
    void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
    }
    @Test
    void testBusinessException() throws Exception {
        mockMvc.perform(get("/api/test-exception"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$.code").value("50000"));
    }
}

Q3:如何与FeignClient集成?

@Configuration
public class FeignConfig {
    @Bean
    public ErrorDecoder errorDecoder() {
        return (methodKey, response) -> {
            // 将Feign异常转换为自定义异常
            return new BusinessException("远程服务调用失败");
        };
    }
}

七、总结

通过@RestControllerAdvice实现全局异常处理可以:

  1. 提高代码可维护性

  2. 增强系统健壮性

  3. 改善用户体验

  4. 便于监控报警

到此这篇关于Spring Boot @RestControllerAdvice全局异常处理最佳实践的文章就介绍到这了,更多相关Spring Boot @RestControllerAdvice全局异常内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java连接合并2个数组(Array)的5种方法例子

    Java连接合并2个数组(Array)的5种方法例子

    最近在写代码时遇到了需要合并两个数组的需求,突然发现以前没用过,于是研究了一下合并数组的方式,这篇文章主要给大家介绍了关于Java连接合并2个数组(Array)的5种方法,需要的朋友可以参考下
    2023-12-12
  • Java中消息队列任务的平滑关闭详解

    Java中消息队列任务的平滑关闭详解

    对于消息队列的监听,我们一般使用Java写一个独立的程序,在Linux服务器上运行。程序启动后,通过消息队列客户端接收消息,放入一个线程池进行异步处理,并发的快速处理。这篇文章主要给大家介绍了关于Java中消息队列任务的平滑关闭的相关资料,需要的朋友可以参考下。
    2017-11-11
  • java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.setXmlVersion问题解决方法

    java.lang.AbstractMethodError: org.apache.xerces.dom.Documen

    这篇文章主要介绍了java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.setXmlVersion问题解决方法,导致本文问题的原因是缺少一个xerces.jar jar包,需要的朋友可以参考下
    2015-03-03
  • Java嵌套for循环优化方案分享

    Java嵌套for循环优化方案分享

    介绍了Java中嵌套for循环的优化方法,包括减少循环次数、合并循环、使用更高效的数据结构、并行处理、预处理和缓存、算法优化、尽量减少对象创建以及本地变量优化,通过这些方法,可以显著提升程序的执行效率,文章还以动态规划优化示例——最长递增子序列
    2025-03-03
  • Spring之关于PropertyDescriptor的扩展剖析

    Spring之关于PropertyDescriptor的扩展剖析

    这篇文章主要介绍了Spring之关于PropertyDescriptor的扩展剖析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • java生成图片验证码功能

    java生成图片验证码功能

    最近在用ssm框架做一个管理系统,做到登录验证时,需要实现图片验证码功能,今天小编给大家分享基于java制作的图片验证码功能,感兴趣的朋友一起看看吧
    2019-12-12
  • Java异步编程Future应用方式

    Java异步编程Future应用方式

    Java中的Future接口用于构建复杂并行操作,它允许异步执行任务,并在需要时获取结果,通过Future接口,可以避免多线程编程中的一些常见问题,如线程执行顺序和结果获取的复杂性,然而,在使用Future时需要注意,并行执行可能会变为串行执行,特别是在使用get()方法时
    2025-02-02
  • Idea打不了断点如何解决

    Idea打不了断点如何解决

    这篇文章主要介绍了Idea打不了断点如何解决的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 快速解决springboot在yml配置了启动端口但启动还是8080问题

    快速解决springboot在yml配置了启动端口但启动还是8080问题

    这篇文章主要介绍了快速解决springboot在yml配置了启动端口但启动还是8080问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03
  • 详解SpringIOC容器相关知识

    详解SpringIOC容器相关知识

    这篇文章主要记录自己在狂神说java中的学习情况,文章里有自己学习的理解和扩展,新手难免有理解偏差或者错误,恳请大佬指正下,需要的朋友可以参考下
    2021-05-05

最新评论