我写了一个宁静的网络服务。RESTful Web 服务的契约是接收参数,通过 SSL 与外部服务通信并响应客户端。服务合同和服务没有问题。服务设计很好,所有已检查的异常都已在 catch 块中捕获,但经过几次服务测试后,似乎未正确处理未检查的异常。有没有办法使用域异常来封装这些未经检查的异常。简单地说,如何处理或预测未经检查的异常。
3 回答
您应该在代码中始终有一个位置来处理所有异常,并且您所描述的内容听起来像是在处理代码的混乱,无论在哪里调用声明检查异常的方法。在遇到检查异常的较低级别代码中使用此代码:
try {
...
catch (RuntimeException e) { throw e;}
catch (Exception e) { throw new RuntimeException(e); }
并在异常屏障(提到的中心位置)使用
try {
...
catch (Throwable t) { // logging, returning error response, whatever
}
finally { // global resource cleanup
}
仅在特殊情况下才需要做更多的事情,您会发现这在代码库中并不常见,即当您的较低级别的方法获取资源时,除了已为每个请求获取的资源之外。一个例子可能是文件 I/O。在这种情况下,当然必须使用 atry-finally
来处理额外的资源,但您仍然不能catch
吞下异常:主要的异常屏障仍然需要知道存在问题并进行清理。
在 RESTful Web 服务的特定情况下,该框架有一个“包罗万象”的处理程序,它会做一些你不喜欢的事情。因此,与这里的其他一些答案相反,添加更多或不同的处理并没有什么坏处。框架的处理程序当然不会为你清理,所以你只能通过自己清理来让事情变得更好。因此,您有两个选择。
您可以根据 JAX-RS 标准将异常映射器添加到您的提供者列表中。
您可以将代码包装在 Throwable 的 try/catch 中,然后在 catch 处理程序中构造一个吸引您的响应。
在不知道您为 JAX-RS 使用什么工具包的情况下,我无法更详细地了解 (1)。
RuntimeExceptions 应该指示编码错误,因此理想情况下您应该修复错误而不是尝试处理它们。不幸的是,一些库开发人员将 RTE 滥用于非 bug 并强迫您捕获它们。您可以将 RuntimeException 包装在 Exception 中。
....
catch (RuntimeException e) {
throw new MyCheckedException("Failed to...", e);
}
编辑:这些天来,这似乎是一个有争议的观点。我知道糟糕的检查异常可能会很痛苦。但是很好地使用受检异常有助于客户和实施者理解合同。当您不关心异常时,将 RuntimeExceptions 用于非错误可能会使在“快乐情况”下使用 API 变得更容易,但当您这样做时,更难知道“悲伤情况”会发生什么。这也使接口的实现者更难知道对它们的期望——它们允许或不允许抛出哪些 RuntimeExceptions 等。