在使用JAX-RS规范的Rest服务中,我可以定义一个通用服务
@GET
@Path("something")
@Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public List<MyPojo> getMyPojoList() {
...
}
在 Jersey 发生了一些神奇的事情,因为在调用时
javax.ws.rs.ext.MessageBodyWriter#writeTo(T t,
Class<?> type,
Type genericType,
Annotation annotations[],
MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException, WebApplicationException;
在分析 genericType
时,很容易看出他的 Value 是 class MyPojo
.
我一直在尝试阅读泽西源代码,以了解他们如何在调用 javax.ws.rs.ext.MessageBodyWriter
的 javax.ws.rs.ext.MessageBodyWriter
之前提取Collection Generic类型,但是一旦到达读取 GenericEntity
类,我就迷路了 .
任何人都可以帮助我了解他们在那里使用哪种魔法?提前致谢!!!
2 回答
一些通用信息通过编译器保留到运行时 . 看一下有关Java反射的文档 . 在这种情况下,它们可能使用getGenericReturnType,尽管有许多方法与参数类型甚至类的通用参数有关 .
这里最明显的缺点是只能保留编译时的信息 - 特别是你无法可靠地检查List以确定它是
List<Integer>
还是List<String>
.您需要使用JAX-RS框架的神奇类来保留您正在寻找的信息 . 我花了很长时间才真正开始研究我的项目,但这就是我解决问题的方法:
首先,在Resource类中,传递泛型集合(注意我使用Response Objects):
然后,您可以创建一个正常的MessageBodyWriter实现,并在方法中执行类型检查,该方法负责检查您的实现是否合适 .
您可以增强
isWriteable
方法以执行更多检查,例如仔细检查MediaType
是否正确,以及是否需要存在某些注释等,具体取决于您的要求 .但要总结一下:
将您的集合包装在
GenericEntity<>
包装器中以保留通用类型信息在MessageBodyWriter中执行适当的强制转换以确定类型 .