2011-11-04 120 views
1

我想更好地了解在j2ee环境重构一些旧代码异常处理和日志记录(我们使用log4j我们的记录机制)。我们的大多数当前的代码做类似下面的代码在业务层,但是,我想切换到unchecked异常,只是忽略它们,除非是有意义的地方处理它们:更好地了解例外和记录在J2EE环境

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

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

问题:

  1. 是否需要登录到业务层的异常?如果没有,请问 我需要记录异常(特别是未经检查的异常)?
  2. 未使用log4j记录的未捕获异常会发生什么? (如果他们在控制台上还印着,什么是 log4j的目的是什么?)

我很困惑,过程是如何工作的?

感谢。

编辑:如果在外部库(Spring,Hibernate等)中发生异常,是否认为这些异常将使用任何正在使用的日志记录机制打印出来?在这种情况下,我想我只需要记录我的代码抛出的异常......或者我在这里基地?

回答

4

在进行下一步之前,请大家在仔细一看:

以下是一些的 异常处理的普遍公认的原则:

  1. 如果无法处理异常,不要抓住它。
  2. 如果发现异常,请不要吞下它。
  3. 尽可能靠近其来源捕捉异常。
  4. 记录一个例外,你可以捕捉它,除非你打算重新抛出它。
  5. 根据您的异常处理的细致程度来构造您的方法。
  6. 根据需要使用尽可能多的类型异常,特别是对于应用程序异常。

第1点显然与第3点相冲突。实际的解决方案是在您完全失去原点之前,您接近异常的源头距离多远以及落差有多远之间的平衡>?意图或原始异常的内容。

IBM DeveloperWorks: EJB best practices

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

无论您如何着手这样做,请确保您了解向Java EE应用程序添加应用程序异常的含义。您可能需要调查它与交易管理逻辑的交互方式,特别是在涉及事务回滚时。在我的工作中,我必须添加一个@ApplicationException(rollback = false)来禁止事务管理器在抛出异常并向上传播时回滚事务。

您可能能够告诉我正在使用EJB,但这些概念也可能非常适用于您的设计。

所以回到你的问题:

是否需要登录到业务层的异常?

如果您打算稍后记录它,则不需要。您最好设计一个高层次的日志记录策略,并记录所有捕获的异常。

如果不是,我是否需要记录异常(特别是未检查的 个)?

我认为你应该记录异常,因为这会帮助你稍后调试任何问题。用户通常不足以捕获任何可能会产生的输出,如果异常传播并在您处理它时被打印在他/她的屏幕上。

未使用log4j记录的未捕获异常会发生什么? (如果他们在控制台上还印着,什么是 log4j的目的是什么?)

我认为它最终会由Web容器被捕获并打印到控制台。如果异常向上传播并到达Web容器异常处理安全网,那么您的异常就会失控。这通常是设计不好的标志。如果你控制你的例外情况,这是最好的。为什么想知道容器如何对未捕获的异常做出反应?这种异常对用户有多大益处?我认为从未捕获的异常中提供的信息几乎是无用的,因为它们距离错误的来源太远,在调试时它们变得无关紧要并且很难处理。

0

我们绝对没有处理异常只是为了记录他们。如果我们抛出其他异常(包含源异常)作为其原因,或者如果我们实现了某些在抛出异常时必须在当前层中实现的逻辑,我们应该发现异常。

是的,这是一个有点冗长的所有方法声明为throws MyException。这就是Spring(你使用)更喜欢使用未经检查的异常的原因。顺便提一下,这是Java 7中的新特性:您可以忽略异常而不声明该方法抛出它。

我认为,我们仍然需要检查暴露的API的第三方应用程序库的发展异常。应用程序层例外应该主要是运行时并且可以在一个中心位置捕获。

0

是否需要登录到业务层的异常?

不可以,但更多的日志=更好的理解到底是怎么回事。换句话说,更多日志=更低的性能。

未使用log4j记录的未捕获异常会发生什么?

你失去了它们。记录器可以将日志保存在您需要的地方,并使用过滤器来获取目前仅有的实际日志。

0

不需要捕捉业务异常(只要它未被选中)。你不需要处理它们或记录它们。你可以吞下它们。问题是 - 这是什么例外?

异常会在应用程序的工作流程中发出一些不适当的行为。如果检查了你,通常可以做一些事情 - 尝试再次做一些操作,做一些解决方法,尝试不同的行动等。

如果未选中,它通常是一个例外,你不知道如何或可以没办法。

它被认为是一个代码气味,如果你只是捕获一个异常并记录它。它不是,因为不好吞咽它,但仍然 - 这不好。

某些容器(即EJB)需要记录发生的异常。此外,在EJB 3.x中,如果您处于JTA托管事务中,并且不会捕获未标记为@ApplicationException(rollback=false)的未检查异常,则事务将自动回滚。这可能就是为什么你可以看到一些try ... catch块,只是内部记录代码。

如果你想摆脱业务逻辑中的异常处理代码,你可能会引入一个拦截器,它会在特定的异常情况下做出适当的反应。

HTH!

0

首先,您可以并且必须记录所有异常的异常堆栈跟踪。事实上,如果您只记录发生异常的IMO,您可能不会记录它。但是,这通常导致的是对异常的放松观点。你应该争取的是有2个日志文件或一个特定的类别,如果在这个类别的例外,他们的意思是发生了关键的事情,必须解决。即使这意味着多次记录相同的异常。太多而不是根本。其次,将所有异常更改为检查异常都可以 - 大多数异常不是“可恢复的”。我所做的工作很好,只是将所有事务包装在一个异常处理包装器中,该包装器记录了异常,然后我可以保证记录所有异常。此外,创建一系列扩展运行时异常的异常类 - 这比重新抛出异常作为运行时异常要好得多,因为当您封装异常时,内部异常堆栈跟踪通常不会被完全记录。

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

1

您可以创建自己的异常层次结构来包装它们以快速识别它的源自应用程序体系结构的位置。此外,还可以进一步提供代码和原因,以涵盖用例不当的情况。

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

处理应用程序并向用户显示时是另一个问题。

干杯!