Java 中异常应该如何处理?
- 哪些地方应该抛异常?基础服务的方法校验到参数不符合标准的时候是返回错误状态码还是抛出异常?
- 哪些地方应该捕获异常?
感觉现在代码中的异常处理很混乱,有些调用栈比较长,每一个方法都在捕获异常打印日志,一个方法抛出异常,接连的就会有一堆方法去捕获+打印日志,然后一堆日志都是同一个异常的。
大家都是怎么处理的?
感觉现在代码中的异常处理很混乱,有些调用栈比较长,每一个方法都在捕获异常打印日志,一个方法抛出异常,接连的就会有一堆方法去捕获+打印日志,然后一堆日志都是同一个异常的。
大家都是怎么处理的?
1
Lpl Mar 21, 2016 via Android
不符合标准的话直接返回错误码。
在对业务进行处理的时候,抛异常。比如接受到别的接口返回的错误码,直接就抛出; 与数据库相关的也抛出,不要 catch; 与文件相关的也抛出。一些感觉不重要的,不会影响也许逻辑的,直接 catch ,然后放到 info 中。 应该是这样吧...错了拍砖 |
2
fwrq41251 Mar 21, 2016
要么处理异常,要么抛出异常,不要都做。
“一堆日志都是同一个异常的”显然违反了这个规则, LOG 的同时又往上抛了。 还有一个比较简单的规则是异常应该尽可能早的抛出,尽可能晚的处理。 |
3
BuilderQiu OP |
4
odirus Mar 21, 2016
|
5
crazyxin1988 Mar 21, 2016
最近一次重构一个后端项目时,这样处理的。
层层方法调用,不全用 checked exception ,层层都要 try catch ,代码看起来拖沓。 内部使用 runtime exception 在最后的外部调用接口使用 checked exception 这样做强制外部系统在调用时,要 try catch ,也方便外部进行异常的转换 |
6
fwrq41251 Mar 21, 2016
@BuilderQiu
再晚一点,如果你用的是 spring mvc ,实现你自己的 HandlerExceptionResolver ,在这里做通用的返回。 需要特殊处理的,就抛出需要捕获的异常,在业务代码里 catch 住处理。 |
7
janxin Mar 21, 2016
这个基本上跟语言完全无关,现在基本上看需求决定:数据一致性要求高的,在数据库操作时 catch 后做回滚之类的操作;业务逻辑处理层大部分都是抛异常到顶层 Controller 统一处理。
|
8
hantsy Mar 21, 2016
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 Mar 21, 2016
@BuilderQiu 跟方便编码一点关系都没有。。。看来你们从来没把异常设计加入到基础架构考虑中去。
|
11
BuilderQiu OP |
12
qwepoidjdj Mar 21, 2016
首先定义顶级异常类型 例如系统级 业务级等(用 uncheck 类型就行)
此后如有需要定义新异常 必须去继承顶级异常 区分异常类型 区分处理方式 区分 LOG 级别 各种区别对待 框架要有全局异常处理机制 所有异常底层都不要 catch 需要抛的全抛 统一由全局异常处理机制处理 这个问题仔细一下就能明白 在开发程序的时候不可能把所有问题都想清楚 想明白 不出问题 落实到代码上来说 当你去调用一个方法的时候 难道要把所有出错的可能都处理了么? 这明显是不可能的 错误的原因各种奇葩 大部分都是代码问题 只能事后分析修补 |
13
SoloCompany Mar 22, 2016
想不明白到现在怎么还会有人觉得 checked exception 可以使 api 更清晰的
这简直是一个大毒瘤,尤其到了 java 8 这个问题就暴露的更彻底了,你试一下给每一个 SAM 接口都增加一套抛异常的版本试试? 再想想为什么 Appenable 被迫声明为抛出 IOException 导致你不得不使用 StringBuilder 来处理个字符串拼接任务还不得不捕获 IOException 然后无意义的不处理的时候是什么感受 |