17

我尝试访问提供交通信息的开放数据网络服务。文档说请求必须GET并且需要包含Accept: application/jsonand Content-Type: application/json。我不明白他们为什么需要Content-Type但是好的:

我尝试仅使用Accept:Header 检索数据,但我总是得到一个415 Unsupported Media Type. 现在我正在尝试这种方式(但我不确定我是否真的正确设置了两个标题):

String entity = ClientBuilder.newClient().target(liveDataURI)
    .path(liveDataPath)
    .request(MediaType.APPLICATION_JSON)
    .accept(MediaType.APPLICATION_JSON)
    .get(String.class);

如您所见,我使用的是 Jersey 2.2,但我仍然得到一个415 Unsupported Media Type.

编辑

所以我让它工作,但我不明白为什么。不是accept(MediaType.APPLICATION_JSON)header("Content-type","application/json")一样吗?

String responseEntity = ClientBuilder.newClient()
    .target(liveDataURI)
    .path(liveDataPath)
    .request(MediaType.APPLICATION_JSON)
    .header("Content-type", "application/json")
    .get(String.class);
4

3 回答 3

20

Accept头告诉服务器您的客户端在响应中想要什么。标Content-Type头告诉服务器客户端在请求中发送的内容。所以两者并不相同。

如果服务器只接受application/json,则必须发送指定请求内容的请求:

Content-Type: application/json

这就是您编辑的代码有效的原因。

编辑

在您使用的第一个代码WebTarget.request(MediaType... acceptedResponseTypes)中。该方法的参数

定义接受的响应媒体类型。

您正在使用Innvocation.Builder.accept(MediaType... mediaTypes)此方法调用的结果。但是accept()没有添加新的标题,在你的第一个代码中是不必要的。

您从不指定请求的内容类型。由于服务器需要一个Content-Type标头,因此它以415.

于 2013-09-04T07:27:18.297 回答
18

不是accept(MediaType.APPLICATION_JSON)header("Content-type","application/json")一样吗?

不,它们是不同的。
这就是它们的关系:

Client                     Server
(header)                   (class/method annotation)
====================================================
Accept          <--->      @Produces
Content-Type    <--->      @Consumes

服务器使用它从客户端接收到的内容(其格式在 中指定Content-Type)并产生客户端接受的内容(其格式在 中指定Accept)。

示例

  • 客户端发送以下标头:
    • Content-Type= text/xml(它在正文中发送一个 XML)
    • Accept= application/json(它期望得到一个 JSON 作为响应)
  • 服务器至少需要为相应的方法提供以下注释(如果没有为该方法明确提及,则这些注释取自类级别):
    • @Consumes(MediaType.TEXT_XML)(它从客户端获取 XML)
    • @Produces(MediaType.APPLICATION_JSON)(它向客户端发送 JSON)

观察

  1. 服务器可以更加灵活,被配置为获取/生成多种可能的格式

    例如:一个客户端可以发送一个 XML 而另一个客户端可以发送一个 JSON 到相同的方法,如果它具有以下注解:@Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML }).

  2. 这些MediaType值只是String常量:

    public final static String APPLICATION_JSON = "application/json";
    public final static String TEXT_XML = "text/xml";
    
于 2016-01-12T23:00:08.457 回答
2

ContainerResponseFilter如果输入请求中未提供默认的 Accept 标头,您可以使用设置默认标头。

@Provider
public class EntityResponseFilter implements ContainerResponseFilter {

    private MediaType getExternalMediaType(){
        MediaType mediaType = new MediaType("application", "vnd.xxx.resource+json")
        return mediaType; 
    }

    @Override
    public void filter( ContainerRequestContext reqc , ContainerResponseContext resc ) throws IOException {
        MediaType mediaType = getExternalMediaType(); 
        List<MediaType> mediaTypes = reqc.getAcceptableMediaTypes();
        if( mediaTypes.contains(mediaType) ) {   
            resc.setEntity( resc.getEntity(), new Annotation[0], mediaType );
        }
        // ...
    }
}
于 2015-10-29T10:53:50.523 回答