【发布时间】:2010-09-07 04:54:03
【问题描述】:
如果您想以相同的方式处理每个失败,例如通过记录它并跳到下一个请求,向用户显示消息并处理下一个事件等,未经检查的异常是可以的。如果这是我的用例,我所要做的就是在我的系统中捕获一些高级别的一般异常类型,并以相同的方式处理所有事情。
但我想从特定问题中恢复过来,我不确定用未经检查的异常处理它的最佳方法。这是一个具体的例子。
假设我有一个使用 Struts2 和 Hibernate 构建的 Web 应用程序。如果我的“动作”出现异常,我会记录下来,并向用户表示歉意。但是我的 Web 应用程序的功能之一是创建新的用户帐户,这需要一个唯一的用户名。如果用户选择了一个已经存在的名称,Hibernate 会在我的系统内部抛出一个org.hibernate.exception.ConstraintViolationException(未经检查的异常)。我真的很想通过要求用户选择另一个用户名来从这个特定问题中恢复过来,而不是给他们同样的“我们记录了你的问题,但现在你已经被淹没了”的消息。
这里有几点需要考虑:
- 有很多人同时创建帐户。我不想在“SELECT”之间锁定整个用户表以查看名称是否存在,如果不存在则“INSERT”。在关系数据库的情况下,可能有一些技巧可以解决这个问题,但我真正感兴趣的是由于基本竞争条件而无法预先检查异常的一般情况。同样的事情也适用于在文件系统上查找文件等。
- 鉴于我的 CTO 倾向于通过阅读“Inc.”中的技术专栏而导致的偷渡式管理,我需要围绕持久性机制设置一个间接层,以便我可以抛弃 Hibernate 并使用 Kodo 或其他任何东西,而无需更改任何内容除了最底层的持久化代码。事实上,在我的系统中有几个这样的抽象层。尽管存在未经检查的异常,如何防止它们泄漏?
- 已声明的检查异常的弱点之一是必须在堆栈上的每次调用中“处理”它们——要么通过声明调用方法抛出它们,要么通过捕获它们并处理它们。处理它们通常意味着将它们包装在另一个适合抽象级别的类型的检查异常中。因此,例如,在检查异常领域,我的 UserRegistry 基于文件系统的实现可能会捕获
IOException,而数据库实现会捕获SQLException,但两者都会抛出隐藏底层实现的UserNotFoundException.如何利用未经检查的异常,在不泄露实现细节的情况下减轻每一层包装的负担?
【问题讨论】: