感觉现在代码中的异常处理很混乱,有些调用栈比较长,每一个方法都在捕获异常打印日志,一个方法抛出异常,接连的就会有一堆方法去捕获+打印日志,然后一堆日志都是同一个异常的。
大家都是怎么处理的?
1
Lpl 2016-03-21 09:59:30 +08:00 via Android
不符合标准的话直接返回错误码。
在对业务进行处理的时候,抛异常。比如接受到别的接口返回的错误码,直接就抛出; 与数据库相关的也抛出,不要 catch; 与文件相关的也抛出。一些感觉不重要的,不会影响也许逻辑的,直接 catch ,然后放到 info 中。 应该是这样吧...错了拍砖 |
2
fwrq41251 2016-03-21 10:09:00 +08:00
要么处理异常,要么抛出异常,不要都做。
“一堆日志都是同一个异常的”显然违反了这个规则, LOG 的同时又往上抛了。 还有一个比较简单的规则是异常应该尽可能早的抛出,尽可能晚的处理。 |
3
BuilderQiu OP |
4
odirus 2016-03-21 10:31:22 +08:00
|
5
crazyxin1988 2016-03-21 10:40:21 +08:00
最近一次重构一个后端项目时,这样处理的。
层层方法调用,不全用 checked exception ,层层都要 try catch ,代码看起来拖沓。 内部使用 runtime exception 在最后的外部调用接口使用 checked exception 这样做强制外部系统在调用时,要 try catch ,也方便外部进行异常的转换 |
6
fwrq41251 2016-03-21 10:45:52 +08:00
@BuilderQiu
再晚一点,如果你用的是 spring mvc ,实现你自己的 HandlerExceptionResolver ,在这里做通用的返回。 需要特殊处理的,就抛出需要捕获的异常,在业务代码里 catch 住处理。 |
7
janxin 2016-03-21 10:50:51 +08:00
这个基本上跟语言完全无关,现在基本上看需求决定:数据一致性要求高的,在数据库操作时 catch 后做回滚之类的操作;业务逻辑处理层大部分都是抛异常到顶层 Controller 统一处理。
|
8
hantsy 2016-03-21 10:56:19 +08:00
Java 异常可以分为 Checked 和 UnChecked 异常,异常设计时如何选择,一直存在争议。
Spring 内部全部使用 Unchecked Exception ,在你的代码中几乎不需要 try/catch 来捕捉,它内置一套机制来处理异常, ExceptionTranslator (异常转换), ExceptionHandler ( Web 异常处理), retry (一些批处理中可以设置遇到异常重新执行)。这种好处是不需要关心太多的异常处理,坏处很多异常到运行时才能发现。 但从接口的设计角度看, Checked 异常有时会让接口看起来比较清晰。 比如,在接口定义了一个方法中要求实现类中 **强制** 检测库存情况: addProductIntoCart(String product) throws OutOfStockException{} 在实际项目,自己可以设计合理的异常类,在业务实现层面抛出来,如果是 Spring 程序用 ExceptionHanlder 来处理。其它 Web 框架也相应的 Exception 处理机制。 异常可以与 Logger 结合起来,以便日后日志分析,一些第三方的 Cloud 服务,如 logentries 也提供日志分析能力,都提供了常用 Logger 的一些扩展方法,这样日志收集起来,完全可以做到可视化。 |
9
BuilderQiu OP @odirus
这个表示可以使用抛异常的方式处理业务异常等哇,现在不用异常就是一堆判断。。 @crazyxin1988 这个办法感觉不错,可以解决这一堆 trycatch 的问题,不过要区分哪些算作内部哪些算作外部的问题 @fwrq41251 嗯,现在基本就是 SpringMVC ,但是抛出异常的地方打印日志感觉能输出更多的业务数据信息,最外层统一处理的话有些数据就不好拿了,除非 catch 了异常,封装再抛出,不记录日志。 @janxin 是的,我指的是一般的业务上的异常,数据库这种涉及到事务处理的肯定就是当场抛出回滚解决了 @hantsy 感觉现在 checked exception 用的都比较少,方便编码。。 |
10
hantsy 2016-03-21 14:07:04 +08:00
@BuilderQiu 跟方便编码一点关系都没有。。。看来你们从来没把异常设计加入到基础架构考虑中去。
|
11
BuilderQiu OP |
12
qwepoidjdj 2016-03-21 15:28:43 +08:00
首先定义顶级异常类型 例如系统级 业务级等(用 uncheck 类型就行)
此后如有需要定义新异常 必须去继承顶级异常 区分异常类型 区分处理方式 区分 LOG 级别 各种区别对待 框架要有全局异常处理机制 所有异常底层都不要 catch 需要抛的全抛 统一由全局异常处理机制处理 这个问题仔细一下就能明白 在开发程序的时候不可能把所有问题都想清楚 想明白 不出问题 落实到代码上来说 当你去调用一个方法的时候 难道要把所有出错的可能都处理了么? 这明显是不可能的 错误的原因各种奇葩 大部分都是代码问题 只能事后分析修补 |
13
SoloCompany 2016-03-22 04:28:23 +08:00
想不明白到现在怎么还会有人觉得 checked exception 可以使 api 更清晰的
这简直是一个大毒瘤,尤其到了 java 8 这个问题就暴露的更彻底了,你试一下给每一个 SAM 接口都增加一套抛异常的版本试试? 再想想为什么 Appenable 被迫声明为抛出 IOException 导致你不得不使用 StringBuilder 来处理个字符串拼接任务还不得不捕获 IOException 然后无意义的不处理的时候是什么感受 |