50.4. 将例外映射到响应
概述
存在引发 WebApplicationException 异常的实例是不现实或不可能的。例如,您可能不希望捕获所有可能的例外情况,然后为它们创建一个 WebApplicationException。您可能还想使用自定义例外,以便更轻松地处理应用程序代码。
若要处理这些情况,您可以使用 JAX-RS API 实施自定义异常提供程序,该提供程序生成要发送到客户端的 Response
对象。通过实施 ExceptionMapper<E> 接口来创建自定义异常供应商。当与 Apache CXF 运行时注册时,每当引发 E
类型的异常时,将使用自定义提供程序。
如何选择异常映射程序
在两个情况下,使用异常映射程序:
- 如果引发任何例外或其子类,则运行时将检查相应的异常映射程序。如果指定映射程序会抛出特定异常,则会选择一个例外映射程序。如果没有为引发特定例外的异常映射程序,则会选择异常最接近的超级分类的异常映射程序。
默认情况下,WebApplicationException 将由默认 mapper
WebApplicationExceptionMapper
处理。即使注册了额外的自定义映射程序,这可能会正确处理 WebApplicationException 异常(例如,自定义RuntimeException
mapper),也不会 使用自定义映射程序,并将改为使用WebApplicationExceptionMapper
。这种行为可以改变,但通过将
Message
对象上的default.wae.mapper.least.specific
属性设为true
来更改。启用此选项后,默认的WebApplicationExceptionMapper
会被重新委派到最低优先级,以便可以处理 WebApplicationException 异常(带有自定义 mapper)。例如,如果启用此选项,可以通过注册自定义RuntimeException
mapper 来捕获 WebApplicationException 异常。请参阅 “为 WebApplicationException 注册异常映射程序”一节。
如果没有找到异常的 mapper,则异常嵌套在 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
注释进行解码。
如果在异常 mapper 正在构建 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
对象,因为它会正常的响应。结果是消费者会收到状态 403
的 HTTP 响应。
注册异常映射程序
在 JAX-RS 应用可以使用例外映射程序之前,例外映射程序必须使用运行时进行注册。异常映射程序使用应用配置文件中的 jaxrs:providers
元素在运行时注册。
jaxrs:providers
元素是 jaxrs:server
元素的子级,含有 bean
元素的列表。每个 bean
元素都定义一个例外映射程序。
例 50.7 “使用运行时注册异常映射程序” 显示配置为使用自定义例外映射 SecurityExceptionMapper
的 JAX-RS 服务器。
例 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); ...