JAX-RS / 泽西岛如何定制错误处理?

2022-08-31 05:52:52

我正在使用泽西岛学习JAX-RS(又名JSR-311)。我已经成功创建了一个根资源,并且正在使用参数:

@Path("/hello")
public class HelloWorldResource {

    @GET
    @Produces("text/html")
    public String get(
        @QueryParam("name") String name,
        @QueryParam("birthDate") Date birthDate) {

         // Return a greeting with the name and age
    }
}

这非常有效,并且可以处理当前区域设置中由 Date(String) 构造函数理解的任何格式(如 YYYY/mm/dd 和 mm/dd/YYYY)。但是,如果我提供的值无效或不被理解,我得到404响应。

例如:

GET /hello?name=Mark&birthDate=X

404 Not Found

如何自定义此行为?也许是不同的响应代码(可能是“400错误请求”)?如何记录错误?也许在自定义标头中添加问题描述(“错误日期格式”)以帮助进行故障排除?或者返回包含详细信息的整个错误响应以及 5xx 状态代码?


答案 1

有几种方法可以使用 JAX-RS 定制错误处理行为。以下是三种更简单的方法。

第一种方法是创建一个扩展 WebApplicationException 的 Exception 类。

例:

public class NotAuthorizedException extends WebApplicationException {
     public NotAuthorizedException(String message) {
         super(Response.status(Response.Status.UNAUTHORIZED)
             .entity(message).type(MediaType.TEXT_PLAIN).build());
     }
}

要抛出这个新创建的异常,您只需:

@Path("accounts/{accountId}/")
    public Item getItem(@PathParam("accountId") String accountId) {
       // An unauthorized user tries to enter
       throw new NotAuthorizedException("You Don't Have Permission");
}

请注意,您不需要在 throws 子句中声明异常,因为 WebApplicationException 是运行时异常。这将向客户端返回 401 响应。

第二种更简单的方法是简单地在代码中直接构造一个实例。只要您不必实现自己的应用程序异常,此方法就有效。WebApplicationException

例:

@Path("accounts/{accountId}/")
public Item getItem(@PathParam("accountId") String accountId) {
   // An unauthorized user tries to enter
   throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}

此代码也向客户端返回 401。

当然,这只是一个简单的例子。如有必要,您可以使异常更加复杂,并且可以生成所需的任何 http 响应代码。

另一种方法是包装现有的 Exception,可能是一个带有小型包装器类的异常,该类实现使用注释的接口。这告诉 JAX-RS 运行时,如果引发包装的异常,则返回 中定义的响应代码。ObjectNotFoundExceptionExceptionMapper@ProviderExceptionMapper


答案 2
@Provider
public class BadURIExceptionMapper implements ExceptionMapper<NotFoundException> {

public Response toResponse(NotFoundException exception){

    return Response.status(Response.Status.NOT_FOUND).
    entity(new ErrorResponse(exception.getClass().toString(),
                exception.getMessage()) ).
    build();
}
}

创建上面的类。这将处理404(NotFoundException),在toResponse方法中,您可以给出自定义响应。同样,还有 ParamException 等,您需要映射它们以提供自定义响应。


推荐