java异常处理设计

本文探讨了Java中异常的分类(检查异常和非检查异常),何时抛出异常的原则,以及如何在SpringAOP中实现全局异常处理。作者提供了设计异常处理模式的详细步骤,包括定义异常枚举、自定义异常类和在代码中正确处理异常。
摘要由CSDN通过智能技术生成

异常的继承体系

java 中的异常的超类是 java.lang.Throwable(后文省略为 Throwable), 他有俩自类Exception和Error,Error是由jvm管理,我们不需要考虑。
RuntimeException是Exception的子类。

  • 检查异常(Checked Exceptions): 继承自 Exception 但不继承自 RuntimeException 的异常属于受检异常。必须通过 try-catch 块或者在方法签名中使用 throws 关键字来显式处理这些异常,否则编译器会报错。也称为“编译时异常”,编译器在编译期间检查的那些异常。由于编译器“检查”这些异常以确保它们得到处理,因此称为“检查异常”。

  • 非受检异常(Unchecked Exceptions): 继承自 RuntimeException 的异常属于非受检异常。可以捕获处理或者向上传递。
    RuntimeException 是非受检异常的根类,包括诸如 NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException 等运行时错误。通常,这些异常表示编程错误或者其他无法在编译时检测到的问题。
    在这里插入图片描述

什么时候应该抛出异常?

抛出异常的目标是清晰地表达在程序执行期间发生的问题,并提供给上层调用者或者异常处理机制足够的信息以便进行处理或者修复。

  1. 特定的业务逻辑异常。例如,银行应用程序中的 InsufficientFundsException 表示账户余额不足。
  2. 状态机无法转向调用者提供的目标状态。
  3. 非法参数

实践

  • 抛出带状态码 RumtimeException 异常
  • 抛出指定类型的 RuntimeException 异常

服务中抛出什么样的异常就自定义一个指定的异常错误,然后在进行抛出异常。

异常设计的准则

  1. 不可以将异常处理作为系统流程的一部分。

  2. 避免过度细分异常,提高重用性。

  3. 避免过度使用 catch(Exception e) 来捕获所有异常。

  4. 不要同时记录和抛出异常,因为异常会打印多次,正确的处理方式要么抛出异常要么记录异常,如果抛出异常,不要原封不动的抛出,可以自定义异常抛出。

  5. 自定义异常不要丢弃原有异常,应该将原始异常传入自定义异常中。
    throw MyException(“my exception”, e);

  6. 自定义异常尽量不要使用检查异常。

  7. 尽可能晚的捕获异常,如非必要,建议所有的异常都不要在下层捕获,而应该由最上层捕获并统一处理这些异常。。

  8. 为了避免重复输出异常日志,建议所有的异常日志都统一交由最上层输出。就算下层捕获到了某个异常,如非特殊情况,也不要将异常信息输出,应该交给最上层统一输出日志。

应用程序中定义的异常应该分为两类

业务异常:用户能够看懂并且能够处理的异常,比如用户没有登录,提示用户登录即可。
系统异常:用户看不懂需要程序员处理的异常,比如网络连接超时,需要程序员排查相关问题。
在这里插入图片描述

spring的aop实现异常全局处理

/**
* http 接口异常处理类
*/
@Slf4j
@RestControllerAdvice("org.example.controller")
public class HttpExceptionHandler {
    /**
     * 处理业务异常
     * @param request 请求参数
     * @param e 异常
     * @return Result
     */
    @ExceptionHandler(value = BizException.class)
    public Object bizExceptionHandler(HttpServletRequest request, BizException e) {
        log.warn("业务异常:" + e.getMessage() , e);
        return Result.fail(e.getCode(), e.getMessage());
    }
    /**
     * 处理系统异常
     * @param request 请求参数
     * @param e 异常
     * @return Result
     */
    @ExceptionHandler(value = SystemException.class)
    public Object systemExceptionHandler(HttpServletRequest request, SystemException e) {
        log.error("系统异常:" + e.getMessage() , e);
        return Result.fail(e.getCode(), e.getMessage());
    }
    /**
     * 处理未知异常
     * @param request 请求参数
     * @param e 异常
     * @return Result
     */
    @ExceptionHandler(value = Throwable.class)
    public Object unknownExceptionHandler(HttpServletRequest request, Throwable e) {
        log.error("未知异常:" + e.getMessage() , e);
        return Result.fail(e.getMessage());
    }
}

在 HttpExceptionHandler 类中,@RestControllerAdvice = @ControllerAdvice + @ResponseBody ,如果有其他的异常需要处理,只需要定义@ExceptionHandler注解的方法处理即可。

设计异常处理模式的流程

第一步:设计异常枚举常量: 定义一组异常枚举常量,用于标识不同类型的异常。每个枚举常量可以包含异常代码、异常信息等信息。

public enum ErrorCode {
    INVALID_INPUT("1001", "Invalid input"),
    DATA_NOT_FOUND("2001", "Data not found"),
    // 其他异常类型...
    ;

    private final String code;
    private final String message;

    ErrorCode(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public String getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

第二步:设计异常类: 创建自定义异常类,通常继承自 Exception 类。在异常类中可以定义一些构造方法,方便在抛出异常时传递异常信息。

public class CustomException extends Exception {
    private final ErrorCode errorCode;

    public CustomException(ErrorCode errorCode) {
        super(errorCode.getMessage());
        this.errorCode = errorCode;
    }

    public ErrorCode getErrorCode() {
        return errorCode;
    }
}

第三步:在异常点抛出异常: 在代码中检测到错误或异常情况时,通过抛出自定义异常来通知调用方。

public class ExampleService {
    public void performAction(String input) throws CustomException {
        if (input == null || input.isEmpty()) {
            throw new CustomException(ErrorCode.INVALID_INPUT);
        }
        // 其他业务逻辑...
    }
}

第四步:捕获处理异常: 在调用方代码中使用 try-catch 块捕获抛出的异常,并根据异常类型进行相应的处理。

public class Main {
    public static void main(String[] args) {
        ExampleService exampleService = new ExampleService();
        try {
            exampleService.performAction(null);
        } catch (CustomException e) {
            System.out.println("Caught exception: " + e.getErrorCode().getCode() + " - " + e.getMessage());
            // 根据异常类型进行处理...
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值