有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java更好地理解J2EE环境中的异常和日志记录

我试图更好地理解j2ee环境中的异常处理和日志记录,以重构一些遗留代码(我们使用log4j作为日志记录机制)。我们当前的大多数代码都与业务层上的以下代码类似,但是,我希望切换到未检查的异常并忽略它们,除非在某个地方处理它们是有意义的:

try {
    doSomething();
} catch (MyException e) {
    log.error("Exception:", e);
    throw e;
}

在业务层抛出异常之后,异常会传播到表示层,表示层会再次捕获异常并通常将其包装在PortletExceptionServletException中,然后再次抛出异常。然后,它由一个Spring处理程序处理,该处理程序向用户显示一条“友好”消息。我最终只希望处理我们希望显示特定错误消息的异常,而忽略其他所有内容

问题:

  1. 是否需要在业务层中记录异常?如果没有,请 我需要记录所有异常(尤其是未检查的异常)
  2. 未使用log4j记录的未捕获异常会发生什么情况? (如果它们仍然打印在控制台中,那么 log4j?)

我对这个过程是如何运作的感到困惑

谢谢

编辑:如果外部库(Spring、Hibernate等)中发生异常,是否假定这些异常将使用正在使用的任何日志机制打印出来?在这种情况下,我想我只需要记录代码抛出的异常。。。还是说我离基地太远了


共 (6) 个答案

  1. # 1 楼答案

    首先,您可以而且必须记录所有异常的异常堆栈跟踪。事实上,在我看来,如果您只记录发生了异常,那么您可能根本不记录它。然而,这通常会导致对异常的放松看法。您应该努力做到的是拥有2个日志文件或一个特定类别,如果该类别中存在异常,则意味着发生了关键事件,必须加以解决。即使这意味着多次记录相同的异常。与其说没有,倒不如说太多

    其次,可以将所有异常更改为检查异常—大多数异常是不“可恢复的”。我所做的工作很好,就是简单地将所有事务包装在记录异常的异常处理包装器中,然后我可以保证所有异常都被记录。此外,创建一组扩展运行时异常的异常类——这比将异常作为运行时异常重新引用要好得多,因为在包装异常时,内部异常堆栈跟踪通常不会完整记录

    第三,重要的是创建一种机制,将过滤到前端的异常映射到后端原因。这很有挑战性,但很重要。如果您可以将用户看到的错误映射回日志文件中的异常堆栈跟踪,则很容易跟踪这些错误

  2. # 2 楼答案

    在继续之前,请仔细查看:

    The following are some of the generally accepted principles of exception handling:

    1. If you can't handle an exception, don't catch it.
    2. If you catch an exception, don't swallow it.
    3. Catch an exception as close as possible to its source.
    4. Log an exception where you catch it, unless you plan to rethrow it.
    5. Structure your methods according to how fine-grained your exception handling must be.
    6. Use as many typed exceptions as you need, particularly for application exceptions.

    Point 1 is obviously in conflict with Point 3. The practical solution is a trade-off >?between how close to the source you catch an exception and how far you let it fall before you've completely lost the intent or content of the original exception.

    IBM DeveloperWorks: EJB best practices

    通常建议您在业务层对应用程序异常使用检查异常。我更喜欢遵循业务界面模式,将业务层与用户界面和web层分离。这将允许我将您的业务层视为服务层库,调用方在调用此层时可能希望以不同的方式处理不同的情况。这就是您可能希望包含已检查异常的原因之一,因为您可以对不同的异常做出不同的反应。此外,包括检查过的异常通常会帮助调用方代码更好地了解调用某些功能时可能出现的不同情况。值得一看业务委托模式,以及它如何帮助您处理异常。简而言之,business delegate pattern允许您在业务层和web层之间创建一个非常薄的层,您可以在其中执行异常处理之类的操作

    无论您如何执行此操作,请确保您理解向JavaEE应用程序添加应用程序异常的含义。您可能需要研究它如何与事务管理逻辑交互,特别是在事务回滚时。在我的工作中,我必须添加@ApplicationException(rollback=false),以禁止事务管理器在抛出异常并向上传播时回滚我的事务

    您可能知道我正在使用EJB,但是这些概念可能也非常适用于您的设计

    回到你的问题:

    Is it necessary to log exceptions in the business tier?

    如果您计划稍后登录,则不必这样做。您最好在高级别上设计一个日志策略,并在那里记录所有捕获的异常

    If not, do I need to log exceptions at all (especially unchecked ones)?

    我认为您应该记录异常,因为这将有助于您以后调试任何问题。如果异常传播并在他/她的屏幕上打印出来,而您不进行处理,那么用户通常没有足够的悟性来捕获可能产生的任何输出

    What happens to uncaught exceptions that are not logged using log4j? (If they're still printed in the console, what's the purpose of log4j?)

    我认为它最终会被web容器捕获并打印到控制台。如果异常向上传播并到达web容器异常处理安全网,则您的异常将失去控制。这通常是不良设计的标志。最好控制例外情况。为什么不知道容器将如何对未捕获的异常作出反应?此外,该例外情况对用户有多大的好处?我认为来自未捕获异常的信息几乎是无用的,因为它们离错误源太远了,以至于在调试时变得无关紧要,难以处理

  3. # 3 楼答案

    您不需要捕获业务异常(只要未选中)。您不需要处理它们或记录它们。你可以把它们吞下去。问题是——这样的例外是什么

    异常表示应用程序工作流中的某些不适当行为。如果它被选中,通常情况下,你可以对它做一些事情-尝试再次执行一些操作,做一些变通,尝试不同的操作,等等

    如果未选中,则通常是您不知道如何或无法处理的异常

    如果您所做的只是捕获一个异常并记录它,那么这就被认为是一种代码气味。它不像吞下它那样坏,但它仍然不好

    某些容器(即EJB)需要记录发生的异常。此外,在EJB3中。x如果您在JTA管理的事务中,并且不会捕获未标记为@ApplicationException(rollback=false)的未检查异常,那么事务将自动回滚。这可能就是为什么你可以看到一些尝试。。。捕获只包含日志代码的块

    如果您想摆脱业务逻辑中的异常处理代码,那么可以引入一个拦截器,该拦截器将对特定异常做出适当的反应

  4. # 4 楼答案

    我们绝对不必为了记录异常而处理异常。我认为,如果我们随后抛出包含源异常作为其原因的其他异常,或者如果我们在抛出异常时实现一些必须在当前层中实现的逻辑,那么我们应该捕获异常

    是的,将所有方法声明为throws MyException有点冗长。这就是为什么Spring(您使用的)更喜欢处理未检查的异常。顺便说一句,这是Java7中的新特性:您可以忽略异常,而不声明方法抛出异常

    我相信,对于开发向第三方应用程序公开API的库,我们仍然需要检查异常。应用层异常应该主要在运行时发生,并在一个中心位置捕获

  5. # 5 楼答案

    您可以创建自己的异常层次结构来包装它们,以便快速识别它在应用程序体系结构中的起源位置。此外,还可以进一步提供代码和理由,以涵盖用例的主要部分

    当潜在的多个客户机猛烈抨击同一个用例或遇到瓶颈时,日志记录可以帮助您识别事件的顺序。日志记录为您提供了一个可追溯的序列,因为请求增加了。此查询中存在拥塞,导致其超时,从而导致其他用户看到另一个异常

    处理应用程序并将其显示给用户是另一个问题

    干杯

  6. # 6 楼答案

    Is it necessary to log exceptions in the business tier?

    没有。但是更多的日志=更好地理解正在发生的事情。换句话说,日志越多,性能越低

    What happens to uncaught exceptions that are not logged using log4j?

    你把它们弄丢了。你可以在需要的地方保存日志,并使用过滤器只获取当前的实际日志