修改ContainerResponseFilter中的响应

时间:2017-10-02 05:55:05

标签: java jersey jetty jax-rs lombok

我希望有一个JAX-RS资源响应的通用结构。例如,假设您有一个PersonsResource和一个像这样的GET方法:

@GET @Path("/{id}")
public Person get(@PathParam("id") String id) {
    return new Person(id); //
}

假设客户端的响应是这样的json:{"id":"some-id"}

现在,我想要实现的是拥有一个ContainerResponseFilter。它将修改响应,以便它将原始实体包装成如下结构:

{  
   "meta":{  
      "href":"http://this.is.request/url"
   },
   "paging":{  
      "offset":0,
      "limit":10
   },
   "entity":{  
      "id":"some-id"
   }
}

我用下面的代码(我使用Lombok来减少样板代码)来实验我的想法:

@Data @NoArgsConstructor @AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD) @XmlType
public class Person {
    private String id;
}

@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement
@Data @NoArgsConstructor @AllArgsConstructor
public class WrappedResponse {
    private Object entity;
}

@Provider @Slf4j
public class WrappedResponseFilter implements ContainerResponseFilter {
    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        responseContext.setEntity(new WrappedResponse(responseContext.getEntity()));
    }
}

但是,当我使用curl调用端点时,我得到的是这样的: {"entity":"Person(id=xyz)"}。显然,相应的MessageBodyWriter只对WrappedResponse中的toString()字段使用了entity方法。那么,我如何将实体也序列化为json,如其JAXB注释所定义的那样?也就是说,对于上面的例子,我如何做出像{"entity":{"id":"xyz"}}

这样的回复

BTW,我使用了以下依赖项:

'javax.servlet:javax.servlet-api:3.1.0'
'org.slf4j:slf4j-api:1.7.25'
'org.projectlombok:lombok:1.16.18'
'javax.ws.rs:javax.ws.rs-api:2.1'
'javax.xml.bind:jaxb-api:2.3.0'
'org.eclipse.persistence:org.eclipse.persistence.moxy:2.7.0'
'org.glassfish.jersey.containers:jersey-container-servlet:2.26'
'org.glassfish.jersey.ext:jersey-spring4:2.26'
'org.glassfish.jersey.core:jersey-server:2.26'
'org.glassfish.jersey.media:jersey-media-moxy:2.26'

我将实验代码作为网络应用程序部署到Mac上的Jetty中。

1 个答案:

答案 0 :(得分:1)

如果您为杰克逊切换MOXy

,它应该可以工作
  

' org.glassfish.jersey.media:Jersey的媒体MOXY:2.26'

     

' org.glassfish.jersey.media:Jersey的媒体JSON-杰克逊:2.26'

原因是MOXy(使用JAXB)需要类型信息。不确定如何发现类型信息的确切启发式方法,但根据我的经验,如果找不到类型信息,则只会默认调用{{1}}。

另一方面,对于Jackson,它不需要类型信息,因为它默认只是内省bean properties来发现应该序列化的内容。