我正在处理我正在进行的Web项目上的错误处理,我遇到了一个案例,其中我向用户显示的错误并不是特别有用。我一直用它来获取错误信息,以便显示给我的用户:
catch (Throwable t) {
...
t.getMessage();
...
}
通常效果很好,通常会为用户提供比丑陋的堆栈跟踪更好的消息,而他们不知道该怎么做。但是,在一种情况下,Hibernate抛出异常并显示错误消息:
无法插入[some.class.name.Here]
这是非常无益的。错误的实际原因隐藏在堆栈跟踪中:
仅接受1753年1月1日至9999年12月31日之间的日期。
鉴于第一条错误消息,我不知道出了什么问题。鉴于第二,我至少知道要看看我输入的日期。为了解决这个问题,我这样做了:
catch (Throwable t) {
...
ExceptionUtils.getExceptionMessageWithCauses(t);
...
}
...
public class ExceptionUtils
{
public static String getExceptionMessageWithCauses(Throwable t)
{
if ( t.getCause() == null ) {
return t.getMessage();
} else {
return t.getMessage()
+ "; caused by: "
+ getExceptionMessageWithCauses(t.getCause());
}
}
}
我首先担心的是,如果两个Throwable类相互引用,我可能会进入某种无限循环。或者,类似地,根本原因是如此之深,以至于即使显示来自Throwables的更友好的错误消息也会产生比堆栈跟踪更好的结果。所以,有两个问题:
做这样的事情是“安全的”,还是人们会想到这会在我脸上爆炸的情况?
除了逐个检查每个可能的错误情况之外,还有更好的方法来处理异常吗?
谢谢!
答案 0 :(得分:2)
嗯,您通常会在网络层验证用户输入,因此您就知道错误的输入是什么。如果从hibernate或数据库驱动程序获得SQLException,通常无法自动且精美地获得真正的原因。
我们所做的是捕获可能对用户有意义的所有异常(它们通常是已检查的异常),所有其他异常(通常是RuntimeExceptions)只是用“发生内部错误”消息处理。
我们的一般例外是ValidationException
,它由我们的验证框架抛出,并包含生成一条好消息所需的所有数据(通常是可翻译的)。
编辑:
有时可能需要遍历原因以获得您显示的异常。例如,我们有持久层抛出的异常,但它们通过EJB层传递,因此包含在EJBExceptions
中。因此,我们遍历原因,直到找到一个异常并显示一条好消息或者显示“内部错误”一个。
请注意,通常用户不应该遇到默认的错误消息,因为大多数人不知道这意味着什么(“嗯,什么是NullPointerException ????”)