Java 如果@products注释丢失,jersey服务将返回什么?

Java 如果@products注释丢失,jersey服务将返回什么?,java,rest,jersey,jax-rs,restful-architecture,Java,Rest,Jersey,Jax Rs,Restful Architecture,我开始学习开发restful web服务 正如我在大多数示例中所注意到的,使用以下注释: @Consumes 定义输入参数的格式 @Produces 定义输出参数的格式 @Produces 但在实际代码中,我看到的方法如下所示: @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Path("/login") public Response login(@FormParam("login") final String userna

我开始学习开发restful web服务

正如我在大多数示例中所注意到的,使用以下注释:

@Consumes
定义输入参数的格式

@Produces
定义输出参数的格式

@Produces
但在实际代码中,我看到的方法如下所示:

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/login")
public Response login(@FormParam("login") final String username, @FormParam("password") final String password){...}
我看到这个方法使用了
POST
HTTP方法。参数
userName
password
将根据
@消费(MediaType.APPLICATION\u form\u URLENCODED)
生成表单。我看到了执行这个方法的URL


但我不明白这个方法会返回什么。哪种格式?

默认情况下,如果未指定,Jersey将生成“应用程序/八位字节流”。有关详细信息,请参阅。它返回Response对象,其中包含您希望回复客户端的http状态。

我只想澄清,“默认情况下,Jersey生成”应用程序/八位字节流“如果未指定”并不完全正确。实际上,幕后有很多复杂的事情,这决定了最终的
内容类型。如规范所述:

请注意,当无法确定具体类型时,上面(实际上在下面:-)使用默认媒体类型
application/octetstream
呈现响应

但是,正如我所说,有一个复杂的算法用于确定这种“具体类型”。我测试过的案例中没有多少会返回
application/octet-stream
。它如下所示(这是直接从规范中获得的。您可以尝试了解它的正面或反面,但它不适合外行):

3.8确定响应的媒体类型 在许多情况下,无法静态确定响应的介质类型。以下算法用于在运行时确定响应媒体类型Mselected:

  • 如果该方法返回其元数据包含响应媒体类型的
    Response
    实例 (msspecified)然后设置Mselected=msspecified,finish

  • 收集可生产介质类型集p:

    • 如果方法用
      @products
      注释,则设置P={V(method)},其中V(
      t
      )表示指定目标
      t
      @products
      的值
    • 否则,如果用
      @products
      注释该类,则设置P={V(class)}
    • Else set P={V(writers)},其中“
      writers
      ”是支持返回的实体对象类的
      MessageBodyWriter
      的集合
  • 如果p={},则设置p={
    '*/*'
    }

  • 获取可接受的媒体类型A。如果A={},则设置A={
    '*/*'
    }

  • 设置M={}。适用于一个组织的每个成员<代码>a
    • 对于P的每个成员<代码>p:
    • 如果a与
      p
      兼容,则将S(
      a
      p
      )添加到M,其中函数
      S
      返回对中最具体的媒体类型,q值为
      a
      ,服务器端qs值为
      p
  • 如果M={},则生成一个
    NotAcceptableException
    (406状态)且无实体。必须按照第3.3.4节所述处理例外情况。结束

  • 按降序对M排序,主键为特异性
    (n/M>n/*>*/*)
    ,次键为q值,第三键为qs值

  • 对于M的每个成员<代码>m:

    • 如果
      m
      是具体类型,则设置Mselected=
      m
      ,finish
  • 如果M包含
    '*/*'
    'application/*
    ',则设置Mselected=
    'application/octet stream'
    ,完成

  • 生成一个
    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();
    }
    
    以上内容将返回
    内容类型: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();
    }
    
    根据我测试的结果,它将返回
    内容类型:application/xml
    ,是的,主体内容将是xml

    现在,如果我们使用
    application/json
    Accept
    头发送请求,我们将得到
    Content-Type:application/json
    的响应头,因为是的,主体内容将是json。这是内容协商发挥作用的一个因素

    如果我们只是用
    201 Created
    响应,这在
    POST
    /create请求中非常常见

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response createCustomer(@FormParam("id") int id, 
                                   @FormParam("name") String name) {
        return Response.created(someNewUri).build();
    }
    
    由于没有内容,因此将不会有
    内容类型
    响应标题

    现在,上面的一些示例不是great REST princial示例,但它表明,如果我们不显式地使用
    @products
    设置媒体类型,那么在确定媒体类型方面需要做很多工作。你必须考虑,响应的身体,可用代码<代码> MeasAgBoDyDrase<代码>,你必须考虑到,从MUBO巨无霸的任何其他方面来看。(注意:我将“内容协商”链接加粗,因为这是一个在使用REST时应该非常熟悉的概念。它实际上在JAX-RS/Jersey中起着重要作用)

    因此,您的问题的答案实际上是这取决于。但希望您已经从这篇文章中获得了一些额外的知识:-)

    正确的url现在是“如果请求不包含内容类型头,那么使用应用程序/octet流媒体类型。”