微服务时代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 边缘检测是一种经典的边缘检测算法,由 John F. Canny 在 1986 年提出。它被广泛应用于计算机视觉和图像处理领域,用于检测图像中的边缘。 【原理】 1. 去噪 由于边缘检测非常容易收到图像的噪声影响,第一步使用 5x5 高斯滤波去除图…...

2023-8-23 滑动窗口
题目链接:滑动窗口 #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通信中间件常用的通信协议
摘要: SOA(面向服务的架构)的软件设计原则之一是模块化。 前言 SOA(面向服务的架构)的软件设计原则之一是模块化。模块化可以提高软件系统的可维护性和代码重用性,并且能够隔离故障。举例来说,…...

解决npm安装依赖失败,node和node-sass版本不匹配的问题
npm安装依赖报错: npm ERR! cb() never called! npm ERR! This is an error with npm itself. 一. 问题描述 用npm安装依赖报错: 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包到安装目录中,并…...
考研C语言进阶题库——更新51-60题
目录 51.银行系中有很多恒星,H 君晚上无聊,便爬上房顶数星星,H 君将整个银河系看做一个平面,左上角为原点(坐标为(1, 1))。现在有 n 颗星星,他给每颗星星都标上坐标&…...
智能算法挑战赛决赛题目——初中组
题目 1. 判断是否存在重复的子序列 从 m 个字符中选取字符,生成 n 个符号的序列,使得其中没有 2 个相邻的子序列相同。如从 1,2,3,生成长度为 5 的序列,序列“12321”是合格的,而“12323”和“…...

一分钟学算法-递归-斐波那契数列递归解法及优化
一分钟学一个算法题目。 今天我们要学习的是用递归算法求解斐波那契数列。 首先我们要知道什么是斐波那契数列。 斐波那契数列,又称黄金分割数列,是一个经典的数学数列,其特点是第一项,第二项为1,后面每个数字都是前…...
选择Rust,并在Ubuntu上使用Rust
在过去的 8 年里,Rust 一直是开发人员最喜欢的语言,并且越来越被各种规模的软件公司采用。然而,它的许多高级规则和抽象创造了一个陡峭的初始学习曲线,这可能会给人留下 Rust 是少数人的保留的印象,但这与事实相去甚远…...

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

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

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

Mac Flutter web环境搭建
获取 Flutter SDK 下载以下安装包来获取最新的 stable Flutter SDK将文件解压到目标路径, 比如: cd ~/development $ unzip ~/Downloads/flutter_macos_3.13.0-stable.zip 配置 flutter 的 PATH 环境变量: 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 是一个文本文件,里面包含组装新镜像时用到的基础镜像和各种指令,使用dockerfile 文件来定义镜像,然后运行镜像,启动容器。 dockerfile文件的组成部分 一个dockerfile文件包含以下部分: 基础镜像信息&…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...
字符串哈希+KMP
P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...

ArcGIS Pro+ArcGIS给你的地图加上北回归线!
今天来看ArcGIS Pro和ArcGIS中如何给制作的中国地图或者其他大范围地图加上北回归线。 我们将在ArcGIS Pro和ArcGIS中一同介绍。 1 ArcGIS Pro中设置北回归线 1、在ArcGIS Pro中初步设置好经纬格网等,设置经线、纬线都以10间隔显示。 2、需要插入背会归线…...
boost::filesystem::path文件路径使用详解和示例
boost::filesystem::path 是 Boost 库中用于跨平台操作文件路径的类,封装了路径的拼接、分割、提取、判断等常用功能。下面是对它的使用详解,包括常用接口与完整示例。 1. 引入头文件与命名空间 #include <boost/filesystem.hpp> namespace fs b…...

GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...