一尘不染

通过GenericEntity在RESTful Response对象中使用Java泛型模板类型>

java

我有一个通用的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一起工作的任何想法吗?


阅读 305

收藏
2020-12-03

共1个答案

一尘不染

编译源代码后,将通过以下行创建(匿名)类:

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

2020-12-03