我有一个通用的JAX-RS资源类,我已经定义了一个通用的findAll
方法
public abstract class GenericDataResource<T extends GenericModel> {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response findAll() {
Query query = em.createNamedQuery(modelClass.getSimpleName()+".findAll");
List<T> list = query.getResultList();
return Response.ok(new GenericEntity<List<T>>(list) {}).build();
}
}
和用户类:
public class User extends GenericModel {
...
}
以下是示例子类定义:
@Path("users")
public class UserResource extends GenericDataResource<User> {
public UserResource() {
super(User.class);
}
}
我得到以下异常:
com.sun.jersey.api.MessageException: A message body writer for Java class
java.util.Vector, and Java type java.util.List<T>,
and MIME media type application/json was not found exception.
如果我用定义的类替换T,例如像User
那样:
GenericEntity<List<User>>(list)
然后它运作正常。
有关如何使其与通用T一起使用的任何想法吗?
答案 0 :(得分:11)
编译源代码后,由行创建的(匿名)类:
new GenericEntity<List<T>>(list) {}
使用类型变量来引用其父变量。由于类型变量在运行时没有值,因此不能使用这样的泛型。您被迫从调用站点传递所谓的类型令牌。这是一个需要从findAll()
调用者传递令牌的示例,但您可以在构造函数中需要一个令牌并将其保存在实例变量中:
public abstract class GenericDataResource<T extends GenericModel> {
public Response findAll(GenericEntity<List<T>> token) {
Query query = em.createNamedQuery(modelClass.getSimpleName() + ".findAll");
List<T> list = query.getResultList();
return Response.ok(token).build();
}
}
来电者会发送一个像
这样的标记new GenericEntity<List<User>>() {}
如果您只使用非参数化子类,findAll()
可能会利用反射来构建令牌(未经测试,希望您明白这一点):
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response findAll() {
Query query = em.createNamedQuery(modelClass.getSimpleName()+".findAll");
List<T> list = query.getResultList();
return Response.ok(new GenericEntity(list, getType())).build();
}
您必须实现getType()
才能返回所需的类型。它将是ParameterizedType
的子类,能够表示类型List<DAO<User>>
答案 1 :(得分:9)
除了答案之外,还要在客户端上阅读Response对象:
List<MyObject> list = response.readEntity(new GenericType<List<MyObject>>(){}));
答案 2 :(得分:2)
响应对象返回给客户端以响应发送到服务器的请求。 Response类具有Response.ResponseBuilder内部类,该内部类将每个属性集收集到其Response.ResponseBuilder类型的字段中。 Response.ResponseBuilder应用Builder设计模式来构造响应对象。
build()方法负责连接在构建过程中形成的Response.ResponseBuilder对象链。 E.g。
Response.status(200);
状态方法在分配STATUS后返回Response.ResponseBuilder
Response.status(200).entity( AnyObj );
实体对象分配类型的实体(返回的有效负载) Response.ResponseBuilder并被分配给Response的实例变量。之后,status还会分配状态并返回Response.ResponseBuilder实例。构建器在build()方法调用时连接它们。
Response.status(200).entity( obj ).build();
最后,构建方法构造完成(包含属性)Response。
现在出现了 GenericEntity 对象的问题。它表示泛型类型T的响应实体。
For Instance,
GenericEntity&GT; obj = new GenericEntity&gt;(lst){}; Response.status(200).entity(obj).build();
obj 是上面给出的List类型。实体方法接受通用的对象类型。如果需要特定类型,你必须将它作为GenericEntity类型的参数传递,在运行时它将被转换为特定类型的对象。
实际使用
希望我的Jersey Framework能够将我的Java模型中的List对象的JSON作为Response对象的一部分回复给客户端。
因此, 新的GenericEntity&gt; ---将对象/有效负载转换为List类型 新的GenericEntity ---运行时类型变为String
Webservice Side上的资源
public Response findAllFruits(@QueryParam("frtID") String frtID ) {
List<String> lst = new ArrayList<String>();
lst.add("Banana");
lst.add("Apple");
GenericEntity<List<String>> obj = new GenericEntity<List<String>>(lst) {};
return Response.status(200).entity( obj ).build();
}
<强>输出强> 响应发送回客户端。 [ “香蕉”, “苹果” ]
如何阅读响应实体
List<CustomType> myObj= response.readEntity(new GenericType<List<CustomType>>() {});
答案 3 :(得分:1)
为了解决这个问题,我做了一个返回GenericEntity
然后从我的泛型类中调用它的方法,如下所示:
@XmlRootElement
public abstract class AbstractRest<T extends IEntity> {
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
public abstract class SmartWebServiceNEW<R extends AbstractRest<T>> {
@GET
@Produces({MediaType.APPLICATION_XML})
public Response findAll() {
List<T> lista = getDelegate().findAll();
if (lista == null || lista.isEmpty()) {
return Response.status(Response.Status.NO_CONTENT).build();
}
List<R> retorno = new ArrayList<R>();
for (T it : lista) {
retorno.add(toRest(it));
}
GenericEntity entity = listToGenericEntity(retorno);
return Response.ok(entity).build();
}
protected abstract GenericEntity listToGenericEntity(List<R> restList);
}
@Path("/something")
@RequestScoped
public class MyEntityResource extends SmartWebServiceNEW<MyEntityExtendingAbstractRest> {
@Override
protected GenericEntity listToGenericEntity(List<MyEntityExtendingAbstractRest> restList) {
return new GenericEntity<List<MyEntityExtendingAbstractRest>>(restList) {
};
}
}