Jersey如何从Collections中提取泛型类型以调用javax.ws.rs.ext.MessageBodyWriter#writeTo()?

时间:2010-06-23 08:33:44

标签: java generics reflection jersey

在使用JAX-RS规范的Rest服务中,我可以定义像

这样的通用服务
@GET
@Path("something")
@Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public List<MyPojo> getMyPojoList() {
    ...
}

泽西岛发生了一些奇迹,因为在调用

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时,很容易看出他的值为class MyPojo

我一直在尝试阅读Jersey源代码,以了解他们在调用writeTo的方法javax.ws.rs.ext.MessageBodyWriter之前如何提取Collection Generic类型,但是一旦到达就读了{ {1}}上课。

任何人都可以帮助我了解他们在那里使用哪种魔法?在此先感谢!!!

2 个答案:

答案 0 :(得分:1)

通过编译器将一些通用信息保留到运行时中。看一下有关Java反射的文档。在这种情况下,它们可能使用getGenericReturnType,尽管有许多方法与参数类型甚至类的泛型参数有关。

这里最明显的缺点是只能保留编译时的信息 - 特别是你无法可靠地检查列表以确定它是List<Integer>还是List<String>

答案 1 :(得分:0)

您需要使用JAX-RS框架的神奇类来保留您正在寻找的信息。我花了相当长的时间才能在我的项目上实际完成此工作,但这是我解决问题的方法:

首先,在您的Resource类中,这样传递通用集合(请注意,我使用Response Objects):

public Response findAll() {
  Collection<MyType> entities = service.findAll(); // whatever code you need to load it.
  GenericEntity<Collection<MyType>> list = new GenericEntity<Collection<MyType>>(entities) {}; // This line is key!
  return Response.ok.entity(list).build();
}

然后,您可以创建一个普通的 MessageBodyWriter 实现,并在负责检查您的实现是否合适的方法中执行类型检查。

public class MyTypeMessageBodyWriter implements MessageBodyWriter<MyType> {
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        if (Collection.class.isAssignableFrom(type) && genericType instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) genericType;
            Type[] actualTypeArgs = parameterizedType.getActualTypeArguments();
            return (actualTypeArgs.length == 1 && actualTypeArgs[0].equals(MyType.class));
        } else {
            return false;
        }
    }
}

您可以增强isWriteable方法来执行更多检查,例如再次检查MediaType是否正确,以及是否需要根据需要添加一些注释等。< / p>

但要总结一下:

  • GenericEntity<>包装器包装您的收藏夹,以保存保存器通用类型信息
  • 在MessageBodyWriter中执行适当的强制转换以确定类型。