当前位置:  开发笔记 > 编程语言 > 正文

JAX-RS/Jersey如何自定义错误处理?

如何解决《JAX-RS/Jersey如何自定义错误处理?》经验,为你挑选了6个好方法。

我正在使用Jersey学习JAX-RS(又名JSR-311).我已经成功创建了一个Root资源并正在使用参数:

@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
    }
}

这很好用,并处理当前语言环境中的任何格式,日期(字符串)构造函数(如YYYY/mm/dd和mm/dd/YYYY)可以理解这种格式.但是,如果我提供的值无效或无法理解,我会得到404响应.

例如:

GET /hello?name=Mark&birthDate=X

404 Not Found

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



1> Steven Levin..:

有几种方法可以使用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());
     }
}

要抛出这个新创建的Exception,你只需:

@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.

当然,这只是一个简单的例子.如果需要,您可以使Exception变得更加复杂,并且您可以生成所需的http响应代码.

另一种方法是包装一个现有的Exception,也许是一个带有一个小包装类的ObjectNotFoundException,它实现了用@Provider注释注释的ExceptionMapper接口.这告诉JAX-RS运行时,如果引发了包装的Exception,则返回ExceptionMapper中定义的响应代码.


在问题中提到的场景中,您将没有机会抛出异常,因为Jersey将无法从输入值创建Date对象的实例,因此会引发异常.有没有办法拦截泽西的例外?有一个ExceptionMapper接口,但是它也拦截了方法抛出的异常(在这种情况下得到).
如果404是有效的情况而不是错误,那么如何避免出现在服务器日志中的异常(即每次查询资源时,只是为了查看它是否已经存在,使用您的方法在服务器中出现堆栈跟踪日志).
在您的示例中,对super()的调用应该略有不同:super(Response.status(Status.UNAUTHORIZED).entity(message).type("text/plain").build()); 谢谢你的见解.
值得一提的是Jersey 2.x定义了一些最常见的HTTP错误代码的异常.因此,您可以使用BadRequestException和NotAuthorizedException之类的内置类,而不是定义自己的WebApplication子类.例如,查看javax.ws.rs.ClientErrorException的子类.另请注意,您可以向构造函数提供详细信息字符串.例如:抛出新的BadRequestException("开始日期必须在结束日期之前");

2> Arnav..:
@Provider
public class BadURIExceptionMapper implements ExceptionMapper {

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等以提供自定义响应.



3> Jan Kronquis..:

当Jersey无法解组参数时抛出com.sun.jersey.api.ParamException,因此一个解决方案是创建一个处理这些类型的异常的ExceptionMapper:

@Provider
public class ParamExceptionMapper implements ExceptionMapper {
    @Override
    public Response toResponse(ParamException exception) {
        return Response.status(Status.BAD_REQUEST).entity(exception.getParameterName() + " incorrect type").build();
    }
}



4> Charlie Broo..:

您还可以为QueryParam注释变量编写可重用的类

public class DateParam {
  private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

  private Calendar date;

  public DateParam(String in) throws WebApplicationException {
    try {
      date = Calendar.getInstance();
      date.setTime(format.parse(in));
    }
    catch (ParseException exception) {
      throw new WebApplicationException(400);
    }
  }
  public Calendar getDate() {
    return date;
  }
  public String format() {
    return format.format(value.getTime());
  }
}

然后像这样使用它:

private @QueryParam("from") DateParam startDateParam;
private @QueryParam("to") DateParam endDateParam;
// ...
startDateParam.getDate();

虽然在这种情况下错误处理是微不足道的(抛出400响应),但使用此类允许您将参数处理分解为一般性,这可能包括日志记录等.



5> StaxMan..:

一个明显的解决方案:接受一个String,自己转换为Date.这样您就可以定义所需的格式,捕获异常并重新抛出或自定义发送的错误.对于解析,SimpleDateFormat应该可以正常工作.

我确信有一些方法可以为数据类型挂钩处理程序,但在这种情况下,您可能只需要一些简单的代码.



6> dshaw..:

我也喜欢StaxMan可能会将QueryParam实现为String,然后根据需要处理转换,重新抛出.

如果特定于语言环境的行为是期望和预期的行为,您将使用以下命令返回400 BAD REQUEST错误:

throw new WebApplicationException(Response.Status.BAD_REQUEST);

有关更多选项,请参阅JavaDoc for javax.ws.rs.core.Response.Status.

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有