当前位置: 首页 > 知识库问答 >
问题:

Jersey的自定义异常映射器不适用于无效的JSON输入

符允晨
2023-03-14

我有以下资源,它使用映射到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请求时,一切正常。正如预期的那样,响应是测试。但是,当我将请求更改为{“titlee”:“Test title”}时,服务器会回复如下:

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

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

到目前为止,我所尝试的是实现我自己的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服务器,并将其部署为胖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>

任何建议都非常感谢。

共有3个答案

孟德曜
2023-03-14

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

  • 该服务是无状态 EJB,使用 EJB 拦截器捕获异常并使用详细信息填充请求范围的对象
  • 实现一个后处理接收器,该接收器从请求范围的对象读取并在服务返回之前修改响应。(这是特定于 JAX-RS 的)
单于承
2023-03-14

我也面临过这个问题。如果注册了< code>JacksonFeature,则可以简单地注册< code > JacksonJaxbJsonProvider 作为解决方法。

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

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

最后一个选项可能是正确的解决方案(正如Kysil Ivan的回答中所指出的),您可以编写自己的异常映射器,然后赋予它高优先级,例如<code>1。如果使用自动发现,只需使用@Provider@Priority对其进行注释:

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

如果您手动注册您的提供商,您可以为您的提供商提供绑定优先级:

@ApplicationPath("/")
public class MyResourceConfig extends ResourceConfig {

    public MyResourceConfig() {
        register(JsonParseExceptionMapper.class, 1);
    }
}

有关更多详细信息,请参阅此答案。

龚征
2023-03-14

好吧,这是愚蠢和黑客,但对我有用:

register(JacksonJaxbJsonProvider.class);

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

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

:(

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

 类似资料:
  • 我正在使用泽西2.22.1来实现REST API。 我创建了一个自定义异常映射器,将运行时异常映射到我选择的特定HTTP响应代码。 我的资源类配置为接受POST请求的多个参数。 当我发送不带任何参数的POST请求时: 我希望调用我的自定义异常映射器,但它没有被调用。相反,我得到了一堆非法状态异常。 有人能解释为什么我的自定义异常映射器没有被调用吗? 注意,如果我在资源方法中抛出一个RuntimeE

  • 我正在使用ApacheCXF、Spring和JAX-RS构建一个REST web服务,当输入JSON验证失败时,我需要在其中发送自定义异常。 我没有使用业务逻辑,而是尝试使用CXF、JAX-RS的现成bean验证功能。 Bean验证工作正常,但是,它总是抛出500个异常,这是不太有用的。根据留档,它是org.apache.cxf.jaxrs.validation.ValidationExcepti

  • 首先,我对这个问题太长表示最诚挚的歉意,但老实说,我不知道如何缩短它,因为每个部分都是一个特例。诚然,我可能对此视而不见,因为我已经把头撞到墙上好几天了,我开始绝望了。 我向所有通读这本书的人表示最大的尊重和感谢。 我希望能够通过使用Jersey ExceptionMapers将Shiro的AuthenticationException及其子类映射到JAX-RS响应,Jersey例外映射器是使用G

  • 问题内容: 我想在我的静态服务中捕获json映射异常,以防输入json无效。 它抛出,但我不知道如何或在何处捕获此异常。我想捕获此异常并发送回适当的错误响应。 一切正常,但是如果json主体格式不正确,则会引发异常。我想抓住这个例外。 问题答案: 最终对我有用的是声明的提供者,例如

  • 问题内容: 我有一个使用Jersey构建的REST服务。 我希望能够根据发送到服务器的MIME设置我的自定义异常编写器的MIME。当接收到json和接收到xml 时返回。 现在我进行了硬编码,但这使XML客户端陷入了黑暗。 我可以利用什么上下文来获取当前请求? 谢谢! 根据答案更新 对于对完整解决方案感兴趣的其他人: 连同 其中ErrorResponseConverter是自定义JAXB POJO

  • 我有两个对象,除了date成员外,其他成员都相同。在obj1中,date是java.sql.date,obj2.date是long(纪元)。 我需要编写一个映射器来将obj1映射到obj2。这就是我试图做的: 但是mapperImpl只有自己的日期转换实现: 我得到了: 这种转换的正确方式是什么?