【问题标题】:Jersey Client / JAX-RS and optional (not default) @QueryParam (client side)Jersey 客户端/JAX-RS 和可选(非默认)@QueryParam(客户端)
【发布时间】:2015-07-20 17:44:31
【问题描述】:

我有一个 RESTful API,它的文档说某个查询参数是可选的,并且不提供默认参数。因此,我可以提供该值,也可以不将其作为参数在 GET 请求中发送。

例子:

  • queryA 为必填项
  • queryB可选的(可以在没有它的情况下发送GET

这应该可行:

http://www.example.com/service/endpoint?queryA=foo&queryB=bar

这也应该有效:

http://www.example.com/service/endpoint?queryA=foo

如何为Jersey-Proxy 制作一个可以做到这一点的客户端界面? 我没有要与之交互的服务器端代码,因此我通过 Jersey-Proxy 使用 org.glassfish.jersey.client.proxy.WebResourceFactory 来生成客户端以与服务器 API 进行交互。

示例界面:

import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/service")
@Produces("application/json")
public interface ServiceInterface {

    @Path("/endpoint")
    @GET
    public Response getEndpoint(
            @QueryParam("queryA") String first,
            @QueryParam("queryB") String second);

}

我知道我可以制作另一种方法:

    @Path("/endpoint")
    @GET
    public Response getEndpoint(
            @QueryParam("queryA") String first);

但是当您有多个可选字段时会发生什么?我不想对它们进行所有可能的突变!

【问题讨论】:

标签: java rest jersey jax-rs


【解决方案1】:

界面一直都是对的

我不敢相信这么容易:

import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/service")
@Produces("application/json")
public interface ServiceInterface {

    @Path("/endpoint")
    @GET
    public Response getEndpoint(
            @QueryParam("queryA") String first,
            @QueryParam("queryB") String second);

}

请注意与问题界面不同的地方??没有。那是因为这就是答案!


不要将@DefaultValue 用于可选参数

如果你想将一个参数默认为一个特定的值,你可以在参数中使用@DefaultValue注解:

import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/service")
@Produces("application/json")
public interface ServiceInterface {

    @Path("/endpoint")
    @GET
    public Response getEndpoint(
            @QueryParam("queryA") String first,
            @QueryParam("queryB") @DefaultValue("default") String second);

}

null 传递给您不想要的@QueryParam

如果要使@QueryParam 可选,则不要应用@DefaultValue 注释。 要使用查询参数传递值,只需正常传递值即可。如果您希望查询参数根本不显示,只需传递null

import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/service")
@Produces("application/json")
public interface ServiceInterface {

    @Path("/endpoint")
    @GET
    public Response getEndpoint(
            @QueryParam("queryA") String first,
            // Pass null to this parameter to not put it in the GET request
            @QueryParam("queryB") String second);

}

所以调用ServiceInterface.getEndpoint("firstQueryParam", "secondQueryParam");调用:

http://targethost.com/service/endpoint?queryA=firstQueryParam&queryB=secondQueryParam

并致电ServiceInterface.getEndpoint("firstQueryParam", null); 致电:

http://targethost.com/service/endpoint?queryA=firstQueryParam

还有瓦拉!没有第二个查询参数! :)

原始值注意事项

如果您的 API 采用原始值(例如 intfloatboolean 等),则为该原始值使用对象包装类 (Autoboxing)(例如 IntegerFloatBoolean 等)。然后,您可以将null 传递给方法:

public Response getEndpoint(@QueryParam("queryA") Boolean first);

【讨论】:

  • 用数字代替字符串怎么样?没有办法使用null,所以你必须检查值。
  • 我相信您需要使用自动框类型:BooleanInteger 等......
  • 如果您需要维护多个客户端并且它们不能全部升级到您的新 API,Jersey 会非常烦人,基本上它会迫使您在界面中为可选查询参数引入重大更改跨度>
【解决方案2】:

您可以将UriInfo 实例(或HttpServletRequest 之类的其他东西)注入到您的方法中,并从中获取您想要的任何数据。

例如

@Path("/endpoint")
@GET
public Response getEndpoint(@Context UriInfo info, @QueryParam("queryA") String queryA) {
  String queryB = info.getQueryParameters().getFirst("queryB");
  if (null != queryB) {
    // do something with it
  }
  ...
}

【讨论】:

  • 这对 WebResourceFactory 有效吗?我会看看我是否可以这样做......
  • 您提到泽西客户端,但据我所知,您的示例是 JAX-RS 端点的服务器端定义...
  • 这个定义是针对客户端的,因为我没有服务端代码。
  • 好的,我明白了,我不确定你是否可以使用@Context 样式注入……但它可能会起作用。
猜你喜欢
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2019-09-25
  • 2023-03-20
  • 2013-02-13
  • 1970-01-01
  • 2016-02-21
相关资源
最近更新 更多