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

本文主要是介绍Spring Boot @RestControllerAdvice全局异常处理最佳实践,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统...

前言

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

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

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

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

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

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

二、核心注解解析

1. @RestControllerAdvice

@RestControllerAdvice@ControChina编程llerAdvice@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.shjseep.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("; "));
  python  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 JSONjavascriptResult 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(jjavascriptsonPath("$.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全局异常内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于Spring Boot @RestControllerAdvice全局异常处理最佳实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155284

相关文章

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

java中新生代和老生代的关系说明

《java中新生代和老生代的关系说明》:本文主要介绍java中新生代和老生代的关系说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、内存区域划分新生代老年代二、对象生命周期与晋升流程三、新生代与老年代的协作机制1. 跨代引用处理2. 动态年龄判定3. 空间分

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语