java - 修改 ContainerResponseFilter 中的响应

标签 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 中的 entity 字段使用了 toString() 方法。那么,如何使实体也按照其 JAXB 注释的定义序列化为 json?也就是说,对于上面的示例,我怎样才能做出像 {"entity":{"id":"xyz"}} 这样的响应?

顺便说一句,我使用了以下依赖项:

'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'

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

最佳答案

如果你把 MOXy 换成 Jackson,它应该可以工作

'org.glassfish.jersey.media:jersey-media-moxy:2.26'

'org.glassfish.jersey.media:jersey-media-json-jackson:2.26'

原因是 MOXy(使用 JAXB)需要类型信息。不确定如何发现类型信息的确切启发式,但根据我的经验,当找不到类型信息时,它只会默认调用 toString()

另一方面,对于 Jackson,它不需要类型信息,因为默认情况下它只会内省(introspection) bean properties发现应该序列化的内容。

关于java - 修改 ContainerResponseFilter 中的响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46520169/

相关文章:

java - 如何获取引发自定义异常的类的名称

java - 正则表达式模式来抓取部分的变化部分

java - Jersey REST 服务的响应不包含空字段

Java Servlet、JAX-RS - 在基于表单的身份验证工作时遇到问题

java - SSL 连接类型

java - 如何禁用左右箭头键在 SWT 列表中导航?

java - 如何解决 Facelets 和 Spring Web Flow 中的刷新问题?

security - 是否可以将 Solr 与 SSL 和 CA 签名证书一起使用

java - RESTful 1-N 可选关系

java - Jersey 资源类未导出