50.4. 将例外映射到 Responses


概述

有些实例会抛出 WebApplicationException 异常不现实或不可能。例如,您可能不希望捕获所有可能的异常,然后为它们创建一个 WebApplicationException。您可能还希望使用自定义例外来更轻松地处理应用程序代码。

为了处理这些情况,JAX-RS API 允许您实施自定义异常提供程序,该提供程序生成要发送到客户端的 Response 对象。通过实施 ExceptionMapper<E> 接口来创建自定义异常提供程序。当使用 Apache CXF 运行时注册时,每当抛出类型 E 异常时,将使用自定义供应商。

如何选择例外映射程序

两个情况下都会使用例外映射器:

  • 当抛出任何异常或其子类时,运行时将检查适当的异常映射器。如果处理特定的异常抛出,则会选择一个异常映射器。如果抛出的具体例外映射程序没有例外,则会选择例外的超级类例外映射器。
  • 默认情况下,WebApplicationException 将由默认的映射程序 WebApplicationExceptionMapper 处理。即使注册了额外的自定义映射器,它可能会处理 WebApplicationException 异常(例如,自定义 RuntimeException 映射器),也不会 使用自定义映射器,而是使用 WebApplicationExceptionMapper

    但是,可以通过在 Message 对象中将 default.wae.mapper.least.specific 属性设为 true 来更改此行为。启用此选项后,默认的 WebApplicationExceptionMapper 会重新分配给最低优先级,以便处理带有自定义例外映射器的 WebApplicationException 异常。例如,如果启用了此选项,可以通过注册自定义 RuntimeException 映射器来捕获 WebApplicationException 异常。请参阅 “为 WebApplicationException 注册异常映射器”一节

如果没有为异常找到异常,则会将异常嵌套在 ServletException 异常中,并传递到容器运行时。然后,容器运行时将确定如何处理异常。

实施异常映射器

异常映射程序是通过实现 javax.ws.rs.ext.ExceptionMapper<E> 接口来创建的。如 例 50.5 “例外映射器接口” 所示,接口具有单一方法 toResponse (),它将原始异常取为参数并返回 Response 对象。

例 50.5. 例外映射器接口

public interface ExceptionMapper<E extends java.lang.Throwable>
{
  public Response toResponse(E exception);
}

异常映射程序创建的 Response 对象由运行时处理,就像任何其他 Response 对象一样。生成的对消费者的响应将包含在 Response 对象中封装的状态、标头和实体正文。

异常映射程序实现被视为运行时的供应商。因此,它们必须使用 @Provider 注释进行解码。

如果在构建 Response 对象时出现异常,则运行时会向消费者发送状态为 500 Server Error 的响应。

例 50.6 “将异常映射到响应” 显示一个例外映射程序,它截获 Spring AccessDeniedException 异常,并生成带有 403 Forbidden 状态和空实体正文的响应。

例 50.6. 将异常映射到响应

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;

import org.springframework.security.AccessDeniedException;

@Provider
public class SecurityExceptionMapper implements ExceptionMapper<AccessDeniedException>
{

  public Response toResponse(AccessDeniedException exception)
  {
    return Response.status(Response.Status.FORBIDDEN).build();
  }

}

运行时会捕获任何 AccessDeniedException 异常,并创建没有实体正文和 403 状态的 Response 对象。然后,运行时会将 Response 对象处理为正常响应。结果是消费者将收到 HTTP 响应,状态为 403

注册异常映射器

在 JAX-RS 应用可以使用异常映射程序之前,必须将异常映射器注册到运行时。异常映射程序使用应用程序配置文件中的 jaxrs:providers 元素与运行时注册。

jaxrs:providers 元素是 jaxrs:server 元素的子级,包含 bean 元素的列表。每个 bean 元素定义一个异常映射器。

例 50.7 “将异常映射器注册到运行时” 显示 JAX-RS 服务器,配置为使用自定义例外映射器 SecurityExceptionMapper

例 50.7. 将异常映射器注册到运行时

<beans ...>
  <jaxrs:server id="customerService" address="/">
    ...
    <jaxrs:providers>
      <bean id="securityException" class="com.bar.providers.SecurityExceptionMapper"/>
    </jaxrs:providers>
  </jaxrs:server>
</beans>

为 WebApplicationException 注册异常映射器

WebApplicationException 异常注册例外映射程序是一个特殊情况,因为此异常类型由默认的 WebApplicationExceptionMapper 自动处理。通常,即使您注册了您要处理 WebApplicationException 的自定义映射程序,它仍将继续由默认的 WebApplicationExceptionMapper 处理。要更改此默认行为,您需要将 default.wae.mapper.least.specific 属性设为 true

例如,以下 XML 代码演示了如何在 JAX-RS 端点上启用 default.wae.mapper.least.specific 属性:

<beans ...>
  <jaxrs:server id="customerService" address="/">
    ...
    <jaxrs:providers>
      <bean id="securityException" class="com.bar.providers.SecurityExceptionMapper"/>
    </jaxrs:providers>
    <jaxrs:properties>
      <entry key="default.wae.mapper.least.specific" value="true"/>
    </jaxrs:properties>
  </jaxrs:server>
</beans>

您还可以在拦截器中设置 default.wae.mapper.least.specific 属性,如下例所示:

// Java
public void handleMessage(Message message)
{
    m.put("default.wae.mapper.least.specific", true);
    ...
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.