【问题标题】:How to write an XML MessageBodyWriter provider with jersey如何使用 jersey 编写 XML MessageBodyWriter 提供程序
【发布时间】:2013-05-24 18:57:31
【问题描述】:

我不是特别想解决任何问题,而是我正在学习球衣。

我有一个这样标记的实体类:

@Entity
@Table(name = "myentity")
@XmlRootElement
public class MyEntity implements serializable {
  // lots of methods...
}

以及相应的球衣服

@Stateless
@Path("entity")
public class EntityFacade {

    @GET
    @Path("{param}")
    @Produces({"application/xml;charset=UTF-8"})
    public List<MyEntity> find(@PathParam("param") String param) {
       List entities = entityManager.getResultList(); // retrieve list from db
       return entities;
    }

}

提供正确的 XML 响应。 假设我想编写一个 MessageBodyWriter 来复制相同的行为,这会产生 XML 响应,我该怎么做?

@Provider
public class TrasformerMessageBodyWriter implements MessageBodyWriter<Object> {

    @Override
    public long getSize(Object o, Class<?> type, Type genericType,
            Annotation[] annotations, MediaType mediaType) {
        return 0;
    }

    @Override
    public boolean isWriteable(Class<?> type, Type genericType,
            Annotation[] annotations, MediaType mediaType) {
        // return true or false depending if I want to rewrite the response
    }

    @Override
    public void writeTo(Object o, Class<?> type, Type genericType,
            Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, Object> httpHeaders,
            OutputStream entityStream) throws IOException,
            WebApplicationException {
        // what do I need to write here...
    }
}

通过使用@Provider 注释进行标记,我可以看到消息正文编写器被正确调用。

当调用 writeTo 时,Object o 是 Vector,Type genericType 是 List,但此时我完全不知道如何在 XML 中转换对象。

最后,如果 jersey 及其注解已经提供了一切,那么 MessageBodyWriter 有什么用处?

我再次重申,这只是一个学术练习。

【问题讨论】:

标签: java jakarta-ee jersey


【解决方案1】:

通常人们会使用MessageBodyWriter 将对象转换为 Jersey 一无所知的数据格式。下面是一个将TableData 域对象转换为 CSV 的示例:

@Singleton
@Produces("text/csv")
@Provider
public class FederationCsvWriter implements MessageBodyWriter<TableData> {

  @Override
  public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
    return TableData.class.isAssignableFrom(type);
  }

  @Override
  public long getSize(TableData data, Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType) {
    return -1;
  }

  @Override
  public void writeTo(TableData data, Class<?> type, Type genericType, Annotation[] annotations,
      MediaType mediaType, MultivaluedMap<String, Object> headers, OutputStream out) throws IOException {
    Writer osWriter = new OutputStreamWriter(out);
    CSVWriter writer = new CSVWriter(osWriter, ',', '"', "\r\n");
    if (data.getResultCount() > 0) {
      //Write the header
      writer.writeNext(data.getResult().get(0).keySet().toArray(new String[data.getResult().get(0).keySet().size()]));

      //Write the data
      for (ModelData row: data.getResult()) {
        writer.writeNext(row.values().toArray(new String[row.values().size()]));
      }
    }
    writer.flush();
  }

}

在您的示例中,您可以通过自己检查对象并将结果提供给OutputStream 来创建 XML,也可以使用 JAXB(Jersey 在内部使用)将对象直接编组到OutputStream。就您的练习而言,JAXB 可能更有趣。

【讨论】:

  • 使用 JAXB 除非我编写了一个包装类,否则 Web 服务会将 List 作为 Vector 返回,因此我无法编组它。
  • 你能解释一下 getSize 应该返回 -1 吗?
  • @StonyZhang - 来自 javadoc (goo.gl/XyrGV):Called before writeTo to ascertain the length in bytes of the serialized form of t. A non-negative return value is used in a HTTP Content-Length header.
  • 非常感谢您的澄清。
  • 根据规范,您不应该关闭 OutputStream。关闭 writer 是否也不会关闭 OutputStream?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-28
  • 1970-01-01
相关资源
最近更新 更多