通过GenericEntity <List <T >>在RESTful Response对象中使用Java-generics模板类型

Emi*_*min 14 java generics rest jax-rs jersey

我有一个通用的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();
    }
}
Run Code Online (Sandbox Code Playgroud)

和用户类:

public class User extends GenericModel {
    ...
}
Run Code Online (Sandbox Code Playgroud)

这里是示例子类定义:

@Path("users")
public class UserResource extends GenericDataResource<User> {

    public UserResource() {
        super(User.class);
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到以下异常:

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.
Run Code Online (Sandbox Code Playgroud)

如果我用定义的类替换T,例如User:

GenericEntity<List<User>>(list)

然后它工作正常.

有关如何使其与通用T一起使用的任何想法?

Raf*_*ele 11

编译源代码后,由该行创建的(匿名)类:

new GenericEntity<List<T>>(list) {}
Run Code Online (Sandbox Code Playgroud)

使用类型变量来引用其父变量.由于类型变量在运行时没有值,因此不能使用这样的泛型.您被迫从调用站点传递所谓的类型令牌.这是一个需要从调用者传递令牌的示例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();
  }
}
Run Code Online (Sandbox Code Playgroud)

来电者会发送一个令牌

new GenericEntity<List<User>>() {}
Run Code Online (Sandbox Code Playgroud)

如果您只使用非参数化子类,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();
}
Run Code Online (Sandbox Code Playgroud)

您必须实现getType()以返回所需的类型.它将是一个ParameterizedType能够表示类型的子类List<DAO<User>>


jed*_*diz 9

除了答案之外,还要在客户端上读取Response对象:

List<MyObject> list = response.readEntity(new GenericType<List<MyObject>>(){}));
Run Code Online (Sandbox Code Playgroud)