在Java中提取用户友好的exception详细信息

我有一个我正在处理的J2EE Web应用程序,当发生exception时,我想获得有关exception的一些基本细节并记录它。 我正在记录的消息应该是非常基本的,这可能对运行Web服务器的人有意义。

使用e.getMessage()是最好的记录吗? 谢谢。

我默认获得整个堆栈跟踪,这样我可以看到错误发生时发生的更多上下文。

如果你使用log4j并将exception传递给它的一个日志记录方法,它将打印你给它的任何消息,以及exception的消息及其堆栈跟踪:

 log.error("caught an exception", throwable); 

如果您有容易出错的事情,比如调用Web服务,您可以将exception中包含的exception包装为您分配非常明确的消息,因此当管理员看到该消息时会告诉他们发生了什么。

就此而言,您可以保留单独的日志,一个用于开发人员的堆栈跟踪,另一个用于编写管理员友好消息。 您可以使用exception处理程序尝试将exception映射到友好消息,然后将该消息写入管理日志。

我做了一些非常相似的事情。 但首先,您根本不需要将错误传达给用户。 告诉他们错误是如何发生的,因为无论如何你都要记录它。 (如果用户知道由于NPE或IO错误而发生错误,即使您将其重命名为更“友好”的术语,这是否有意义?)

首先,您可能需要考虑将所有exception重新抛出为运行时(未经检查)exception 。 这将强制集中和一致地记录错误。 否则,您将不得不希望error handling代码的每个实例都能正确记录它。 要重新抛出SQLExceptions,例如:

  try{ conn.close(); } catch(SQLException ex){ //logger.error("Cannot close connection"); //don't log this here, do it centrally throw new RuntimeException(ex); } 

您需要将用户转发到一般错误页面,只是告诉他们发生了错误。 这向他们表明他们所做的一切都没有得到处理。 这非常重要,因此他们不会反击并继续尝试一次又一次地输入付款。 让他们知道出现了问题,并且(a)联系服务台或(b)在默认错误页面中放置一个表格,该页面可以记录故障单或向服务台发送电子邮件。 要完成此任务,您需要在web.xml中定义它:

  500 /Error.jsp  

接下来,在error.jsp页面(或servlet)内部,如果容器允许您将堆栈跟踪引用为request.getAttribute("javax.servlet.error.message"));在此处记录错误request.getAttribute("javax.servlet.error.message"));

或者 ,创建一个仅对响应起作用的filter,如下所示:

 try { chain.doFilter(req, res); } catch (Exception e) { logger.error("pass any Mapped Diagnostic Context here", e); //log here, centrally throw new RuntimeException(e); //throws back to the container so that the error page will be seen } 

这将捕获所有传播的exception(未经检查和未被捕获),记录它们,然后重新抛出它们以便它们调用错误页面。 这将导致错误报告

  1. 准确(每个错误实例一个日志)
  2. 可靠(如果用户收到错误,您将收到日志记录详细信息
  3. 一致(标准化,如果您实施重新抛出已检查的exception未经检查,您将能够看到所有exception,并且还可以阻止用户进入容易出错的区域,因为他们将垃圾插入表格或者表格中,因此您可能面临灾难性的数据清理任务左键表无人居住)

最后,您可能需要考虑使用log4j并使用输出到某处的appender来查看错误,而无需等待操作团队将它们发送给您。 如果您经常维护应用程序,那么就更容易了。

有可能。 问题是,如果没有至少调用方法信息,这不是非常有用

考虑以下内容

 /** * Returns class.method:linenumber of the caller (or, more accurately * the caller of the caller). *  * * 

* Returns unknown if stacktrace is mucked up. Uses reflection and string * concatenation, so don't overuse this for trivial matters. For exception * handling and for logging, on the other hand, it is useful. * * @return method name of caller's caller and line number (String) */ public static String returnCaller( Class ignoreMe ) { String ignoreClass = ignoreMe.getName(); StackTraceElement[] steArr = new Throwable().getStackTrace(); if (steArr != null) { // subscript 1 is returnCaller(). // subscript 2 is the caller of returnCaller() // subscript 3 is the caller of the caller of returnCaller()... for( int i = 0; i < steArr.length; i++) { if (steArr[i] == null) break; String myclass = steArr[i].getClassName(); if (myclass.equals(ErrorHandle.class.getName())) continue; if (ignoreClass.equals(myclass)) continue; return steArr[i].getClassName() + "." + steArr[i].getMethodName() + ":" + steArr[i].getLineNumber(); } } return "unknown"; }

仅记录exception消息不是一个好主意; 你失去了发生exception的那一行,这使得在代码中找到记录的exception大多数时候都是噩梦。

记录整个exception/堆栈跟踪。

如果您只是想通知系统管理员,那个问题出了问题,但是没有开发人员必须查看它,因为它是一些暂时已知的问题,或者可以通过系统管理员解决,一个好的描述性消息就足够了。 在所有其他情况下,每个开发人员都非常感谢获得完整的堆栈跟踪以及exception时系统的状态(输入参数等等)(如果可用)。