我创建了一个自定义ExceptionMapper,每次在API中发生异常时都会调用该自定义exceptionMapper,以将其映射到适当的响应。以下是我的自定义异常类:

@Provider
public class ServiceExceptionMapper implements ExceptionMapper<Throwable> {
  private Logger logging = LoggerFactory.getLogger(getClass());

  @Override
  public Response toResponse(Throwable throwable) {
    log.error("There is an exception: ", throwable);


    if (throwable instanceof IllegalArgumentException) {
      return Response.status(Response.Status.BAD_REQUEST).entity(throwable.getMessage()).type    (MediaType.TEXT_PLAIN).build();
    }

    if (throwable instanceof WebApplicationException) {
      WebApplicationException we = (WebApplicationException) throwable;
      return we.getResponse();
    }
    return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(throwable.getMessage()).type(MediaType.TEXT_PLAIN).build();
   }
}


现在,在资源类中,我有一个try和catch块。如果存在异常,catch块应该捕获它并调用自定义异常映射器类。引发异常的常用方法如下:

 catch (Exception e) {
    throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity("Internal Server Error").build());
}


我试图通过以下方式调用异常映射器类:

catch (Exception e) {
    exceptionMapper.toResponse(e);
}


其中ServiceExceptionMapper是类的字段。

最佳答案

ExceptionMapper是做什么用的?


  但是,如何调用自定义异常映射器类以引发相同的异常呢?





  我希望自定义异常映射器类负责抛出API中发生的异常。因此,我不想直接引发异常(我的第二个代码段),而是要调用异常映射器类并希望它引发该异常。


ExceptionMapper背后的想法是将已抛出的Exception映射到Response。检查ExceptionMapper#toResponse(E)方法签名,您将看到它收到扩展了Throwable并且必须返回Response的内容。这种方法由JAX-RS运行时调用。

如果由于某种原因,您不想直接在资源方法代码中引发异常,则可以考虑创建一个实用程序类来执行此操作,然后可以调用其方法来实例化并引发异常。然后ExceptionMapper会将已引发的异常映射到HTTP响应。

使用JAX-RS查找提供商

如果需要对提供程序实例(ExceptionMapper是提供程序)执行运行时查找,则可以使用Providers可注入接口。使用@Context批注将其注入资源类中:

@Context
private Providers providers;


然后,您可以为特定的异常类获取ExceptionMapper

ExceptionMapper<Throwable> exceptionMapper = providers.getExceptionMapper(Throwable.class);




注1:对于可以使用@Context注释注入的其他类型,请参考此answer

注意2:Providers界面API允许您查找以下提供程序:


ContextResolver
ExceptionMapper
MessageBodyReader
MessageBodyWriter

10-08 13:21