创建全局异常处理器(Global Exception Processor)

先来了解一下什么是异常?

创建全局异常处理器(Global Exception Processor)_第1张图片

在Java程序中,异常(Exception)是指在程序执行过程中发生的非正常情况,它打断了正常的指令流;Java中的异常处理是一种用于处理程序中错误和异常情况的一种机制。
如上图所示异常主要分为两类,包括Error和Exception,两种异常有一个共同的父类是Throwable;在Exception中又分为RuntimeException(运行时异常)和CheckedException(编译时异常);
运行时异常(不受检查异常): 这类异常包括运行时异常(RuntimeException )和错误(Error );它们不需要显式地捕获,也就是说,编译器不会检查是否提供了处理这些异常的代码。
编译时异常(受检查异常): 这类异常必须被显式地捕获或者通过方法签名声明抛出。

创建全局异常处理器:

  • 确保对同类型的异常采用统一的处理方式;
  • 提高代码可维护性;
  • 减少代码冗余;
  • 增强用户的体验;
1、创建全局异常处理类
使用@ControllerAdvice(或者是@RestControllerAdvice;文章末尾介绍两个注解的区别)注解定义一个全局异常处理类,将这个类作为全局异常处理器。
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice  //控制器增强类
@Slf4j
public class ExceptionCatch {

    /**
     * 处理不可控异常
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseResult exception(Exception e){
        e.printStackTrace();
        log.error("catch exception:{}",e.getMessage());
        return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);//ResponseResult是自定义的返回结果集,AppHttpCodeEnum是自定义所有错误状态码和描述的枚举类
    }

    /**
     * 处理可控异常  自定义异常
     * @param e
     * @return
     */
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseResult exception(CustomException e){
        log.error("catch exception:{}",e);
        return ResponseResult.errorResult(e.getAppHttpCodeEnum());
    }
}
2、创建自定义异常类

定义业务异常,用于在代码中主动抛出特定错误。

public class CustomException extends RuntimeException {

    private AppHttpCodeEnum appHttpCodeEnum;

    public CustomException(AppHttpCodeEnum appHttpCodeEnum){
        this.appHttpCodeEnum = appHttpCodeEnum;
    }

    public AppHttpCodeEnum getAppHttpCodeEnum() {
        return appHttpCodeEnum;
    }
}
3、在业务代码中抛出自定义异常

在Service或Controller层按需抛出异常,由全局处理器统一处理。

@RestController
public class UserController {

    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        if (user == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        return user;
    }
}

除却上面三个步骤之外,还需要自己创建AppHttpCodeEnum枚举类(枚举类不能使用 @Data 注解生成 get方法)和ResponceResult结果返回类;在SpringMVC、SpringWebFlux和SpringBoot项目中可以通过@Order注解指定组件的加载顺序或优先级,优先级较低的处理器会先被调用。

附加知识1:@RestControllerAdvice和@ControllerAdvice区别

@RestControllerAdvice和@ControllerAdvice是Spring框架中用于处理全局异常的两个注解,它们都提供了对控制器(Controller)层进行全局异常处理的便捷方式;

@ControllerAdvice:

默认情况下,@ControllerAdvice方法返回的是视图名称或ModelAndView对象。如果需要返回JSON数据,需要配合@ResponseBody注解。

@RestControllerAdvice:

@RestControllerAdvice是@ControllerAdvice和@ResponseBody的组合注解,专为RESTful服务设计。它默认将方法的返回值序列化为JSON或XML格式。

特性

@ControllerAdvice

@RestControllerAdvice

默认返回值类型

视图名称或

ModelAndView

JSON 或 XML 数据

是否需要 @ResponseBody

需要(如果返回 JSON 数据)

不需要(默认支持 JSON 数据)

适用场景

传统 Spring MVC 项目(视图渲染)

RESTful 服务(JSON 数据返回)

组合注解

@ControllerAdvice

+

@ResponseBody

附加知识2:@ControllerAdvice 和 @ExceptionHandler 的底层实现
  • @ControllerAdvice

    • @ControllerAdvice是一个类级别的注解,标记的类会被Spring容器识别为全局组件。
    • 在Spring启动时,@ControllerAdvice类会被扫描并注册到ExceptionHandlerExceptionResolver中。
    • @ControllerAdvice类中的@ExceptionHandler方法会被收集并缓存,以便在异常发生时快速调用。
  • @ExceptionHandler

    • @ExceptionHandler是一个方法级别的注解,用于标记处理特定异常的方法。
    • 当异常发生时,ExceptionHandlerExceptionResolver会遍历所有注册的@ExceptionHandler方法,找到匹配的异常类型并调用对应的方法。
附加知识3:底层核心类
  • HandlerExceptionResolver

    • 这是Spring MVC中处理异常的接口,ExceptionHandlerExceptionResolver是其默认实现。
    • ExceptionHandlerExceptionResolver负责调用@ExceptionHandler方法。
  • ControllerAdviceBean

    • 在Spring启动时,@ControllerAdvice类会被封装为ControllerAdviceBean对象,并注册到Spring容器中。
  • ExceptionHandlerMethodResolver

    • 每个@ControllerAdvice类中的@ExceptionHandler方法会被封装为ExceptionHandlerMethodResolver对象,用于快速查找匹配的异常处理方法。

你可能感兴趣的:(java,开发语言,jvm,spring,boot)