- 作者: gigix 2004年03月30日, 星期二 10:22
你可以使用这个链接引用该篇日志 http://publishblog.blogdriver.com/blog/tb.b?diaryID=97808
对不起对不起,刚才界面没反应,点多了,不好意思。
我的处理是这样的,我以前也是在每一层设置异常基类,然后让client去捕捉,后来我发现这样好象不太妥当,我就让这些异常基类通通提升一个层次,让client去定义,底层的模块捕捉到异常之后,转译成高层的异常再抛出去,因为我觉得本来属于某一层的异常却要到低层模块去定义很别扭。不如在client层提供入口,让底层去使用,比较符合ocp的原则,不知道对是不对。至于RuntimeException和checked Exception的问题我觉得如果底层有RuntimeException抛出来肯定是哪里有问题了,还不如让它quick and clean的停下来,错误再积累就不好了。
其实我也参加工作没几个月,菜鸟一只,经验谈不上,一点小小意见,如果错了请不要客气。
我的处理是这样的,我以前也是在每一层设置异常基类,然后让client去捕捉,后来我发现这样好象不太妥当,我就让这些异常基类通通提升一个层次,让client去定义,底层的模块捕捉到异常之后,转译成高层的异常再抛出去,因为我觉得本来属于某一层的异常却要到低层模块去定义很别扭。不如在client层提供入口,让底层去使用,比较符合ocp的原则,不知道对是不对。至于RuntimeException和checked Exception的问题我觉得如果底层有RuntimeException抛出来肯定是哪里有问题了,还不如让它quick and clean的停下来,错误再积累就不好了。
其实我也参加工作没几个月,菜鸟一只,经验谈不上,一点小小意见,如果错了请不要客气。
我现在的异常处理和你做的差不多。每一层都有BaseUnckeckedException,但有时候也用CheckedException。以前在onjava看到过一篇讨论受它影响比较深。对于无法处理的异常,就用UnChecked,例如SQL错误,产生于DAL,对于系统的来说是致命的。交给BusinessLayer毫无用处,因此抛出DaException。
如果是有用的可处理的例如处理用户登录的时候,UserNotExistException或PasswordNotVerfiedException就用CheckedException,交给Client去处理,显示不同的信息。
另外,在处理异常方面,我现在采用的是Struts1.1的ExceptionHandler机制。在ExceptionHandler捕获所有的Throwable,然后交给一个统一的或者按照module区分的Error.Jsp页面来显示。
另外有一个问题就是i18n在异常中如何处理。抛出的异常最终会显示到界面上。如果不做任何i18n处理恐怕不够友好。因此我让所有的自定义Exception实现一个ErrorKeyable接口。包含的Error就是i18n的key。如果我在ExceptionHandler中得到的Exception是ErrorKeyable的实例,那么就显示定制的错误信息。如果不是,就显示Unkown Error,呵呵。然后做个按钮在错误页让用户提交给admin。
“使用这些接口的地方不是都要做相应变化了吗”,不是的,因为我用的都是unchecked exception,就算接口上声明了,client同样可以不catch。
对于异常处理,原本我从来没把它当一个问题,用的处理方式也一般都是参照thinking in java中的介绍。可后来在hibernate中文论坛看到robbin和其他人对于check exception的讨论之后才发现异常处理确实是一个很让人头大的问题,后来又找到了tij作者写的一个关于ce的文章,最后的感觉是看的越多人越晕,到现在又看到了你的这篇了。看了这么些文章之后,最大的感受是,不管正方、反方都是言之成理,因为此也就更让我不知该如何处理了。(如你这篇文章有个例子啥的就很完美了)
我现在比较头疼的是,哪些异常应该抛出,哪些可以不抛(如将connection返回链接池时出现错误,而实际 的处理已经可以返回正确结果),如果异常出现嵌套,又该如何去进行深度捕获,另外就是异常应该以何种面目抛出,对于抛出的异常信息之后又该如何对用户进行引导,等等等等。这些东西一思考发现其实难度还是蛮大的,不是像当初直接抛一个出错页面就可以了戏的。
对于你提出的两个折中方案,我有些疑惑:
对于2还好说,可以使用一个专门的异常处理方法,在将异常作为参数传递进去,然后再进行日志处理等操作即可。
而对于1,我就很是迷惑了。你所谓的“在接口上标注异常签名”是指在接口后面加上throws?如果这样的话,使用这些接口的地方不是都要做相应变化了吗?而且,我的观念中接口最好是开始就定义完成,或是在重构时根据需要提升接口,如果在client都已经完成后再修改接口,岂不是带来大量工作量?
一些极不成熟的想法,作为java低手,这些也确实对我造成了困扰,还请不吝解惑,3kx