我只是想澄清一下“如果未指定,默认情况下 Jersey 会生成“application/octet-stream””并不完全正确。实际上幕后发生了很多复杂的事情,这决定了最终的结果Content-Type
。正如规范中所述:
注意上面的(实际上below:-) 使用默认媒体类型呈现响应application/octetstream
当无法确定具体类型时.
但是,正如我所说,有一个复杂的算法可以确定这种“具体类型”。我测试过的情况并不多application/octet-stream
。它如下所示(这直接来自规范。您可以尝试制作它的头部或尾部,但这不适合外行):
3.8 确定响应的媒体类型
In many cases it is not possible to statically determine the media type of a response. The following algorithm is used to determine the response media type, Mselected, at run time:
If the method returns an instance of Response
whose metadata includes the response media type
(Mspecified) then set Mselected = Mspecified, finish.
-
收集可制作的媒体类型集P:
- 如果该方法被注释为
@Produces
, set P = {V(方法)} 其中V (t
) 代表的值@Produces
在指定目标上t
.
- 否则,如果该类被注释为
@Produces
, set P= {V(类)}。
- 其他设置P = {V(作家)} 其中 '
writers
' 是一组MessageBodyWriter
支持返回的实体对象的类。
If P= {},设置P = {'*/*'
}
获取可接受的媒体类型A. If A= {},设置A = {'*/*'
}
-
Set M= {}。对于每个成员A; a
:
- For each member of P;
p
:
- 如果a兼容
p
, add S(a
; p
) to M,其中函数S
返回 q 值为该对中最具体的媒体类型a
和服务器端 qs 值p
.
If M= {} 然后生成一个NotAcceptableException
(406 状态)并且没有实体。必须按照第 3.3.4 节中的描述处理异常。结束。
Sort M按降序排列,并具有特定的主键(n/m > n/* > */*)
,q-value 的辅助键和 qs-value 的第三键。
-
对于每个成员M; m
:
- If
m
is a concrete type, set Mselected = m
, finish.
If M contains '*/*'
or 'application/*
', set Mselected = 'application/octet-stream'
, finish.
生成一个NotAcceptableException
(406 状态)并且没有实体。必须按照第 3.3.4 节中的描述处理异常。结束。
你可以看到这并不像说的那么容易,它总是默认为application/octet-stream
。简单的例子
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response createCustomer(@FormParam("id") int id,
@FormParam("name") String name) {
return Response.ok("OK I GOT IT").build();
}
上面会返回Content-Type: text/plain
假设你创建了一个Customer
对象并返回它
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response createCustomer(@FormParam("id") int id,
@FormParam("name") String name) {
Customer customer = new Customer(id, name);
return Response.ok(customer).build();
}
根据我的测试,它会返回Content-Type: application/xml
是的,身体内容will是 XML。
现在,如果我们发送带有Accept
标题为application/json
,我们将得到一个响应头Content-Type: application/json
,是的,正文内容将是 json。这就是内容协商发挥作用的地方
如果我们只是回应201 Created
,这在POST
/创建请求
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response createCustomer(@FormParam("id") int id,
@FormParam("name") String name) {
return Response.created(someNewUri).build();
}
将有no Content-Type
响应头,因为没有内容。
现在,上面的一些示例并不是很好的 REST 主要示例,但它表明,如果我们没有明确设置媒体类型,那么确定媒体类型需要做很多工作@Produces
。您必须考虑响应的正文,可用MessageBodyWriters
, 你有内容协商 http://en.wikipedia.org/wiki/Content_negotiation考虑在内,以及规范中那些胡言乱语中的其他内容。 (注意:我将“内容协商”链接加粗,因为这是一个您在使用 REST 时应该真正熟悉的概念。它实际上在 JAX-RS/Jersey 中发挥着重要作用)。
所以你问题的答案实际上是这取决于。但希望您从这篇文章中获得了一些额外的知识:-)