使用Java-泛型模板类型>
我有一个通用的JAX-RS资源类和我已经定义了一个通用的findAll
方法使用Java-泛型模板类型>
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工作?
一旦源代码被编译,由线产生的(匿名)类:
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>>
THanks Raffaele。我有一个类“公共类UserResource扩展GenericDataResource
无需重写。调用'findAll()'的代码必须传递一个标记,但该方法本身没有修改就可以工作。顺便说一句,如果你绝对确信**你只会通过像'UserResource'这样的非参数化子类来使用'GenericDataResource
实际上没有明确调用findAll的方法。它通过注释调用。我编辑了问题以显示JAX-RS注释。 – Emin 2013-03-14 12:22:32
为了解决它的子类中的做了一个方法返回一个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) {
};
}
}
除了答案,阅读Response对象后面的客户端上:
List<MyObject> list = response.readEntity(new GenericType<List<MyObject>>(){}));
响应对象得到响应请求返回到客户端发送到服务器。 Response类具有Response.ResponseBuilder内部类,它收集每个属性设置为其类型为Response.ResponseBuilder的字段。 Response.ResponseBuilder应用Builder设计模式来构造响应对象。
build()方法负责连接构建过程中形成的Response.ResponseBuilder对象链。 例如分配STATUS
Response.status(200).entity(AnyObj);
实体对象后
Response.status(200);
状态的方法返回Response.ResponseBuilder分配 类型Response.ResponseBuilder的实体(有效载荷返回)和被分配给的响应的实例varible。之后,状态还会分配状态并返回Response.ResponseBuilder实例。构建器在build()方法调用时连接它们。
Response.status(200).entity(obj).build();
最后,构建方法构建完整(有属性阐述)响应。
现在问题GenericEntity对象。它代表了一种通用类型T.
对于实例的响应实体,
GenericEntity> OBJ =新GenericEntity>(LST){}; Response.status(200).entity(obj).build();
obj是List的类型,如上所述。实体方法接受对象通用类型。如果出现特定类型的需要,则必须将其作为GenericEntity类型的参数传递,在运行时将它转换为特定类型的对象。
实际运用
通缉我的球衣框架来这是List对象在我的Java模型回客户端作为响应对象的一部分数组类型的响应JSON。
因此, 新GenericEntity> ---连铸对象/有效载荷列出 类型新GenericEntity ---运行时类型变得字符串
资源上web服务侧
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>>() {});
超类型令牌的整点是捕获,否则将被删除的一般信息。试图让令牌本身具有通用性就是......适得其反。 – Perception 2013-03-14 11:47:58
我需要“T扩展GenericModel”,因为有一些函数需要在抽象类中访问,例如T.getId() – Emin 2013-03-14 11:52:29