Java-异常:不恰当的异常转换、不充分的日志记录、过度或不当的异常捕获

news2024/11/25 12:53:29

Java-异常:不恰当的异常转换、不充分的日志记录、过度或不当的异常捕获

  • Java-异常:不恰当的异常转换、不充分的日志记录、过度或不当的异常捕获
    • 一、前期准备
    • 二、案例分析
      • 1、不恰当的异常转换
      • 2、不充分日志记录
      • 3、过度或不当的异常捕获
    • 三、正确处理方式
      • 1、方式1
      • 2、方式2

Java-异常:不恰当的异常转换、不充分的日志记录、过度或不当的异常捕获

异常相关概念可以参考:秋刀鱼不做梦-Java 异常处理详解

在这里,我重点针对异常不恰当的转换不充分的日志记录过度或不当的异常捕获的问题来说

一、前期准备

封装API的响应结果

@Data
@AllArgsConstructor
public class APIResponse<T> {
    private boolean success;
    private T data;
    private int code;
    private String message;
}

自定义异常

public class BusinessException extends RuntimeException {

    private int code;

    public BusinessException(String message, int code) {
        super(message);
        this.code = code;
    }

    public int getCode() {
        return code;
    }
}

定义全局异常处理器

@RestControllerAdvice
@Slf4j
public class RestControllerExceptionHandler {

    private static int GENERIC_SERVER_ERROR_CODE = 2000;
    private static String GENERIC_SERVER_ERROR_MESSAGE = "服务器忙,请稍后再试";

    @ExceptionHandler
    public APIResponse handle(HttpServletRequest req, HandlerMethod method, Exception ex) {
        if (ex instanceof BusinessException) {
            BusinessException exception = (BusinessException) ex;
            log.warn(String.format("访问 %s -> %s 出现业务异常!", req.getRequestURI(), method.toString()), ex);
            return new APIResponse(false, null, exception.getCode(), exception.getMessage());
        } else {
            log.error(String.format("访问 %s -> %s 出现系统异常!", req.getRequestURI(), method.toString()), ex);
            return new APIResponse(false, null, GENERIC_SERVER_ERROR_CODE, GENERIC_SERVER_ERROR_MESSAGE);
        }
    }
}

一个异常处理器,用于处理@RestController注解的控制器中抛出的异常。它使用@Slf4j注解来使用日志记录功能

  • @RestControllerAdvice注解表示这是一个全局异常处理类。
  • @ExceptionHandler注解表示该方法用于处理异常。
  • handle方法用于捕获异常,并根据异常类型返回不同的响应。
    • 如果异常是BusinessException类型,则记录日志并返回一个包含异常信息的APIResponse对象。
    • 如果异常不是BusinessException类型,则记录日志并返回一个包含通用错误信息的APIResponse对象。

controller

@Slf4j
@RestController
@RequestMapping("handleexception")
public class HandleExceptionController {
    
    //……
    
    private void readFile() throws IOException {
        Files.readAllLines(Paths.get("a_file"));
    }
}

二、案例分析

@GetMapping("exception")
public void exception(@RequestParam("business") boolean b) {
    if (b)
        throw new BusinessException("订单不存在", 2001);
    throw new RuntimeException("系统错误");
}

在这里插入图片描述

自定义异常生效

1、不恰当的异常转换

    @GetMapping("wrong1")
    public void wrong1() {
        try {
            readFile();
        } catch (IOException e) {
            throw new RuntimeException("系统忙请稍后再试");
        }
    }

在这里插入图片描述

问题将具体的IOException转换为非具体的RuntimeException,失去了原始异常的详细信息,不利于问题的定位和调试。应该尽可能保留或封装原始异常,以便于追踪错误源头

2、不充分日志记录

    @GetMapping("wrong2")
    public void wrong2() {
        try {
            readFile();
        } catch (IOException e) {
            log.error("文件读取错误, {}", e.getMessage());
            throw new RuntimeException("系统忙请稍后再试");
        }
    }

在这里插入图片描述

问题

  • 虽然记录了日志但异常转换仍存在问题:与wrong1类似,该方法虽然在抛出新异常前记录了详细的错误信息,但是最终抛出的是一个不包含原始异常信息的RuntimeException。这会导致堆栈跟踪信息丢失,不易于问题诊断。
  • 可以改进日志内容:虽然记录了错误信息,但是直接使用e.getMessage()可能不足以覆盖所有上下文信息,理想情况下应考虑记录更多上下文,如当前执行的操作、涉及的变量值等。

3、过度或不当的异常捕获

    @GetMapping("wrong3")
    public void wrong3(@RequestParam("orderId") String orderId) {
        try {
            readFile();
        } catch (Exception e) {
            log.error("文件读取错误", e);
            throw new RuntimeException();
        }
    }

在这里插入图片描述

问题

  • 过度捕获异常使用了非常广泛的Exception进行捕获,这意味着它会捕获所有类型的异常,包括那些可能本应由上层处理或根本就不应该被捕获的异常。这可能导致隐藏问题使得某些异常被不恰当地处理
  • 缺少异常信息抛出的RuntimeException没有提供任何具体信息,这对于调试和日志记录是非常不利的。至少应该提供一个有意义的错误消息
  • 日志记录不完整:虽然记录了错误日志,但是没有利用占位符插入异常信息(e)到日志消息中,这可能会遗漏重要的异常详情

上述的问题主要影响系统的可维护性和故障排查能力,所以我们需要更加细致地处理异常,保留异常链,以及提供充分的日志信息

三、正确处理方式

1、方式1

    @GetMapping("right1")
    public void right1() {
        try {
            readFile();
        } catch (IOException e) {
            log.error("文件读取错误", e);
            throw new RuntimeException("系统忙请稍后再试");
        }
    }

在这里插入图片描述

2、方式2

    @GetMapping("right2")
    public void right2() {
        try {
            readFile();
        } catch (IOException e) {
            throw new RuntimeException("系统忙请稍后再试", e);
        }
    }

在这里插入图片描述

方式1和方式2虽然表达不一样,但是都解决了:不恰当的异常转换、不充分的日志记录、过度或不当的异常捕获的问题,虽然代码简单,但是涉及异常操作时,也要引起重视,不然,出bug了,不好搞

  • 异常精确捕获,并精确处理,比方说上面right1和right2都是IOException
  • 获取更详细的异常日志,直接打印 e
  • 注意异常转换,丢失异常的上下

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

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

相关文章

2024年6月计算机视觉论文推荐:扩散模型、视觉语言模型、视频生成等

6月还有一周就要结束了&#xff0c;我们今天来总结2024年6月上半月发表的最重要的论文&#xff0c;重点介绍了计算机视觉领域的最新研究和进展。 Diffusion Models 1、Autoregressive Model Beats Diffusion: Llama for Scalable Image Generation LlamaGen&#xff0c;是一个…

C++20中的Feature Test Mocros

C20定义了一组预处理器宏&#xff0c;用于测试各种语言和库的feature。 Feature Test Mocros(特性测试宏)是C20中引入的一种强大机制&#xff0c;用于应对兼容性问题。Feature Test Mocros作为预处理器指令(preprocessor directives)出现&#xff0c;它使你能够在编译过程中仔细…

Edge 浏览器退出后,后台占用问题

Edge 浏览器退出后&#xff0c;后台占用问题 环境 windows 11 Microsoft Edge版本 126.0.2592.68 (正式版本) (64 位)详情 在关闭Edge软件后&#xff0c;查看后台&#xff0c;还占用很多系统资源。实在不明白&#xff0c;关了浏览器还不能全关了&#xff0c;微软也学流氓了。…

计算机网络期末

1、IP 地址为:192.168.0.254,它的子网掩码应该为( ) A.255.255.255.0 B.255.255.254.0 C.255.255.252.0 D.255.255.0.0 2、最容易产生网络可靠性瓶颈问题的拓扑构型是&#xff08; &#xff09;。 A 总线型 B 星型 C 环型 D 网状型 3、HTTP 就是电子邮件阅读协议&#xff0…

Android开发实用必备的几款插件,提高你的开发速度

1.GsonFormat 使用方法&#xff1a;快捷键AltS也可以使用AltInsert选择GsonFormat&#xff0c;作用&#xff1a;速将json字符串转换成一个Java Bean&#xff0c;免去我们根据json字符串手写对应Java Bean的过程。 2.ButterKnife Zelezny 又叫黄油刀 使用方法&#xff1a;CtrlS…

Java程序之动物声音“模拟器”

题目&#xff1a; 设计一个“动物模拟器”&#xff0c;希望模拟器可以模拟许多动物的叫声和行为&#xff0c;要求如下&#xff1a; 编写接口Animal&#xff0c;该接口有两个抽象方法cry()和getAnimalName()&#xff0c;即要求实现该接口的各种具体的动物类给出自己的叫声和种类…

PostgreSQL如何定义缓冲区管理器?

目录 一、PostgreSQL是什么二、缓冲区管理器介绍三、缓冲区管理器的应用场景四、如何定义缓冲区管理器 一、PostgreSQL是什么 PostgreSQL是一种高级的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它以其稳定性、可靠性和高度可扩展性而闻名。它最初由加…

史上最强面试题,拿大厂京东,阿里offer全靠它。程序员必看。

答&#xff1a;对于short s1 1; s1 s1 1;由于1是int类型&#xff0c;因此s11运算结果也是int 型&#xff0c;需要强制转换类型才能赋值给short型。而short s1 1; s1 1;可以正确编译&#xff0c;因为s1 1;相当于s1 (short)(s1 1);其中有隐含的强制类型转换。 #6、Java 有…

Trimesh介绍及基本使用

Trimesh介绍及基本使用 Trimesh是一个纯Python 工具库&#xff08;支持3.7版本以上&#xff09;&#xff0c;用于加载和使用三角形Mesh网格&#xff0c;支持多种常见的三维数据格式&#xff0c;如二进制/文本格式的STL、Wavefront OBJ、二进制/文本格式的PLY、GLTF/GLB 2.0、3…

食谱API

在当今追求健康与美味完美结合的时代&#xff0c;获取准确而丰富的食品和营养信息变得至关重要。无论是热衷于探索世界各地美食的烹饪爱好者&#xff0c;还是对自身饮食营养严格把控的健康追求者&#xff0c;都离不开可靠的资源。幸运的是&#xff0c;现在有诸如 TheMealDB 和 …

测试辅助工具(抓包工具)的使用2 之 抓包工具的基本用法

1.过滤设置: Filters- --- 勾选use Filters- --- 下拉选择show only the following hosts ---- 输入域名或者ip地址(多个地址用;隔开) --- 点击action(Run filterset now) 2.删除数据 方式一:点击Remove all 方式二: 黑窗口输入cls,回车 删除一条数据:选中数据---右键选择Rem…

LabVIEW电路板故障诊断系统

基于LabVIEW软件开发的电路板故障诊断系统&#xff0c;涵盖功能测试、性能测试和通讯测试等多个方面。系统集成了多种硬件设备&#xff0c;包括NI PXI-1033机箱、NI PXI-4071数字万用表、NI PXI-4130电源模块、NI PXI-8512 CAN模块等&#xff0c;通过模块化设计实现了对电路板的…

Tortoise 删除文件

1、右击需要删除的文件&#xff0c;选择Delete 2、提交

0基础学习线段树

前言&#xff1a; 线段树&#xff1a;用树来表示一个一个的线段区间。 1、为什么要使用线段树&#xff1f; 题目&#xff1a;给定一个数组nums&#xff0c;我们有两种下面两种操作 1、查询nums数组下标i到下标j的和&#xff1b; 2、将nums数组指定下标的值改为指定的一个新…

screenshot-to-code之安装、测试

准备 GPT收费账号 screenshot-to-code Supported AI models: GPT-4O - Best model!GPT-4 Turbo (Apr 2024)GPT-4 Vision (Nov 2023)Claude 3 SonnetDALL-E 3 for image generation git或者手动 下载源代码 https://github.com/abi/screenshot-to-code pip install poetry (…

【图像识别系统】昆虫识别Python+卷积神经网络算法+人工智能+深度学习+机器学习+TensorFlow+ResNet50

一、介绍 昆虫识别系统&#xff0c;使用Python作为主要开发语言。通过TensorFlow搭建ResNet50卷积神经网络算法&#xff08;CNN&#xff09;模型。通过对10种常见的昆虫图片数据集&#xff08;‘蜜蜂’, ‘甲虫’, ‘蝴蝶’, ‘蝉’, ‘蜻蜓’, ‘蚱蜢’, ‘蛾’, ‘蝎子’, ‘…

ROS话题通信机制实操C++

ROS话题通信机制实操C 创建ROS工程发布方(二狗子)订阅方(翠花)编辑配置文件编译并执行注意订阅的第一条数据丢失 ROS话题通信的理论查阅ROS话题通信流程理论 在ROS话题通信机制实现中&#xff0c;ROS master 不需要实现&#xff0c;且连接的建立也已经被封装了&#xff0c;需要…

反馈时延与端到端拥塞控制

先从 越来越无效的拥塞控制 获得一个直感。 开局一张图&#xff0c;剩下全靠编。这是一道习题&#xff1a; 这图来自《高性能通信网络(第二版)》&#xff0c;2002 年的书&#xff0c;很好很高尚&#xff0c;目前这种书不多了。不准备做这道题&#xff0c;但意思要明白&#x…

Redis学习|Redis基础知识、Redis五大数据类型、Redis三种特殊数据类型、Redis事务

Redis基础知识 redis默认有16个数据库&#xff0c;并且这个数量可以在conf配置文件中更改 默认使用的是第0个 可以使用 select 进行切换数据库! key *查看数据库所有的key 清除当前数据库 flushdb 清除全部数据库的内容FLUSHALL 为什么redis是6379!(了解一下即可!) Redis 是…

关于笔记本电脑连接电源时触摸板失灵、卡顿、乱飘的问题

目录 前言 问题原因 解决方法 前言 我查阅了相关的资料和方法如下&#xff08;很感谢这位楼主大佬提供的问题所在&#xff09;&#xff1a; 问题原因 解决方法 那么解决方法无非就是几种&#xff08;方法仅供参考&#xff0c;不排除一些危险性&#xff09;&#xff1a; 1…