在j2ee应用程序中,我计划标准化异常处理策略。不再吞下异常并且基本上将所有已检查的异常转换为未检查的(除了一些实际上可以从中恢复。标准将是所有异常将被抛回到容器中(例如:{{ 3}})。无法恢复SQLException之类的异常,如果它在数据层深处发生,我将强制它向上。但是,小的子例程,如电子邮件通知将包含在try catch中以防止因打破整个应用程序流而发生异常。(EG:为什么要阻止整个过程完成,因为用户没有收到他们不需要的电子邮件通知!)
对此有何建议?再次重申我基本上将所有异常重新抛回到具有自己的错误页面的容器,然后将其记录到log4j。
答案 0 :(得分:2)
我认为电子邮件示例是检查异常的最佳方法。你有一些可能出错并且是短暂的,所以检查异常的存在会让你思考它。如果所有内容都是运行时异常,那么您的应用程序会因为微不足道的原因而爆炸,没有人会想到它。
无论如何,如果你的项目,一般的答案是把它扔到顶部,那么在Runtime Exception中包装是完全有效的。需要考虑的几件事情:
坚持异常链接。不执行此操作的唯一原因是,如果要序列化异常,那么包含不可序列化成员的一些异常会使事情变得有趣。情况似乎并非如此,因此不允许吞咽异常。如果必须,请使用initCause。这是我们项目中的一个小帮手方法:
public static <T extends Throwable> T initCause(T newException, Throwable cause) {
return (T) newException.initCause(cause);
}
这有助于人们避免抛出异常。
我更喜欢避免不必要的RuntimeException和Error Throwables链接,当一个方法上有许多不同的Checked Exceptions并且开发人员只捕获Exception时不可避免地会发生这种情况,所以我推荐一个静态方法,它做了这样的事情:
public static void throwRuntimeExceptionFromThrowable(Throwable e) {
if (e == null) {
return;
} else if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else if (e instanceof Error) {
throw (Error) e;
} else {
throw new RuntimeException(e.getMessage(), e);
}
}
这有两种选择。一个是使它无效(就像这个代码那样),它具有调用者的优点,永远不会忘记抛出结果。缺点是如果你有这样的东西:
public Object someMethod() {
try {
return getTheObject();
} catch (Exception e) {
throwRuntimeExceptionFromThrowable(e);
}
}
编译器不喜欢你。你必须在catch之后返回,并在try之前声明一个变量。
另一个选项是将Exception作为RuntimeException返回(只是抛出Error)并让调用者执行throw。编译器更快乐,但是调用者可能忘记这样做,并且在没有抛出它的情况下调用该方法,然后吞下异常。
答案 1 :(得分:1)
异常应由与其相关的图层处理。 因为检查异常并不意味着您可以处理它,或者您必须在应用的每一层处理它。此时您可能希望将它们变为运行时异常。因此,您可以忽略(记录它们)的异常,无法恢复的异常以及可以恢复的异常。问题是相同的异常类型,例如SQLException,可以输入多个类别。 IOException也是另一个例子。 无法恢复的编程错误应该是运行时异常,应该靠近容器进行记录,或让您的应用程序“轻轻地”失败。在jdbc PreparedStatement中访问无效索引是编程错误。 有连接问题不是。因此,在数据层,您设法进行区分,然后将不可恢复的异常转换为运行时异常并抛出它。有时它并不意味着重试连接将起作用。 业务方法应该只关注业务相关的异常,这就是为什么你不在代码中的任何地方处理NullPointerExceptions或ArrayIndexOutOfBoundsException而你不必将它们放在方法签名中。同样的逻辑适用于计算部门员工平均工资的数据源不可知业务方法,它不应该抛出SQLExceptions但是如果用户提供了错误的部门,则应抛出诸如InvalidDeptException之类的东西。码。 引发声明也是自我记录代码,如果你抛出自己的运行时异常,请务必正确记录。
答案 2 :(得分:1)
一般情况下,我建议您遵循案例中的Fault Barrier
模式 - 这是对您计划遵循的方法的进一步阐述。请在此处查看:http://www.oracle.com/technology/pub/articles/dev2arch/2006/11/effective-exceptions.html(请参阅an older review of it)。
对于电子邮件,不确定您的具体情况。总的来说,这听起来像AOP的完美案例。如果你在JEE5中,那么自定义@Interceptor
可能是有序的 - 由于运行时异常可以在那里编码常见的“非中断”逻辑,然后你可以将它绑定到多个bean /方法。
答案 3 :(得分:0)
对于数据库访问异常,我建议查看Spring如何处理它们。我发现这很容易在实践中使用。
答案 4 :(得分:0)
你在哪里知道你永远无法从SQLException(以及其他)恢复?在精心编写的代码中,您经常可以。首先,整个SQLTransientException层次结构适用于您可以从中恢复的异常(例如SQLTransientConnectionException)。将异常视为不可恢复的,实际上可以处理它们是一个常见的错误。
我认为您的损失政策对于电子邮件发生故障等轻微错误没有任何不妥。当然,应该通知用户。