• java异常 | 处理规范、全局异常、Error处理



    🚃异常类型

    在这里插入图片描述

    异常大类发生场景
    Throwable所有异常的根类
    Error由虚拟机或系统引发的异常
    ExceptionRuntimeException :运行时异常,不需要显式捕获或声明;非RuntimeException:必须显式捕获或声明的异常

    🎠显示声明异常:

    ①:try-catch
    try {
        // 执行可能抛出Runtime异常的代码
    } catch (ClassCastException e) {
        throw new CustomException("业务处理异常", e);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    ②方法签名
    public void method() throws ClassCastException{
        // 可能抛出Runtime的代码
    }
    
    • 1
    • 2
    • 3

    🚃异常处理规范

    ⚓️异常包装

       规范:
           捕获异常后,将其包装为自定义异常,并添加更多的上下文信息。

    1. 按业务划分异常:可以更好地反映业务逻辑和场景,使得异常的处理更加准确和精细化。例如,在电商应用中可以定义订单异常、库存异常、支付异常等来表示不同的业务异常情况。
    2. 按层划分异常:可以更好地将异常的处理与各层的责任分离开来。例如,在多层架构中,可以定义表示数据访问层异常的数据库异常、表示业务逻辑层异常的业务异常、表示展示层异常的界面异常等。
    3. 按其他需求划分异常常:例如按照功能模块、错误类型、系统模块等进行划分。

       代码示例:
    try {
        // 执行可能抛出异常的代码
    } catch (Exception e) {
        // 将异常包装为自定义异常,添加更多上下文信息
        throw new CustomException("业务处理异常", e);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ⚓️异常传递

       规范:
           在方法签名中明确声明可能抛出的受检异常,以便上层调用者知晓,并在适当的层次处理异常。

       代码示例:

    public void method() throws IOException {
       // 可能抛出IOException的代码
    }
    
    • 1
    • 2
    • 3

    ⚓️异常日志记录

       规范:
           在异常处理过程中,记录异常相关的信息,如异常类型、异常堆栈信息、触发异常的位置等。

       代码示例:

    try {
       // 可能抛出异常的代码
    } catch (Exception e) {
       logger.error("异常类型: " + e.getClass().getSimpleName());
       logger.error("异常堆栈信息: ", e);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ⚓️异常处理的最佳实践

       规范:
           避免捕获过宽的异常类型,尽量捕获具体的异常类型;在合适的地方捕获异常,不要滥用异常捕获;及时关闭资源,避免资源泄露等。

       代码示例:

    try {
       // 可能抛出特定异常的代码
    } catch (SpecificException se) {
       // 处理特定异常的逻辑
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    🚃全局异常处理

    ⛵️优点:

       @ControllerAdvice+@ExceptionHandler注解确保捕获和处理Controller层的异常。

    ⛵️代码示例:

    /**
     * @Description: 全局异常类
     * @Version: 1.0
     */
     
    @ControllerAdvice//使用该注解表示开启了全局异常的捕获
    public class GlobalExceptionHandler {
        private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
        /**
         * 处理空指针的异常
         *
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value = NullPointerException.class)
        @ResponseBody
        public FrontResult exceptionHandler(HttpServletRequest req, NullPointerException e) {
            logger.error("URL : " + req.getRequestURL().toString());
            logger.error("HTTP_METHOD : " + req.getMethod());
            logger.error("发生空指针异常!原因是:", e);
            return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResultMsgEnum.EXECUTE_FAIL.getMsg());
        }
    
        /**
         * 处理索引越界异常
         *
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value = IndexOutOfBoundsException.class)
        @ResponseBody
        public FrontResult exceptionHandler(HttpServletRequest req, IndexOutOfBoundsException e) {
            logger.error("URL : " + req.getRequestURL().toString());
            logger.error("HTTP_METHOD : " + req.getMethod());
            logger.error("索引越界异常!原因是:", e);
            return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResultMsgEnum.EXECUTE_FAIL.getMsg());
        }
    
        /**
         * 处理类未找到异常
         *
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value = ClassNotFoundException.class)
        @ResponseBody
        public FrontResult exceptionHandler(HttpServletRequest req, ClassNotFoundException e) {
            logger.error("URL : " + req.getRequestURL().toString());
            logger.error("HTTP_METHOD : " + req.getMethod());
            logger.error("发生类未找到异常!原因是:", e);
            return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResultMsgEnum.EXECUTE_FAIL.getMsg());
        }
    
        /**
         * 处理SQL异常
         *
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value = SQLException.class)
        @ResponseBody
        public FrontResult exceptionHandler(HttpServletRequest req, SQLException e) {
            logger.error("URL : " + req.getRequestURL().toString());
            logger.error("HTTP_METHOD : " + req.getMethod());
            logger.error("发生SQL异常!原因是:", e);
            return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResultMsgEnum.EXECUTE_FAIL.getMsg());
        }
    
        /**
         * 处理IO异常
         *
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value = IOException.class)
        @ResponseBody
        public FrontResult exceptionHandler(HttpServletRequest req, IOException e) {
            logger.error("URL : " + req.getRequestURL().toString());
            logger.error("HTTP_METHOD : " + req.getMethod());
            logger.error("发生IO异常!原因是:", e);
            return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResultMsgEnum.EXECUTE_FAIL.getMsg());
        }
    
        /**
         * 处理其他异常
         *
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value = Exception.class)
        @ResponseBody
        public FrontResult exceptionHandler(HttpServletRequest req, Exception e) {
            logger.error("URL : " + req.getRequestURL().toString());
            logger.error("HTTP_METHOD : " + req.getMethod());
            logger.error("未知Exception!原因是:", e);
            return FrontResult.getExceptionResult(ResultCodeEnum.FAIL.getCode(), ResultMsgEnum.EXECUTE_FAIL.getMsg());
        }
    
        /**
         * 处理Error异常
         *
         * @param req
         * @param e
         * @return
         */
        @ExceptionHandler(value = Error.class)
        @ResponseBody
        public FrontResult errorHandler(HttpServletRequest req, Error e) {
            logger.error("URL : " + req.getRequestURL().toString());
            logger.error("HTTP_METHOD : " + req.getMethod());
            logger.error("未知Error!原因是:", e);
            // 发送警报通知
            sendAlertNotification();
            
            // 执行清理操作(关闭数据库连接、释放资源等)
            cleanup();
            
            // 终止应用程序
            System.exit(1);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128

    ⛵️注意:

       全局异常处理应该是最后的防线,用于捕获未被处理的异常。在应用程序的各个层次中,尽量在局部进行异常处理,以确保能够在发生异常时立即采取适当的措施


    🚃Error类型的异常如何处理

       对于Java中的Error类型异常,通常是指严重的系统级错误,它们通常无法被应用程序处理或恢复,并且可能会导致应用程序的非正常终止,所以Error类型的异常一定要被开发人员重视。

    ⛲️常见Error异常

    类型发生场景
    OutOfMemoryError内存溢出错误,表示应用程序在申请内存时无法满足需求
    StackOverflowError栈溢出错误,表示方法调用的层级过深,导致栈空间不足
    NoClassDefFoundError找不到类定义错误,表示在运行时无法找到所需的类文件
    NoSuchMethodError找不到方法错误,表示在运行时无法找到所需的方法
    ExceptionInInitializerError表示在静态初始化期间发生异常
    IllegalAccessError表示非法访问类、字段或方法
    AbstractMethodError表示抽象方法没有被实现或覆盖
    AssertionError断言错误,表示断言语句失败

    ⛲️处理建议

       以下是处理Error类型异常的一些常见做法:

    1. 不要捕获后不处理:

       Error类型的异常会导致应用程序无法正常运行,处理这些异常的主要目标是尽快终止程序的执行,以避免进一步的损害或数据丢失。即时捕获记录错误信息后,也应继续抛出异常,让这些异常冒泡到应用程序的顶层,由Java虚拟机或操作系统来处理。

    2. 记录错误日志:

       当发生Error类型异常时,及时记录错误信息到日志中,以便后续的故障排查和分析。可以使用日志框架(如log4j、logback等)、或java虚拟机的错误日志来记录错误信息,并确保日志配置正确,以便及时获取异常的详细信息。

    //配置java虚拟机错误日志
    java -XX:ErrorFile=/path/to/error.log -jar xxxxx.jar
    
    • 1
    • 2
    3. 异常监控和报警:

       设置合适的异常监控和报警机制,当系统发生Error类型异常时,及时通知相关人员或团队尽快处理。可以使用监控工具和服务(如Prometheus、Grafana等)来实现异常监控和报警功能。

    4. 优雅降级:

       在面对严重的Error异常时,可以考虑进行优雅降级处理。例如,通过切换到备用服务、提供默认值或警告消息等方式,尽量保持系统的可用性,并减少对用户的影响。

    ⛲️结论

       在面对Error异常时,重要的是及时记录、报警、定位问题,并采取适当的措施来保证系统的稳定性和可用性,及时发现及时处理。

  • 相关阅读:
    level2接口有什么用?是如何获取A股行情数据的?
    【数据仓库工具箱】DW/BI系统的核心元素和基本要求
    高校 Web 站点网络安全面临的主要的威胁
    用HTML+CSS做一个漂亮简单的轻量级图片相册博客网站(web前端期末大作业)
    【码神之路】【Golang】博客网站的搭建【学习笔记整理 持续更新...】
    【CNN记录】tensorflow slice和strided_slice
    Java实现常见排序算法
    Java代理
    MySql版本号查看命令
    nodejs+vue全国公考岗位及报考人数分析
  • 原文地址:https://blog.csdn.net/CharmaineXia/article/details/130841976