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

news2024/11/25 8:19:14

文章目录

    • 🚃异常类型
      • 🎠显示声明异常:
        • ①:try-catch
        • ②方法签名
    • 🚃异常处理规范
      • ⚓️异常包装
      • ⚓️异常传递
      • ⚓️异常日志记录
      • ⚓️异常处理的最佳实践
    • 🚃全局异常处理
      • ⛵️优点:
      • ⛵️代码示例:
      • ⛵️注意:
    • 🚃Error类型的异常如何处理
      • ⛲️常见Error异常
      • ⛲️处理建议
        • 1. 不要捕获后不处理:
        • 2. 记录错误日志:
        • 3. 异常监控和报警:
        • 4. 优雅降级:
      • ⛲️结论


🚃异常类型

在这里插入图片描述

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

🎠显示声明异常:

①:try-catch

try {
    // 执行可能抛出Runtime异常的代码
} catch (ClassCastException e) {
    throw new CustomException("业务处理异常", e);
}

②方法签名

public void method() throws ClassCastException{
    // 可能抛出Runtime的代码
}

🚃异常处理规范

⚓️异常包装

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

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

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

⚓️异常传递

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

   代码示例:

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

⚓️异常日志记录

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

   代码示例:

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

⚓️异常处理的最佳实践

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

   代码示例:

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

🚃全局异常处理

⛵️优点:

   确保在应用程序的各个层次中,无论是控制器、服务层还是数据访问层,都能够捕获和处理异常。

⛵️代码示例:

/**
 * @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);
    }
}

⛵️注意:

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


🚃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

3. 异常监控和报警:

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

4. 优雅降级:

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

⛲️结论

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/630260.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

骨传导蓝牙耳机哪个牌子好,列举几款知名的骨传导耳机

​骨传导耳机,顾名思义就是通过骨头传播声音的耳机,由于它在声音传播方式上与传统耳机不同,不需要借助外耳、耳道,也能让耳朵更好地感受到外界的声音,在一些特殊场合下可以让使用者听到环境音。骨传导耳机虽然很小巧轻…

AI实战营:目标检测与MMDetection

目标检测的基本范式 什么是目标检测 目标检测 vs 图像分类 目标检测 in 人脸识别 目标检测 in 智慧城市 目标检测 in 自动驾驶 目标检测 in 下游视觉任务 目标检测技术的演进 基础知识 框、边界框(Bounding Box) 交并比 Intersection Over Union 目标检…

奇舞周刊第495期:软件高可用实践那些事

记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 软件高可用实践那些事儿 本文从高可用落地实践的角度,通过协作效率,技术落地和运营规范等几个层面,阐述了高可用具体实施步骤和落地细节。 浏览…

如何使用微软官方工具制作win11启动盘

windows11 启动盘制作和使用 一、启动盘制作准备二、制作步骤三、对其他电脑安装windows11系统 一、启动盘制作准备 1.至少存储空间为8GB的空白U盘 2.一台电脑 二、制作步骤 1.在官方网站中选择下载工具,选择创建windows11安装,下载完毕之后&#xff…

混淆矩阵、准确率、召回率、漏报率、误报率、F1分数

1、混淆矩阵 在二分类问题中,混淆矩阵被用来度量模型的准确率。因为在二分类问题中单一样本的预测结果只有Yes or No,即:真或者假两种结果,所以全体样本的经二分类模型处理后,处理结果不外乎四种情况,每种情…

ASP.NET Core MVC 从入门到精通之Html辅助标签(一)

随着技术的发展,ASP.NET Core MVC也推出了好长时间,经过不断的版本更新迭代,已经越来越完善,本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容,适用于初学者,在校毕业生&#xff0c…

微信小程序快速入门【一】

微信小程序快速入门【一】 文章目录 微信小程序快速入门【一】👨‍🏫内容1:背景👨‍⚖️内容2:准备工作👨‍💻内容3:新建一个小程序🍉文末推荐 👨‍&#x1f…

有关 python 切片的趣事

哈喽大家好,我是咸鱼 今天来讲一个我在实现 python 列表切片时遇到的趣事 在正式开始之前,我们先来了解一下切片(slice) 切片操作是访问序列(列表、字符串…)中元素的另一种方法,它可以访问一…

莱特兄弟的家庭教育

莱特兄弟的三个设计经验 你可以从他们如何使得一辆自行车飞行中学到很多东西 克莱夫汤普森 大家都知道莱特兄弟是第一个实现动力飞行的人——他们的飞机于1903年12月17日在北卡罗来纳州的基蒂霍克起飞。 但是在实现这一突破之前的过程? 这真是令人感兴趣,并且充满了…

【PWN · ret2text | ‘/bin/sh‘写在bss段】[HNCTF 2022 Week1]ezr0p32

目录 前言 一、题目 二、解题过程 payload的构造 三、exp 总结 前言 一直在做libc的中规中矩的题目,遇到一题有点老的类型的题目有些陌生。但其实其中原理比较简单,但是涉及到/bin/sh获取的常规操作,而自己也没整理过,于…

Git->分支

⭐作者介绍:大二本科网络工程专业在读,持续学习Java,努力输出优质文章 ⭐作者主页:逐梦苍穹 ⭐所属专栏:Git ⭐如果觉得文章写的不错,欢迎点个关注一键三连😉有写的不好的地方也欢迎指正&#x…

springboot+vue体育馆场地器材管理系统的设计与实现

体育馆管理系统有管理员和用户两个角色。用户功能有场地信息,员工信息,器材信息,留言反馈,个人中心。管理员功能有个人中心,用户管理,场地信息管理,场地类型管理,员工信息管理&#…

Redis - 缓存雪崩,缓存穿透,缓存击穿

Redis是一个完全开源的,遵守BSD协议的,高性能的key-value的数据存储结构系统,它支持数据持久化,可以将内存中的数据保存在磁盘中。不仅支持简单的key-value类型的数据结构,同事还提供list,zset,…

ChatGPT+小红书的8种高级玩法

掌握了这套万能命令,让你快速做出小红书爆款文案! 一、用ChatGPT做定位 我是一个大龄的普通人,没有什么特殊的技能,接下来,请你作为一位小红书的账号定位专家,通过与我对话的方式,为我找到我的小红书账号定…

Hive | 报错锦集

知识目录 一、写在前面✨二、Hive启动hiveserver2报错🔥三、HiveServer2启动方式✨四、Hive执行SQL语句报一大堆日志🍉五、Hive使用Load加载数据报错🍭六、Hive执行含Count的SQL语句报错🍉七、Hive执行SQL语句报/bin/java&#x1…

golang 读取csv文件到excel--推荐使用【不同实现方式】

需求:把下面的csv文件,自动写入到excel模版中, 1.自动按照csv的行数,以日期时间名问sheet名成写入到excel表的sheet名称中 2.自动复制excel的第一个sheet的所有内容,同时用csv文件的内容填充特定区域内容 xy1.csv文…

动态组件:类组件

函数组件的缺点: 第1次渲染组件,把函数执行,产生一个私有的上下文: EC(V),把解析出来的props「含children」 传递进来「但是被冻结了」,对函数返回的JSX元素「virtualDOMJ进行渲染。当我们点击按钮的时候,…

信道容量详解

本专栏包含信息论与编码的核心知识,按知识点组织,可作为教学或学习的参考。markdown版本已归档至【Github仓库:https://github.com/timerring/information-theory 】或者公众号【AIShareLab】回复 信息论 获取。 文章目录 信道容量信道容量的…

Django--创建项目与app的初步认识

目前我是想学习Django来搭建一个网站,记录一下我学初学的过程与遇到的问题。 我直接使用pycharm来创建一个Django项目,就不用在终端输入命令行的方式创建虚拟环境。 在终端输入,python manage.py runserver,点击连接web页面进行测…

为什么说python里面函数参数的默认值最好不要使用可变类型

之前发布过Python中函数的介绍:Python中函数的介绍 ,今天来做一个小小的补充说明:为什么说python里面函数参数的默认值最好不要使用可变类型 Python中,函数参数的默认值是在函数定义时计算的,而不是在每次函数调用时计…