【发布时间】:2015-02-09 22:24:12
【问题描述】:
我正在使用 Jersey/JAX-RS 来实现 RESTful Web 服务。我有一个关于 ExceptionMapper interface 的问题,它似乎没有在任何地方记录。
假设我有以下自定义(扩展 RuntimeException)异常:
FizzException extends RuntimeExceptionBuzzException extends FizzException
现在假设我希望我的异常映射器执行以下Exception-to-Response 映射:
-
FizzException实际上映射到 HTTP 404 NOT FOUND -
BuzzException映射到未经授权的 HTTP 403 - 其他所有内容都映射到 HTTP 500 内部服务器错误
所以,如果我正确理解 API,我需要实现 3 个不同的异常映射器:
@Provider
public class DefaultExceptionMapper implements ExceptionMapper<Exception> {
@Override
Response toResponse(Exception exc) {
// Map to HTTP 500
}
}
@Provider
public class FizzExceptionMapper implements ExceptionMapper<FizzException> {
@Override
Response toResponse(Exception exc) {
// Map to HTTP 404
}
}
@Provider
public class BuzzExceptionMapper implements ExceptionMapper<BuzzException> {
@Override
Response toResponse(Exception exc) {
// Map to HTTP 403
}
}
然而,这让我很好奇:既然我们正在进行异常类继承,那么哪些映射器实际上会触发?例如:
-
BuzzException扩展FizzException,最终扩展Exception。因此,如果抛出BuzzException,哪个映射器会触发:BuzzExceptionMapper、FizzExceptionMapper或DefaultExceptionMapper? - 反过来:当
Exception被抛出时,因为BuzzException最终是Exception,映射器会触发:BuzzExceptionMapper、FizzExceptionMapper或DefaultExceptionMapper?
【问题讨论】:
-
牛是一种动物。所以如果你拿了一头牛,但称它为“动物”,然后把它从山上扔下来,你从山上扔掉的是什么?到头来还是一头牛。同样,如果你抛出一个 BuzzException,那么这就是你从山上抛出的东西——即使你称它为 FizzException。
-
谢谢@Gimby 我有点看到你的类比,但仍然可以看到
BuzzExceptionMapp认为BuzzException是Exception,因此地图抛出Exceptions,是我提出问题的基础。但似乎泽西岛足够聪明,可以进行必要的班级检查,所以不用担心 :-) -
“所以,如果我正确理解 API,我需要实现 3 个不同的异常映射器” - 你没有必须 :- ) 在您的
FizzExceptionMapper中,您可以查看if (e.getClass() == BuzzException.class)。也只是一个 FYI,让你的异常类扩展WebApplicationException并在构造函数中映射响应也很常见,如 here 所示。默认的 Jersey 映射器将处理它。我们不需要创建自己的。除非该异常类已经存在,否则您将需要映射器。
标签: java rest error-handling jersey jax-rs