当前位置: 首页 > news >正文

微服务时代java异常捕捉

一、尽量不要使用e.printStackTrace(),而是使用log打印。


​反例:​

try{
  // do what you want  
}catch(Exception e){
  e.printStackTrace();
}

正例:​

try{
  // do what you want  
}catch(Exception e){
  log.info("你的程序有异常啦,{}",e);
}

理由:​


printStackTrace()打印出的堆栈日志跟业务代码日志是交错混合在一起的,排查异常日志不太方便。
e.printStackTrace()语句产生的字符串记录的是堆栈信息,如果信息太长太多,字符串常量池所在的内存块没有空间了,即内存满了,那么,用户的请求就卡住啦~

二、catch了异常,但是没有打印出具体的exception,无法更好定位问题


​反例:​

try{
  // do what you want  
}catch(Exception e){
  log.info("你的程序有异常啦");
}
 

​正例:​

try{
  // do what you want  
}catch(Exception e){
  log.info("你的程序有异常啦,{}",e);
}

​理由:​

反例中,并没有把exception出来,到时候排查问题就不好查了啦,到底是SQl写错的异常还是IO异常,还是其他呢?所以应该把exception打印到日志中哦~

三、不要用一个Exception捕捉所有可能的异常

反例:​

public void test(){
    try{
        //…抛出 IOException 的代码调用
        //…抛出 SQLException 的代码调用
    }catch(Exception e){
        //用基类 Exception 捕捉的所有可能的异常,如果多个层次都这样捕捉,会丢失原始异常的有效信息哦
        log.info(“Exception in test,exception:{}”, e);
    }
}

正例:​

public void test(){
    try{
        //…抛出 IOException 的代码调用
        //…抛出 SQLException 的代码调用
    }catch(IOException e){
        //仅仅捕捉 IOException
        log.info(“IOException in test,exception:{}”, e);
    }catch(SQLException e){
        //仅仅捕捉 SQLException
        log.info(“SQLException in test,exception:{}”, e);
    }
}
 

理由:

用基类 Exception 捕捉的所有可能的异常,如果多个层次都这样捕捉,会丢失原始异常的有效信息哦

四、记得使用finally关闭流资源或者直接使用try-with-resource

​反例:​

FileInputStream fdIn = null;
try {
    fdIn = new FileInputStream(new File("/jay.txt"));
    //在这里关闭流资源?有没有问题呢?如果发生异常了呢?
    fdIn.close();
} catch (FileNotFoundException e) {
    log.error(e);
} catch (IOException e) {
    log.error(e);
}


​正例1:​

需要使用finally关闭流资源,如下

FileInputStream fdIn = null;
try {
    fdIn = new FileInputStream(new File("/jay.txt"));
} catch (FileNotFoundException e) {
    log.error(e);
} catch (IOException e) {
    log.error(e);
}finally {
    try {
        if (fdIn != null) {
            fdIn.close();
        }
    } catch (IOException e) {
        log.error(e);
    }
}


​正例2:​

当然,也可以使用JDK7的新特性try-with-resource来处理,它是Java7提供的一个新功能,它用于自动资源管理。


资源是指在程序用完了之后必须要关闭的对象。
try-with-resources保证了每个声明了的资源在语句结束的时候会被关闭
什么样的对象才能当做资源使用呢?只要实现了java.lang.AutoCloseable接口或者java.io.Closeable接口的对象,都OK。

try (FileInputStream inputStream = new FileInputStream(new File("jay.txt")) {
    // use resources   
} catch (FileNotFoundException e) {
    log.error(e);
} catch (IOException e) {
    log.error(e);
}


​理由:​

如果不使用finally或者try-with-resource,当程序发生异常,IO资源流没关闭,那么这个IO资源就会被他一直占着,这样别人就没有办法用了,这就造成资源浪费。


五、捕获异常与抛出异常必须是完全匹配,或者捕获异常是抛异常的父类

​反例:​

//BizException 是 Exception 的子类
public class BizException extends Exception {}
//抛出父类Exception
public static void test() throws Exception {}


try {
    test(); //编译错误
} catch (BizException e) { //捕获异常子类是没法匹配的哦
    log.error(e);
}


​正例:​

//抛出子类Exception
public static void test() throws BizException {}


try {
    test();
} catch (Exception e) {
    log.error(e);
}
 

六、捕获到的异常,不能忽略它,至少打点日志吧


​反例:​

public static void testIgnoreException() throws Exception {
    try {       
        // 搞事情
    } catch (Exception e) {     //一般不会有这个异常

    }
}


​正例:​

public static void testIgnoreException() {
    try {
        // 搞事情
    } catch (Exception e) {     //一般不会有这个异常
        log.error("这个异常不应该在这里出现的,{}",e); 
    }
}


理由:​

虽然一个正常情况都不会发生的异常,但是如果你捕获到它,就不要忽略呀,至少打个日志吧~

七、注意异常对你的代码层次结构的侵染(早发现早处理)


​反例:​

public UserInfo queryUserInfoByUserId(Long userid) throw SQLException {
    //根据用户Id查询数据库
}
 

​正例:​

public UserInfo queryUserInfoByUserId(Long userid) {
    try{
        //根据用户Id查询数据库
    }catch(SQLException e){
        log.error("查询数据库异常啦,{}",e);
    }finally{
        //关闭连接,清理资源
    }
}



​理由:​

我们的项目,一般都会把代码分 Action、Service、Dao 等不同的层次结构,如果你是DAO层处理的异常,尽早处理吧,如果往上 throw SQLException,上层代码就还是要try catch处理啦,这就污染了你的代码~


八、自定义封装异常,不要丢弃原始异常的信息Throwable cause


我们常常会想要在捕获一个异常后抛出另一个异常,并且希望把原始异常的信息保存下来,这被称为异常链。公司的框架提供统一异常处理就用到异常链,我们自定义封装异常,不要丢弃原始异常的信息,否则排查问题就头疼啦

​反例:​

public class TestChainException {
    public void readFile() throws MyException{
        try {
            InputStream is = new FileInputStream("jay.txt");
            Scanner in = new Scanner(is);
            while (in.hasNext()) {
                System.out.println(in.next());
            }
        } catch (FileNotFoundException e) {
            //e 保存异常信息
            throw new MyException("文件在哪里呢");
        }
    }
    public void invokeReadFile() throws MyException{
        try {
            readFile();
        } catch (MyException e) {
            //e 保存异常信息
            throw new MyException("文件找不到");
        }
    }
    public static void main(String[] args) {
        TestChainException t = new TestChainException();
        try {
            t.invokeReadFile();
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
}
//MyException 构造器
public MyException(String message) {
        super(message);
    }

运行结果如下,没有了Throwable cause,不好排查是什么异常了啦

正例:​

public class TestChainException {
    public void readFile() throws MyException{
        try {
            InputStream is = new FileInputStream("jay.txt");
            Scanner in = new Scanner(is);
            while (in.hasNext()) {
                System.out.println(in.next());
            }
        } catch (FileNotFoundException e) {
            //e 保存异常信息
            throw new MyException("文件在哪里呢", e);
        }
    }
    public void invokeReadFile() throws MyException{
        try {
            readFile();
        } catch (MyException e) {
            //e 保存异常信息
            throw new MyException("文件找不到", e);
        }
    }
    public static void main(String[] args) {
        TestChainException t = new TestChainException();
        try {
            t.invokeReadFile();
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
}
//MyException 构造器
public MyException(String message, Throwable cause) {
        super(message, cause);
    }
 


九、运行时异常RuntimeException ,不应该通过catch 的方式来处理,而是先预检查,比如:NullPointerException处理


​反例:​

try {
  obj.method() 
} catch (NullPointerException e) {
...
}

​正例:​

if (obj != null){
   ...
 


十、注意异常匹配的顺序,优先捕获具体的异常


注意异常的匹配顺序,因为只有第一个匹配到异常的catch块才会被执行。如果你希望看到,是NumberFormatException异常,就抛出NumberFormatException,如果是IllegalArgumentException就抛出IllegalArgumentException。

​反例:​

try {
    doSomething("test exception");
} catch (IllegalArgumentException e) {       
    log.error(e);
} catch (NumberFormatException e) {
    log.error(e);
}

正例:​

try {
    doSomething("test exception");
} catch (NumberFormatException e) {       
    log.error(e);
} catch (IllegalArgumentException e) {
    log.error(e);
}
 

理由:

因为NumberFormatException是IllegalArgumentException 的子类,反例中,不管是哪个异常,都会匹配到IllegalArgumentException,就不会再往下执行啦,因此不知道是否是NumberFormatException。所以需要优先捕获具体的异常,把NumberFormatException放前面~
 

相关文章:

微服务时代java异常捕捉

一、尽量不要使用e.printStackTrace(),而是使用log打印。 ​反例:​ try{ // do what you want }catch(Exception e){ e.printStackTrace(); } ​ 正例:​ try{ // do what you want }catch(Exception e){ log.info("你的程序有异常啦,{}",e)…...

Hadoop支持LZO压缩

LZO(Lempel-Ziv-Oberhumer)是一种快速压缩算法,特别适用于大数据处理。在Hadoop生态系统中,LZO压缩通常用于Hadoop MapReduce作业的输入和输出数据,以减少存储空间和数据传输的开销。 以下是在Hadoop中使用LZO压缩的一般步骤: 安装LZO库和工具: 首先,需要在Hadoop集群…...

vue3 01-setup函数

1.setup函数的作用: 1.是组合式api的入口2.比beforeCreate 执行更早3.没有this组件实例一开始创建vue3页面的时候是这样的 <template></template> <script> export default{setup(){return{ }} } </script>给容器传参在页面中显示 数据给模板使用,以…...

iOS swift 类似AirDrop的近场数据传输 MultipeerConnectivity 框架

文章目录 1.github上的demo 1.github上的demo insidegui/MultipeerDemo – github insidegui/MultipeerKit – github...

Lnton羚通云算力平台OpenCV-PythonCanny边缘检测教程

Canny 边缘检测是一种经典的边缘检测算法&#xff0c;由 John F. Canny 在 1986 年提出。它被广泛应用于计算机视觉和图像处理领域&#xff0c;用于检测图像中的边缘。 ​【原理】 1. 去噪 由于边缘检测非常容易收到图像的噪声影响&#xff0c;第一步使用 5x5 高斯滤波去除图…...

2023-8-23 滑动窗口

题目链接&#xff1a;滑动窗口 #include <iostream>using namespace std;const int N 1000010;int n, k; int a[N], q[N];int main() {scanf("%d%d", &n, &k);for(int i 0; i < n; i) scanf("%d", &a[i]);int hh 0, tt -1;for(…...

SOA通信中间件常用的通信协议

摘要&#xff1a; SOA&#xff08;面向服务的架构&#xff09;的软件设计原则之一是模块化。 前言 SOA&#xff08;面向服务的架构&#xff09;的软件设计原则之一是模块化。模块化可以提高软件系统的可维护性和代码重用性&#xff0c;并且能够隔离故障。举例来说&#xff0c;…...

解决npm安装依赖失败,node和node-sass版本不匹配的问题

npm安装依赖报错&#xff1a; npm ERR! cb() never called! npm ERR! This is an error with npm itself. 一. 问题描述 用npm安装依赖报错&#xff1a; npm ERR! cb() never called! npm ERR! This is an error with npm itself. Please report this error at: npm ERR! …...

2023 网络建设与运维 X86架构计算机操作系统安装与管理题解

任务描述: 随着信息技术的快速发展,集团计划2023年把部分业务由原有的X86架构服务器上迁移到ARM架构服务器上,同时根据目前的部分业务需求进行了部分调整和优化。 一、X86架构计算机操作系统安装与管理 1.PC1系统为ubuntu-desktop-amd64系统(已安装,语言为英文),登录用户…...

LAMP 架构及Discuz论坛与Wordpress博客搭建

目录 1 LAMP 配置与应用 1.1动态资源与语言 1.2 LAMP 架构的组成 1.2.1 主要功能 2 编译安装Apache http 服务 2.1 环境准备 2.1.1 关闭防火墙及selinux服务 2.1.2 安装依赖环境 2.2 安装软件包 2.2.1 解压软件包 2.2.2 移动apr包 apr-util包到安装目录中&#xff0c;并…...

考研C语言进阶题库——更新51-60题

目录 51.银行系中有很多恒星&#xff0c;H 君晚上无聊&#xff0c;便爬上房顶数星星&#xff0c;H 君将整个银河系看做一个平面&#xff0c;左上角为原点&#xff08;坐标为&#xff08;1, 1&#xff09;&#xff09;。现在有 n 颗星星&#xff0c;他给每颗星星都标上坐标&…...

智能算法挑战赛决赛题目——初中组

题目 1. 判断是否存在重复的子序列 从 m 个字符中选取字符&#xff0c;生成 n 个符号的序列&#xff0c;使得其中没有 2 个相邻的子序列相同。如从 1&#xff0c;2&#xff0c;3&#xff0c;生成长度为 5 的序列&#xff0c;序列“12321”是合格的&#xff0c;而“12323”和“…...

一分钟学算法-递归-斐波那契数列递归解法及优化

一分钟学一个算法题目。 今天我们要学习的是用递归算法求解斐波那契数列。 首先我们要知道什么是斐波那契数列。 斐波那契数列&#xff0c;又称黄金分割数列&#xff0c;是一个经典的数学数列&#xff0c;其特点是第一项&#xff0c;第二项为1&#xff0c;后面每个数字都是前…...

选择Rust,并在Ubuntu上使用Rust

在过去的 8 年里&#xff0c;Rust 一直是开发人员最喜欢的语言&#xff0c;并且越来越被各种规模的软件公司采用。然而&#xff0c;它的许多高级规则和抽象创造了一个陡峭的初始学习曲线&#xff0c;这可能会给人留下 Rust 是少数人的保留的印象&#xff0c;但这与事实相去甚远…...

SVM详解

公式太多了&#xff0c;就用图片用笔记呈现&#xff0c;SVM虽然算法本质一目了然&#xff0c;但其中用到的数学推导还是挺多的&#xff0c;其中拉格朗日约束关于α>0这块证明我看了很长时间&#xff0c;到底是因为悟性不够。对偶问题也是&#xff0c;用了一个简单的例子才明…...

mysql全文检索使用

数据库数据量10万左右&#xff0c;使用like %test%要耗费30秒左右&#xff0c;放弃该办法 使用mysql的全文检索 第一步:建立索引 首先修改一下设置: my.ini中ngram_token_size 1 可以通过 show variables like %token%;来查看 接下来建立索引:alter table 表名 add f…...

opencv 进阶17-使用K最近邻和比率检验过滤匹配(图像匹配)

K最近邻&#xff08;K-Nearest Neighbors&#xff0c;简称KNN&#xff09;和比率检验&#xff08;Ratio Test&#xff09;是在计算机视觉中用于特征匹配的常见技术。它们通常与特征描述子&#xff08;例如SIFT、SURF、ORB等&#xff09;一起使用&#xff0c;以在图像中找到相似…...

Mac Flutter web环境搭建

获取 Flutter SDK 下载以下安装包来获取最新的 stable Flutter SDK将文件解压到目标路径, 比如: cd ~/development $ unzip ~/Downloads/flutter_macos_3.13.0-stable.zip 配置 flutter 的 PATH 环境变量&#xff1a; export PATH"$PATH:pwd/flutter/bin" // 这个命…...

在外SSH远程连接macOS服务器

文章目录 前言1. macOS打开远程登录2. 局域网内测试ssh远程3. 公网ssh远程连接macOS3.1 macOS安装配置cpolar3.2 获取ssh隧道公网地址3.3 测试公网ssh远程连接macOS 4. 配置公网固定TCP地址4.1 保留一个固定TCP端口地址4.2 配置固定TCP端口地址 5. 使用固定TCP端口地址ssh远程 …...

Dockerfile文件详细

Dockerfile 是一个文本文件&#xff0c;里面包含组装新镜像时用到的基础镜像和各种指令&#xff0c;使用dockerfile 文件来定义镜像&#xff0c;然后运行镜像&#xff0c;启动容器。 dockerfile文件的组成部分 一个dockerfile文件包含以下部分&#xff1a; 基础镜像信息&…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...