【问题标题】:Can @GET define Consumes Content-Type for JAX-RS implementation?@GET 可以为 JAX-RS 实现定义消耗 Content-Type 吗?
【发布时间】:2013-05-12 07:39:31
【问题描述】:

我一直在尝试一些关于 JAXRS 的示例(本示例使用 Jersey)。以下是我拥有的示例存根实现:

    @Path("stubservice")
public class StubImpl
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getString(@QueryParam("first")
    int first, @QueryParam("second")
    int second)
    {
        return "first: " + first + " second: " + second;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public String getSize(@QueryParam("size")
                              int size,
                              @Context
                              HttpHeaders headers)
    {
        Gson gson = new Gson();
        return gson.toJson("something else");
    }
}

如果getSize 方法的定义中没有@Consumes(MediaType.APPLICATION_JSON),则此类在初始化期间会出错。但是有了它,StubImpl 类会正确初始化并根据传入请求的Content-Type 是否为application/json 来处理请求。

初始化时出错:

SEVERE: The following errors and warnings have been detected with resource and/or provider classes: SEVERE: Producing media type conflict. The resource methods public java.lang.String StubImpl.getString(int,int) and public java.lang.String StubImpl.getSize(int,javax.ws.rs.core.HttpHeaders) can produce the same media type

据我了解,@GET 请求永远不需要 @Consumes(MediaType.APPLICATION_JSON),因为它是用于正文中的内容类型(而 GET 方法没有正文)。

是预期的现有行为吗?

提前致谢

【问题讨论】:

  • 奇怪...你得到什么样的错误?是不是可能和HttpHeaders标注@Context注解的参数有关?
  • @AlexR 感谢您的回复。更新错误信息
  • 有人注意到这个问题吗?
  • 它要么是球衣错误,要么是 jax-rs 规范错误。一世。 e.即使使用@Consumes,它也应该给出相同的错误,但事实并非如此。在球衣 jira 上报告 - 他们反应迅速。
  • @randomstring 我正在寻找你预测的答案(认为泽西岛的提交者可能会回应)。还是谢谢你

标签: java rest get jersey jax-rs


【解决方案1】:

根本不是 JAX-RS 专家,所以这只是猜测。

如果您不设置@Consumes(MediaType.APPLICATION_JSON),Jersey 如何决定在 GET 请求进入时调用哪个方法?

这两种方法都在同一路径上响应 GET 请求,接受任何媒体类型,并产生相同的媒体类型。所以我的猜测是,当 GET 请求进入此路径时,Jersey 无法决定(除了随机之外)调用哪个方法,因此拒绝启动。

@Consumes 注释使它在请求具有 JSON 主体时调用 getSize(即从不),而在所有其他情况下调用其他方法(即始终)。

【讨论】:

  • 我认为这是一个错误的猜测。 Jersey 可以根据 Accept: 标头来决定,如果缺少该标头,则会有优先级顺序来提供哪些编码。根据该顺序,它会找到使用正确 @Produces 注释的方法。
  • @randomstring:准确地说。但是由于这两个方法都有相同的Produces注解,所以它无法决定调用哪一个。
  • 正确的与Produces 相同,但我的意思是猜测错误是您猜测@Consumes 用于消除歧义。既然GET 没有实体,那么泽西岛为什么还要费心去看@Consumes,除非它是为了删除在第一种情况下不应该存在的死代码。因此,无论@Consumes 注释如何,歧义仍然存在。
  • 好吧,OP 的问题表明不存在歧义。请参阅下面的 trevgiddy 的答案。
  • 我敢打赌 OP 描述的行为取决于实现。 Jersey 是第一个与 Java EE 计划竞争的参考实现,它没有忽略应用于@GET@Consumes,因此给出了“假阴性” - i。 e.它应该给出相同的初始化错误,但它不是由于错误或由于规范错误而导致的实现定义的行为
【解决方案2】:

您没有为 getString 和 getSize 设置路径。这是根本原因。

   @Path("stubservice")
public class StubImpl
    @GET
    @Path("getstring")   //the full path will be /stubservice/getstring
    @Produces(MediaType.APPLICATION_JSON)
    public String getString(@QueryParam("first")
    int first, @QueryParam("second")
    int second)
    {
        return "first: " + first + " second: " + second;
    }

    @GET
    @Path("getsize")    //the full path will be /stubservice/getsize
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public String getSize(@QueryParam("size")
                              int size,
                              @Context
                              HttpHeaders headers)
    {
        Gson gson = new Gson();
        return gson.toJson("something else");
    }
}

【讨论】:

  • 抱歉,问题在于两个@GET 方法的路径相同。我知道如果@Path 不同,它不会造成任何问题
  • 如果目标是使用相同的 HTTP 字 (GET) 和相同的 URI 路径 (/) 定义这两种方法,您认为 JERSEY 会如何在它们之间产生差异?我的意思是,从调用者的角度来看,你会在 http 请求中提供什么不同的东西?知道查询参数不算数。此外,REST 架构模式不期望在 GET 中提供“正文”内容。
  • @zim2001 我知道当他们的注释定义没有区别时,泽西岛预计会出错。但是,问题是关于影响实现的@Consumes 定义
  • 到目前为止,我没有正确理解您的问题。如果我是正确的,您的问题可以改写为“JERSEY 中是否缺少一个控件,应该使它在这种情况下抛出相同的异常,无论 GET 上的潜在 @Consumes 是什么?”。我会回答是的。
【解决方案3】:

从初始化时遇到的错误开始:

您收到错误的原因是@Stony Zhang 建议的。当您删除 @Consumes 时,这两种方法本质上都指向同一路径,而 JAX-RS 无法区分这两个 RESTFul 端点。

GET 请求不需要@Consumes(MediaType.APPLICATION_JSON)。来自@Consumes oracle documentation 的 Oracle 文档 @Consumes 注释用于指定资源可以从客户端接受或使用的表示的 MIME 媒体类型。这意味着您确实不需要使用 json 作为端点将要接受的媒体类型。您可以使用 @Consumes("multipart/related") 或 @Consumes({"text/plain,text/html"}) 或其他任何东西,具体取决于您发送到服务器的 MIME 类型。

您说@GET 没有正文也是正确的。这放置在 @Path 注释中,是来自 url 的查询字符串输入。有点像

`@GET

 @Path("/stubservice/{id}")`

【讨论】:

    猜你喜欢
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 2013-03-15
    • 2011-06-27
    • 2014-03-12
    • 2019-05-20
    • 1970-01-01
    相关资源
    最近更新 更多