有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

带有ExceptionMapper的java Jersey/Jackson异常问题

我正在使用Jersey向外部世界提供java REST服务。我提供了一些采用JSON的函数,并使用Jackson框架和jersey将它们转换为POJO

我的问题是,如果向服务器发送了错误的jackson格式,则答案(http响应的内容)是特定于jackson的异常描述。如果我有一个带有属性“姓氏”的POJO,并将json字符串中的“sursname”发送到服务器,我会得到:

Unrecognized field "sursname" (Class XY), not marked as ignorable at [Source: sun.net.httpserver.FixedLengthInputStream@903025; line: 1, column: 49] (through reference chain: XY["sursname"])

这很好,但我希望有我自己的响应内容,例如我自己的错误代码。我已经写了一个自定义异常apper,它应该映射所有可丢弃的内容

@Provider
public class WebserviceExceptionMapper implements ExceptionMapper<Throwable> {

@Override
public Response toResponse(Exception e) {
    e.printStackTrace();
    return Response.status(400).entity("{\"errorcode\":\"CRITICAL_ERROR\"}").type(MediaType.APPLICATION_JSON).build();
    }
}

似乎jackson异常是在调用webservice方法之前抛出的,所以我没有机会映射它

有人有主意吗?非常感谢并为我的英语感到抱歉;)


共 (5) 个答案

  1. # 1 楼答案

    我也遇到了同样的问题,并且解决了覆盖ExceptionMapper的问题。完美的我还需要做的一件事是,如何覆盖我的应用程序的JacksonProvider(我不知道它是否与我使用的Jersey版本-2.19有关),但我没有100%理解。这是我的网站。覆盖它的xml部分:

    <init-param>
    <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>
            com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider
        </param-value>
    

  2. # 2 楼答案

    当然,之前会抛出Jackson异常:调用Jackson提供程序是为了在方法中创建您期望的对象。然而,使用ExceptionMapper,您不仅应该能够映射您的异常,还应该能够映射提供者异常

    您确定您的提供商已注册吗?如果从方法而不是从提供程序抛出异常,是否会调用它

    如果上一个问题的答案是“是”,那么尝试为具体的异常实现ExceptionMapper,而不是Throwable

  3. # 3 楼答案

    不久前,我在使用Jackson和Apache CXF时遇到了类似的问题。如果异常没有发生在我的JAX-RS方法中,而是发生在JacksonJsonProvider中,则不会调用异常映射程序。在我的例子中,解决方案是扩展JacksonJsonProvider,捕获特定的Jackson json异常,并将它们重新命名为^{}

    下面是我的扩展JacksonJsonProvider的重写readFrom方法:

        @Override
        public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
                MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
            try {
                return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream);
            } catch (JsonParseException jpe) {
                throw new WebApplicationException(jpe, Response.status(Status.BAD_REQUEST)
                        .entity(new ErrorEntity("Malformed json passed to server: \n" + jpe.getMessage())).build());
            } catch (JsonMappingException jme) {
                throw new WebApplicationException(jme, Response
                        .status(Status.BAD_REQUEST)
                        .entity(new ErrorEntity("Malformed json passed to server, incorrect data type used: \n"
                                + jme.getMessage())).build());
            }
        }
    
  4. # 4 楼答案

    自定义ExceptionMapper无法捕获异常的原因是Jackson库提供了自己的异常映射器,该映射器会在常规异常映射器捕获异常之前捕获异常

    有人建议您应该为JsonParseExceptionMapper和JacksonMappingExceptionMapper实现自己的异常映射程序,但这会产生不一致的结果See this issue on their GitHub

    要解决此问题,必须确保没有注册任何内置异常映射程序。如果您正在使用JSON的jackson jaxrs providers库:jackson jaxrs JSON provider,请确保您只注册了jackson jaxrs JSON provider。类或JacksonJsonProvider。类在应用程序类中:

    public class MyApplication extends ResourceConfig {
        public MyApplication() {
            register(JacksonJaxbJsonProvider.class)
        }
    }
    

    注意杰克森功能。类,因为它注册内置的异常标记。另外,请远离jersey media json jackson库,它会自动添加一些内置的异常映射程序,而无需执行任何操作

  5. # 5 楼答案

    感谢您的帮助,JsonParseException的ExceptionMapper没有帮助。我从我的项目中删除了杰克逊jar文件,并包含了杰克逊的来源。然后我修改了ord。科德豪斯。杰克逊。贾克斯。JsonParseExceptionMapper和JacksonMappingExceptionMapper返回我的自定义响应内容。我对它不满意,但它现在起作用了

    谢谢你的帮助