我有一个通用的JAX-RS资源类,并且定义了一个通用的findAll方法
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这样的已定义类:
User
GenericEntity<List<User>>(list)
然后就可以了
关于如何使它与通用T一起工作的任何想法吗?
编译源代码后,将通过以下行创建(匿名)类:
new GenericEntity<List<T>>(list) {}
使用类型变量来引用其父级。由于类型变量在运行时没有值,因此不能使用此类泛型。您被迫从呼叫站点传递所谓的 类型令牌 。这是一个示例,要求从的调用者传递令牌findAll(),但是您可以在构造函数中要求一个令牌,并将其保存在实例变量中:
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>>
getType()
ParameterizedType
List<DAO<User>>