REST风格的Response对象使用Java的泛型模板类型通过GenericEntity (Us

2019-07-21 14:48发布

我有一个通用的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)

然后正常工作。

任何想法,我怎么可以把它与一般的科技工作?

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



Answer 2:

除了答案,读取响应对象后面的客户端上:

List<MyObject> list = response.readEntity(new GenericType<List<MyObject>>(){}));


Answer 3:

Response对象被返回到客户端响应请求发送到服务器。 响应类有收集设置为其类型Response.ResponseBuilder的字段中的每个属性Response.ResponseBuilder内部类。 Response.ResponseBuilder应用生成器设计模式来构建响应对象。

构建()方法负责连接形成在构建的过程Response.ResponseBuilder对象链。 例如

Response.status(200);   

状态的方法分配状况进行评估后返回Response.ResponseBuilder

 Response.status(200).entity( AnyObj );

实体对象分配类型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是列表的类型如以上给出。 实体方法接受其是通用的对象类型。 在情况下,特定类型的需要,你得把它作为通过在运行时它强制转换为特定类型的对象GenericEntity类型的参数。

实际使用

想为我的球衣框架来这是List对象在我的Java模型回客户端作为响应对象的一部分数组类型的响应JSON。

因此,新GenericEntity> ---连铸对象/有效载荷列出类型新GenericEntity ---运行时类型变得字符串


资源WebService的方

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>>() {});


Answer 4:

为了解决这个问题一提出来返回的方法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) {
        };
    }

}


文章来源: Using Java-generics template type in RESTful Response object via GenericEntity>