【问题标题】:Custom ExceptionMapper for Jersey not working for invalid JSON inputJersey 的自定义 ExceptionMapper 不适用于无效的 JSON 输入
【发布时间】:2017-03-21 04:09:49
【问题描述】:

我有以下资源消耗被映射到 POJO 的 JSON。

@Path("example")
public class ExampleResource {

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response addThesis(MyObject myObject) {
        return Response.ok().entity("Test").build();
    }
}

这是 POJO 类:

public class MyObject {
    private String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

当我发送一个带有 {"title":"Test title"} 正文的 POST 请求时,一切正常。正如预期的那样,响应是Test。但是,当我将请求更改为 {"titlee":"Test title"} 时,服务器会回复:

无法识别的字段“titlee”(com.my.package.MyObject 类),未标记为可忽略(一个已知属性:“title”]) 在 [来源:org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@6dc6a46a; line: 2, column: 11](通过引用链:com.my.package.MyObject["titlee"])

显然这是 Jersey 抛出并返回的异常。如何拦截此异常并返回自定义状态码和消息?

到目前为止,我尝试的是实现我自己的 ExceptionMapper:

@Provider
public class MyJsonExceptionMapper implements ExceptionMapper<JsonProcessingException> {
    public Response toResponse(JsonProcessingException e) {
        return Response.status(400).entity("JSON Processing Error").build();
    }
}

不幸的是,响应保持不变。当我为自定义异常实现 ExceptionMapper 并在资源方法中抛出相应的异常时,一切正常。我认为这与覆盖我自己的 JsonProcessingException 的默认 ExceptionMapper 有关。然后我尝试创建一个通用映射器(“implements ExceptionMapper”),但还是没有成功。

我到处寻找并尝试了很多方法,包括扩展 ResourceConfig 和注册我的映射器,但到目前为止没有任何效果。

更多信息可能有助于缩小问题范围:我使用 Grizzly2 作为 HTTP 服务器,我将其部署为 Fat JAR。

我的 pom.xml 的依赖部分如下所示:

<dependencies>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.24</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-grizzly2-http</artifactId>
        <version>2.24</version>
    </dependency>
</dependencies>

非常感谢任何建议。

【问题讨论】:

  • 据我记得我认为为 JsonMappingException 和 JsonParseException 实现映射器,应该覆盖默认的映射器。我不太确定如何禁用它们。
  • Throwable 实现映射器应该覆盖/all/ 现有的映射器。但这似乎不起作用。也不会在 ResourceConfig 中明确重新注册 ExceptionMapper&lt;JsonMappingException&gt;
  • (同时按照文档建议实现ExtendedExceptionMapper 也不起作用...)

标签: json jersey jackson jax-rs


【解决方案1】:

好的,这很愚蠢,但对我有用:

register(JacksonJaxbJsonProvider.class);

这是由于 Jackson 功能入口点中的以下“良好的默认行为”:

if (!config.isRegistered(JacksonJaxbJsonProvider.class)) { // add the default Jackson exception mappers context.register(JsonParseExceptionMapper.class); context.register(JsonMappingExceptionMapper.class);

:(

但是,我仍然更喜欢“真正”解决问题的答案 - 即。没有预先注册组件,因此功能无法正确配置它们...

【讨论】:

  • (以便扩展映射器可以拒绝异常以将其发送到默认映射器...)
【解决方案2】:

我们在 Wildfly 上使用 JAX-RS 来实现我们的 Web 服务,并使用以下内容来完成您在 Glassfish 上使用 Jersey 所做的事情。也许它具有您可以查找的类似功能。我们的步骤是:

  • 服务是无状态的EJB,使用EJB拦截器来捕获异常 并使用详细信息填充请求范围的对象
  • 实现一个 PostProcessInterceptor,它从请求范围的对象中读取并在服务返回之前修改响应。 (这是 JAX-RS 特有的)

【讨论】:

    【解决方案3】:

    我也遇到过这个问题。如果注册了JacksonFeature,您可以简单地注册JacksonJaxbJsonProvider 作为解决方法。


    JacksonFeature 在类路径中时,Jersey 会自动发现它。另一种解决方法是通过将ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE 设置为true 来禁用自动发现。因此,您需要手动注册其他功能。


    或者,您可以摆脱 jersey-media-json-jackson 工件并改用 jackson-jaxrs-json-provider。这样,您将摆脱JacksonFeature,然后您可以注册自己的异常映射器。


    最后一个选项,可能看起来是 正确 解决方案(正如 Kysil Ivan 的 answer 所指出的那样),您可以编写自己的异常映射器,然后给它一个高优先级,例如 @ 987654341@。如果您使用自动发现,只需使用 @Provider@Priority 注释即可:

    @Provider
    @Priority(1)
    public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> {
        ...
    }
    

    如果你手动注册你的提供者,你可以give your provider a binding priority:

    @ApplicationPath("/")
    public class MyResourceConfig extends ResourceConfig {
    
        public MyResourceConfig() {
            register(JsonParseExceptionMapper.class, 1);
        }
    }
    

    查看answer了解更多详情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-29
      • 2012-03-12
      • 2014-02-05
      相关资源
      最近更新 更多