当我们的应用程序抛出我们捕获的错误时,我们将消息和堆栈跟踪放在专门为我们的应用程序创建的日志文件中(myapp.log)。例如:
public class SomeClass {
OurLogger log = OurLogger.getLogger ("myapp", SomeClass.class);
public void someMethod {
try {
//code
}
catch (DataAccessException e)
{
log.error(e.getMessage(), e);
}
}
}
我们这样做是因为我们所处的环境中有多个应用程序驻留在应用程序服务器上......我们的应用程序日志应与server.log
分开。
但是,对于某些我们没有捕获错误的情况......堆栈跟踪正在server.log
上写入。在这些情况下,我们也希望将堆栈错误发送到myapp.log
。我知道我们可以在web.xml中定义一个异常并转发到一个jsp页面,但在这种情况下,是否有办法不将堆栈跟踪发送到server.log
而是发送到myapp.log
?除了通过代码更改捕获异常当然。
答案 0 :(得分:1)
但是,对于某些我们没有发现错误的情况......堆栈跟踪正在写在server.log上
对我而言,这是一种正常行为。某些例外(例如RuntimeException
)被应用程序服务器捕获并记录在应用程序服务器日志文件中(对于使用GlassFish的域是全局的)。并且你不会看到它们全部捕获,你希望容器在这种情况下完成它的工作,例如回滚一个事务,或者你会得到令人讨厌的错误。
在这些情况下,我们也希望将堆栈错误发送到myapp.log。我知道我们可以在web.xml中定义一个异常并转发到一个jsp页面,但在这种情况下,是否有一种方法可以不将堆栈跟踪发送到server.log而是发送到myapp.log?
据我所知,这是不可能的。即使您添加<error-page>
,它仍然是将捕获异常的应用服务器,因此这不会解决您的“问题”。即使您使用servlet过滤器来捕获Throwable
(我不会这样做)并在应用程序级别记录它,您将不得不重新抛出它以让容器完成其工作,如上所述。所以它不会完全解决你的“问题”。
除了通过代码更改捕获异常当然。
不要这样做,你不想要抓住它们!
答案 1 :(得分:0)
答案是appserver / webcontainer依赖。这超出了Java EE规范。有关详细信息,请参阅其文档的“日志记录”章节。有些人可能会根据需要支持该构造,但其他人可能不会。
最佳解决方案是拥有一个全局异常处理程序,例如您自己提到的<error-page>
。让它听java.lang.Exception
或Throwable
。或者,您可以拥有(或重复使用)Filter
来监听/*
并将chain.doFilter(request, response)
放在try-catch
块Exception
或Throwable
内}}
编辑:以下是评论中要求的一些代码示例。首先是监听Filter
的{{1}}。我之前解释它的方式几乎就是编写代码本身:
/*
请注意,我建议将其放在网络应用程序的“前端控制器”public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
try {
chain.doFilter(request, response);
} catch (Exception e) {
logger.error("Caught an uncaught exception.", e);
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
req.getRequestDispatcher("error.jsp").forward(req, res);
}
}
中。我不知道你是否正在使用任何东西(虽然这样做太明显了)但我也不知道你是否正在使用一些可能已经提供的现有框架。为此解决方案。
错误页面,好吧,你不能绕过一个丑陋的小脚本来记录异常。
Servlet
请注意,此仍然将例外记录到<% logger.error("Caught an uncaught exception", exception); %>
。在这一点上,转身已经太晚了。