2011-08-12 23 views
16

我想在泽西岛编写一个通用函数,它可以用来通过REST获取相同类型的对象列表。我基于它在这个论坛上找到的信息:link获取REST资源列表<T>与泽西

@Override 
public <T> List<T> fetchResourceAsList(String url) { 
    ClientConfig cc = new DefaultClientConfig(); 
    Client c = Client.create(cc); 
    if (userName!=null && password!=null) { 
    c.addFilter(new HTTPBasicAuthFilter(userName, password)); 
    } 
    WebResource resource = c.resource(url); 
    return resource.get(new GenericType<List<T>>() {}); 
} 

但是,这是行不通的。如果我尝试执行它,我收到以下错误:SEVERE: A message body reader for Java class java.util.List, and Java type java.util.List<T>, and MIME media type application/xml was not found

但是,如果我写这个功能没有模板(用实际的类名称替换T)它只是正常工作。当然,这种方式失去了它的意义。

有没有办法解决这个问题?

+0

见下面链接 http://stackoverflow.com/questions/1603404/using-jaxb-to-unmarshal-marshal-a-liststring – fmucar

+0

@fmucar:这又具有对服务器的提示我懂了。我需要客户端的通用类型支持。 – NagyI

回答

21

我已经找到解决方案 https://java.net/projects/jersey/lists/users/archive/2011-08/message/37

public <T> List<T> getAll(final Class<T> clazz) { 

    ParameterizedType parameterizedGenericType = new ParameterizedType() { 
     public Type[] getActualTypeArguments() { 
      return new Type[] { clazz }; 
     } 

     public Type getRawType() { 
      return List.class; 
     } 

     public Type getOwnerType() { 
      return List.class; 
     } 
    }; 

    GenericType<List<T>> genericType = new GenericType<List<T>>(
      parameterizedGenericType) { 
    }; 

    return service.path(Path.ROOT).path(clazz.getSimpleName()) 
      .accept(MediaType.APPLICATION_XML).get(genericType); 
} 
+0

这工作形式与泽西2.9,我非常感谢你! –

+0

顺便说一句,扩展你的例子,并使用基类的Collection.class OwnerType和RawType,这也工作。所以我应该能够为所有集合类型重用单个parameterizedType。 –

6

见GenericType类的球衣可以帮助您以及

的Unmarshaller需要知道什么类型的对象存在,才可以unmarhall返回的内容。由于泛型信息在运行时不可用,所以你所要求的是不可能的。它不能忽略一些它不知道的事情。

最好你可以做的是;

public <T> List<T> fetchResourceAsList(Class<?> beanClass, String url) { 
    ... 

    if(beanCLass.equals(MyBean.class)){ 
     return resource.get(new GenericType<List<MyBean>>() 
    }else if(...){ 
     ... 
    }... 
} 

或使用泛型警告(我不知道这是否会工作)

public List fetchResourceAsList(String url) { 
    ... 
     return resource.get(new GenericType<List<Serializable>>() 
} 
+0

您已经提供了服务器端的示例。这怎么能帮助我在客户端?我可以在浏览器中查看Jersey服务器生成的列表。我的问题是,如果我在上面的函数中使用泛型类型,客户端无法获取资源。我可以获取资源,如果我手动构建客户端每次在某个特定类型的位置。但是我不想要这个。 – NagyI

+0

好吧,我得到了。这是在这里描述相同的问题:http://janmaterne.wordpress.com/2008/10/10/getting-the-type-of-a-generic-class-at-runtime/ – NagyI

+0

请问为什么泛型信息isn运行时可用吗? – gosua

3

上user2323189扩展,您可以使用收藏而不是List.class,这样你就可以序列化所有扩展Collection的类型。我在我的基类客户端类中创建了一个简单的getter,并且可以简单地使用它来检索任何类型的Collection。不是在我的构造函数中提供了clazz变量,所以它不是提供的参数。你可以把它变成一个静态方法,并使用带有Class参数的签名GenericType>使其更通用。

public GenericType<Collection<T>> getParameterizedCollectionType() { 
     ParameterizedType parameterizedGenericType = new ParameterizedType() { 
      public Type[] getActualTypeArguments() { 
       return new Type[] { clazz }; 
      } 

      public Type getRawType() { 
       return Collection.class; 
      } 

      public Type getOwnerType() { 
       return Collection.class; 
      } 
     }; 
     return new GenericType<Collection<T>>(parameterizedGenericType){}; 
    }