⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 dzone.com/articles/good-exception-handling 「Radek Hecl」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

Oh no, don't do this to me...

中文翻译:

哦,请不要这样写……

// 写一句注释跳过异常
try {
throw new IOException("Made up");
} catch (IOException e) {
// 跳过
}
// 记到日志里,继续处理
try {
throw new IOException("Made up");
} catch (IOException e) {
log.error("blah blah blah", e);
}
// 标记 TODO,不做任何处理
try {
throw new IOException("Made up");
} catch (IOException e) {
// TODO - 处理异常 (;
}

.... and still, I am finding those catch blocks inside various projects. This is a great way to suppress the problem — for a short period of time. A few weeks or months later, this will become a nightmare for developers. Walking through the old log files and trying to figure out what went wrong is definitely not that most people want to do. Therefore, let's avoid that.

The first rule is that catch blocks are here to handle exceptional situations. Logging exceptions and moving on is not considered as handling. The only case when it makes sense to suppress exception is during the closing of the resource after a prior exception (this case isn't covered within this article; if you are interested, then here is an old yet still very good blog post written by McDowell).

There are three basic patterns of how to handle exceptions: translate, retry, and recover.

Translate is often used when you have to deal with a checked exception, your method can't bubble it up, and recovery is not possible. In such cases, it is appropriate to translate it into a runtime exception and throw up. Then, the runtime exception is typically handled in the framework level. Retry is useful when dealing with unreliable services. It makes sense only if retrying makes sense fundamentally. The good example is retrying to overcome network interruptions. Recover is good when the strategy for doing that is defined. For example, you can write data to the local storage if sending over network fails. Of course, then it's necessary to define what to do with that file.

In addition, the mentioned patterns might be combined. Examples are as follows.

中文翻译:

我在各种项目中发现了这种 catch 语句。这是一种“好办法”,可以在短期内掩盖问题。然而几周或几个月后,这些代码将成为开发人员的噩梦。绝大多数人可不想读日志查问题。因此,还是让我们避免这种情况。

规则一:catch 语句是用来处理异常的,把异常记到日志里然后继续执行不算处理。唯一的例外是,在发生异常后关闭资源(本文不讨论这种情况;如果感兴趣,可以参考这篇 McDowell 的博客,虽然写的时间比较早,但内容很不错)。

有三种处理异常的基本模式:转换(translate)、重试(retry)和恢复(recover)。

转换经常用于处理受检异常(checked exception),在方法中异常无法抛出,并且无法恢复时使用。在这种情况下,将其转换为运行时异常(runtime exception)而后抛出是最合适的做法。接下来,运行时异常通常由框架处理。在处理不可靠的服务时,重试非常有用,前提是重新尝试有意义。一个很好的例子就是网络中断重试。如果定义了这种策略,那么就能够恢复到正常状态。例如,如果通过网络发送数据失败,可以将数据写入本地存储。当然,这时就必须定义如何处理该文件。

此外,上面提到的模式可以组合,比如像下面这个例子如下。

// 转换
try {
thrownew IOException("Made up");
} catch (IOException e) {
thrownew RuntimeException(e);
}
// 重试5次后放弃
boolean end = false;
int count = 0;
while (end == false) {
try {
// 发送信息
if (true) {
thrownew MessagingException("Made up");
}
end = true;
} catch (MessagingException e) {
if (count >= 5) {
// 尝试5次放弃。
thrownew RuntimeException("was not able to send message even after five tries", e);
}
++count;
try {
Thread.sleep(30000);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
thrownew RuntimeException(e1);
}
}
}
// 恢复:如果传输失败记录到文件
try {
// 发送信息
thrownew MessagingException("Made up");
} catch (MessagingException e) {
try {
// 写文件
thrownew IOException("Made up");
} catch (IOException e1) {
// 如果写文件失败,不再进行恢复
thrownew RuntimeException(e1);
}
}

If everything fails, then this way will at least guarantee that you will be aware of the problem. In addition, it will provide you always the true cause of the issue; therefore, you will be able to quickly identify where the problem is!

Happy handling!

中文翻译:

如果一切都失败了,那么上面这种方法至少可以确保你能意识到问题所在。此外,它还提供了问题的真正原因,从而让你能快速定位问题。

祝编程快乐!

文章目录