【问题标题】:Jersey: Returning 400 error instead of 500 when given invalid request body泽西岛:给定无效请求正文时返回 400 错误而不是 500
【发布时间】:2012-03-23 18:31:12
【问题描述】:

我正在使用 Jersey 的集成 Jackson 处理将传入的 JSON 转换为 POJO,例如:

@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response newCustomer( CustomerRepresentation customer)
{
...
}

如果客户端发送带有无效字段的 JSON,Jersey 当前返回 500 Internal Server Error。相反,我想返回一个400 Bad Request,最好带有一些有意义的详细信息来指示哪些字段有误。

对如何实现这一点有任何见解吗? (至少返回一个通用的 400 而不是完全不合适的 500?)

更新: 这是在调用我的处理程序之前在服务器端生成的异常:

javax.servlet.ServletException: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: 
Unrecognized field "this_isnt_a_known"_field" (Class com.redacted....), not marked as ignorable

【问题讨论】:

  • 400实际上是Bad request,即服务器认为客户端发送了错误的请求。所以在语义上它不符合你想要实现的目标。
  • 感谢您接住我的失误。我打算输入“错误请求”。相应地编辑了问题。
  • 如果请求正文无效,Jersey 通常会返回 400。你确定它不会在你的方法体中使用 NPE 或其他东西失败吗?您是否在应用服务器日志中看到任何错误和/或堆栈跟踪?
  • 谢谢!很高兴知道 Jersey supposed 返回 400。我正在更新问题以包含服务器端异常。它肯定是在到达我的处理程序之前生成的,并且与 JSON 中无法识别的字段相关。
  • @HolySamosa:您可以做的是在调试模式下运行您的 Web 容器,在引发UnrecognizedPropertyException 时放置断点,然后查看处理它时会发生什么。也许你会在泽西岛发现一个错误。

标签: jersey jax-rs


【解决方案1】:

我终于能够通过实现 ExceptionMapper 来捕获 Jackson 抛出的 UnrecognizedPropertyException 并将其映射到 400 Bad Request 响应来解决此问题:

@Provider
public class UnrecognizedPropertyExceptionMapper implements ExceptionMapper<UnrecognizedPropertyException>
{

    @Override
    public Response toResponse(UnrecognizedPropertyException exception)
    {
        return Response
                .status(Response.Status.BAD_REQUEST)
                .entity( "'" + exception.getUnrecognizedPropertyName() + "' is an unrecognized field.")
                .type( MediaType.TEXT_PLAIN)
                .build();
    }

}

【讨论】:

  • @HolySamosa 感谢分享。但不知何故 toResponse() 没有被调用。
  • 嘿 HolySamosa...你能告诉我们你的 toResponse() 是如何被调用的吗?我被这个问题困住了,没有任何解决方案可以抛出 400 而不是 500 错误。
  • +1 因为您的解决方案为我提供了故障排除提示。我收到 HTTP 400 Bad request 错误,“multipart/form-data”中的数据类型无效。捕获一般异常帮助我找到问题 -> 公共类 ExceptionInterceptor 实现 ExceptionMapper
【解决方案2】:

我尝试使用 HolySamosa 的回答将 status 500 映射到 status 400,但此映射器没有捕获到异常,并且 status 500 仍然存在被退回。

调试后发现抛出的是JsonParseException,而不是UnrecognizedPropertyException。这是因为我发送了一些垃圾文本(根本不是 JSON)。

当我从客户端发送一个正确的 JSON,其格式不适合我在服务器端的 DTO,然后我得到 UnrecognizedPropertyException。 所以有两种情况:

  • 当您发送的垃圾不是 JSON 和
  • 当您发送 JSON,但它与您的 DTO 类不匹配时。

现在我为两者返回 status 400

【讨论】:

    【解决方案3】:

    在 dropwizard 领域,有一个名为 JsonProcessingExceptionMapperExceptionMapper 与您正在寻找的功能相似。也许您可以从中获得灵感,了解如何在非 dropwizard 世界中解决您的特定问题。

    【讨论】:

      【解决方案4】:

      我也遇到过同样的问题...不幸的是,据我所知,没有什么好的方法可以拦截 Jackson 异常并生成您自己的错误代码。

      您可以选择使用@JsonIgnoreProperties,然后严格验证反序列化的对象。这不会告诉您您的发件人是否发送了垃圾邮件,但如果他们错过了必填字段,您会发现的。

      我找不到任何方法来访问传入的实际 JSON,除了创建一个 @Provider 类来捕获 JSON、验证它,然后将其传递给 Jackson 进行反序列化。

      【讨论】:

      • Jersey 可以将 JSON 作为 JsonNode 传递给您的处理程序,这将允许我们验证格式正确的 JSON,但 Jersey 仍会为非 JSON 请求返回 500(或者我假设 - 我没有还没试过)。
      • 我终于回到了这个问题上,并且能够使用 ExceptionMapper 解决它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-05
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-08
      • 1970-01-01
      相关资源
      最近更新 更多