在 jax-rs 中返回列表作为响应的最便携(或标准)方式是什么?

What is the most portable (or standard) way of returning a list as a response in jax-rs?

好吧,任何人都可以说这个问题已经被提出并得到了回答。没关系我也找到了。

我对使用 List<T> 进行响应的方式并不感到困惑,只是不相信其可移植性。

假设我有一个很好注释的实体,看起来像这样。

@XmlRootElement
public class Stock {

    @XmlAttribute
    private Long id;
}


列表<股票>

什么时候这样做,

@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public List<Stock> readStocks() {
    final List<Stock> list = getStocks();
    return list;
}

据了解,GlassFish 和 WileFly 可以正常工作。

<stocks> <!-- automatic plural? -->
  <stock xmlns="http://...">
  </stock>\
  <stock xmlns="http://...">
  </stock>
</stocks>

<collection> <!-- fixed? -->
  <stock xmlns="http://...">
  </stock>\
  <stock xmlns="http://...">
  </stock>
</collection>

和JSON,(我认为可能因提供商而异)

[
    {
        "id": 1
    },
    {
        "id": 2
    }
]


通用实体<列表<股票>>

有时我会在容器找不到 MessageBodyWriter 时遇到问题。所以我喜欢这个。

@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public GenericEntity<List<T>> readStocks() {
    return new GenericEntity<List<Stock>>(getStocks()) {};
}

@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response readStocks() {
    return Response.ok(new GenericEntity<List<Stock>>(getStocks()) {}).build();
}


WrapperClass

@XmlRootElement
public class Stocks {
    @XmlElement
    private List<Stock> stock;
}

@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Stocks readStocks() {
    final Stocks entity; ///
    return Response.ok(entity).build();
}

根据 4.2.4 Standard Entity Providers (JSR-339),List 不在强制预打包列表中 MessageBody(Reader|Writer)

List<T>是否标准化?或者哪种方式最便携?

List 并不是真正的问题。 JSON 和 XML 的 MBW 对于 isWritable 通常总是 return 正确。这就是他们能够处理您抛出的所有类型的方式。 有关的是类型擦除。 GenericEntity 的目的是缓存泛型类型参数,这允许 MBW 知道要编组的类型。

注意 GenericEntity 通常在 returning Response 时使用。想象一下这种情况

public Response get() {
    List<Somthing> l = service.get();
    return Response.ok(l).build();
}

由于类型擦除,MBW 无法在实体到达类型时知道类型。对于一些提供者来说,这并不重要。例如对于 Jackson,它通常不需要知道类型,因为它只是内省序列化的属性。但是对于 MOXy/JAXB,它本质上需要知道 class。这就是 GenericEntity 发挥作用的地方。

Normally type erasure removes generic type information such that a Response instance that contains, e.g., an entity of type List<String> appears to contain a raw List<?> at runtime. When the generic type is required to select a suitable MessageBodyWriter, this class may be used to wrap the entity and capture its generic type.

...

List<String> list = new ArrayList<String>();
GenericEntity<List<String>> entity = new GenericEntity<List<String>>(list) {};
Response response = Response.ok(entity).build();