使用JAX-RS Jersey 2.2获取Content-Type和Accept标头的请求

时间:2013-09-03 15:01:18

标签: web-services rest jersey jax-rs content-type

我尝试访问一个开放数据网络服务,它为我提供了流量信息。文档说请求必须为GET,并且需要包含Accept: application/jsonContent-Type: application/json。我不明白为什么他们需要Content-Type但是确定:

我尝试仅使用Accept:标头检索数据,但我总是得到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);

3 个答案:

答案 0 :(得分:15)

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

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

Content-Type: application/json

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

修改

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

  

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

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

您永远不会指定请求的内容类型。由于服务器需要Content-Type标头,因此它会以415响应。

答案 1 :(得分:13)

  

["abc", "def"...]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(它在正文中发送XML)
    • text/xml = Accept(希望获得JSON作为回复)
  • 服务器需要至少为相应的方法添加以下注释(如果未针对该方法明确提及注释,则从类级别获取注释):
    • application/json(它从客户端获取XML)
    • @Consumes(MediaType.TEXT_XML)(它向客户端发送JSON)

<强>观测值

  1. 服务器可以更灵活,配置为获得/生成多个可能的格式

    例如:客户端可以发送XML,而另一个客户端可以将JSON发送到同一方法,如果它具有以下注释:@Produces(MediaType.APPLICATION_JSON)

  2. @Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })值仅为MediaType常量:

    String

答案 2 :(得分:2)

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

@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 );
        }
        // ...
    }
}