不同的Jersey 2响应取决于媒体类型(JSON / XML)

时间:2016-07-27 13:30:09

标签: rest jersey filtering marshalling moxy

在RESTful Glassfish 4应用程序(JERSEY 2.22.2,MOXY as JSON Provider)中,我们有一个能够生成JSON和XML输出的资源方法。

方法响应通过MessageBodyWriter传递,但它仅用于在某些情况下构建对象图。在这些情况下,独立于客户端请求的媒体类型,图表将正确应用。

另一方面,当MessageBodyWirter的isWriteable()方法返回false,因此传递给MessageBodyFactory的writers列表中的下一个writer时,JSON媒体类型请求和XML媒体类型请求(即请求标头中分别为Accept: application/jsonAccept: application/xml)。

在第一种情况下,FilteringMoxyJsonProvider被选为响应writer,因为EntityFilteringFeature已注册。响应是根据实体过滤注释编写的。

虽然当客户端要求XML响应时,会选择另一个MessageBodyWriter(org.glassfish.jersey.jaxb.in​​ternal.XmlRootElementJaxbProvider)。 这是由于MessageBodyFactory中WriterModel的排序,其中FilteringMoxyJsonProvider位于XmlRootElementJaxbProvider之后。

在这种情况下,编写XML响应时不会应用任何过滤器。

我们试图寻找一种方法来改变编写器的顺序,也试图访问EntityFieldProcessor类,但没有运气。

是否可以让两种方案(即JSON和XML响应请求)以相同的方式工作?是否可以在MessageBodyFactory中排除某些作者注册或更改其顺序?

任何帮助将不胜感激。

    //Configuration 
    public class ApplicationConfigVersione1 extends ResourceConfig { 
    ....

    register(EntityFilteringFeature.class); 
    register(MyCustomWriter.class);


    ------------------------

    @Produces({"application/json", "application/xml"})
    public class MyCustomWriter implements MessageBodyWriter<MyCustomObject> {
    ....


    @Override
    public boolean isWriteable(Class<?> type, Type genericType,
                Annotation[] annotations, MediaType mediaType) {
        if (mustUseCustomWriter()) {
                return true;
            } else {
          return false;
        //In this case, with request header accept=application/xml, the xml response is not filtered.
        }
    }



    @Override
    public void writeTo(MyCustomObject customObject, Class<?> type, Type genericType, Annotation[] annotations, 
    MediaType mediaType,
        MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
            throws IOException, WebApplicationException {

            objectGraph = buildObjectGraph();

            marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, objectGraph);
            marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, mediaType.toString());

            //**** objectGraph applies to XML and JSON media types
            marshaller.marshall(object, entityStream);

1 个答案:

答案 0 :(得分:1)

我还尝试使用Jersey的实体过滤机制,其资源产生application/jsonapplication/xml响应,并根据repsonse类型查看不同的结果信息。

我怀疑moxy组件的这个关闭/不会修复的github问题是我们通过过滤看到的行为的原因:https://github.com/jersey/jersey/issues/3036