Jersey 内容类型自定义

Posted

技术标签:

【中文标题】Jersey 内容类型自定义【英文标题】:Jersey content type customization 【发布时间】:2012-02-19 08:43:20 【问题描述】:

您好,我有一个场景,我想在不使用请求标头内容类型的情况下动态控制球衣网络服务返回的内容类型。

目前我做的是标准的事情:

@Produces( "application/xml", "application/json") 
public ContactsConverter getSearchContacts()

所以默认情况下我会取回 xml。但是,如果我想取回一个 json 对象,我必须在我的请求标头中设置“Content-Type: application/json”。目前这对我来说不是一个选项,因为请求来自跨域 ajax 调用,其中内容类型将始终为 /。因此,我想在我的请求中使用一个标志或一些聪明的东西来指定返回的内容类型。我环顾四周,但没有看到任何有用的东西,一个建议是发送 json 作为默认值,但这是我想避免做的事情。

【问题讨论】:

你需要一些方法来检测服务器上的内容类型。可能基于传入请求对象的内容? 【参考方案1】:

首先,我认为 Jersey 在这里做错了,因为 Content-Type 是一个描述请求/响应内容的标头,并且您没有在请求中包含任何内容,它实际上应该而是将其行为基于 Accepts 标头,但将其放在一边......

仅仅因为它是一个ajax调用,并不意味着content-type总是/,在客户端你可以像这样调用setRequestHeader:

var xhr = new XMLHttpRequest();
xhr.open("POST", "http://myjaxrs-server/getSearchContacts");
xhr.onreadystatechange = function() 
    /* normal javascript to deal with the response goes here */
;

xhr.setRequestHeader("Content-Type", "application/json");

xhr.send("data i'm posting");

在 CORS 请求上设置 Content-Type 标头将导致预检发生。您必须支持服务器代码中的预检,否则 CORS 请求将被拒绝。为 getSearchContacts 提供您的正常代码,但预检将使用 OPTIONS 方法进行:

@OPTIONS
public Response preflight(
    @HeaderParam("Access-Control-Request-Method") String requestMethod,
    @HeaderParam("Origin") String origin,
    @HeaderParam("Access-Control-Request-Headers") String requestHeaders) 
return Response
    .ok()
    .header("Access-Control-Allow-Origin", "*") // TODO replace with specific origin
    .header("Access-Control-Allow-Headers", "Content-Type")
    .build();

现在将允许带有自定义标头的 CORS 请求。

这很容易出错:据我所知,即使是 google 电子表格 API 也无法正确响应预检,这意味着您实际上无法更改 javascript 中的任何数据。

【讨论】:

以上是关于Jersey 内容类型自定义的主要内容,如果未能解决你的问题,请参考以下文章

如何注册现有的 Jersey MessageBodyReader Provider 来处理其他内容类型?

JAX-RS Jersey 读取内容类型为“*”的实体

Jersey Rest服务类型

在 drupal 8 的另一个自定义内容类型字段中使用自定义内容类型作为字段

Drupal 自定义内容类型列表视图

Magnolia 自定义内容类型作为属性