一般问题
编写服务方法时,引发许多异常与将其抽象为通用ServiceException
相比有其优点和缺点。如果抛出许多异常,则可以告诉客户端确切的错误原因,以便客户端可以更明智地处理错误。如果将它们抽象为一个ServiceException
(例如,通过exception wrapping),那么您将隐藏发生错误的详细信息,这在某些情况下可能有用,而在其他情况下却是有害的。
例如,通过抛出泛型DaoException
来隐藏DAO类中出错的细节可能很有用。这样,客户端不必知道您是从文件,Web服务还是从关系数据库中进行读取。但是,假设您正在验证用户输入,并且至少有四件事可能会导致用户输入出错。在后一种情况下抛出四个不同的异常不是更明智,对于验证出错的每一件事都抛出一个异常?
我的具体问题
在我当前的项目中,我正在研究一种服务方法,该方法将树状结构保存到关系数据库中。它必须验证树,并且至少有四件事可能与树有关。可能存在重复的节点,或者节点可能缺少其必填的X,Y,Z字段。因此,服务方法抛出四个不同的异常是有意义的:DuplicateNodeException
,MissingXException
,MissingYException
,MissingZException
。
但是服务方法还使用DAO类,该类通过JdbcTemplate抛出DataAccessException
。我想知道如何处理此DataAccessException
。将其包装为ManagerException
,然后再次包装为ServiceException
,并作为ServiceException
处理,是否有意义?然后,我将混合两种方法(a)抛出特定的描述性异常,以及(b)抛出通用包装异常。在这里混合使用这些方法是一个好主意吗?
我问的原因是,对于我来说,捕获这四个与验证相关的异常,然后捕获通用的,非描述性的ServiceException
,似乎有点奇怪。似乎很奇怪,因为ServiceException
太抽象了,以至于无法一目了然地知道出了什么问题,您将不得不检查日志并阅读异常消息,或者浏览代码中的调用层次结构。然后,我要求验证将这两种方法混合使用确实是一种好习惯,或者是普遍的,还是明智的,因为从直觉上看,这对我来说很奇怪。在核心Java中是否有任何相似之处,其中两种异常处理方法都在同一方法中使用?
可能的解决方案(根据Andreas的回答)
在Service类中处理此类异常是否有意义?以下是一些伪代码,提出了一种可能的解决方案。这样,我不会创建无用的,已检查的,非描述性的ServiceException,但是我确实具有未检查的异常的全部捕获(通过在末尾捕获Exception)。您对此解决方案有何看法?
class HttpService {
private Service service;
// ...
public HttpServiceResponse saveTree(Node root) {
try {
service.saveTree(root);
} catch (DuplicateNodeException e) {
return HttpServiceResponse.failure(DUPLICATE_NODE_EXCEPTION);
} catch (MissingXException e) {
return HttpServiceResponse.failure(MISSING_X_EXCEPTION);
} catch (MissingYException e) {
return HttpServiceResponse.failure(MISSING_Y_EXCEPTION);
} catch (MissingZException e) {
return HttpServiceResponse.failure(MISSING_Z_EXCEPTION);
} catch (Exception e) {
return HttpServiceResponse.failure(INTERNAL_SERVER_ERROR);
}
}
}
答案 0 :(得分:3)
大多数异常应该是未经检查的,因为它们实际上不是可操作的,即调用者除了传递,记录或使当前执行的任何操作失败之外,实际上无能为力进行中。仅应检查可操作且需要此类调用者操作的异常,这种情况很少见。
如果所有异常均未选中,则表示调用方可以处理单个捕获。由于服务层不再需要包装来自例如在DAO层中,如果需要,调用方 可以捕获并处理特定的异常。