Jersey客户端:如何添加一个列表作为查询参数

时间:2022-07-21 19:34:38

I'm creating a Jersey client for a GET service that has a List as query parameter. According to the documentation, it's possible to have a List as a query parameter (this information is also at @QueryParam javadoc), check it out:

我正在为GET服务创建一个Jersey客户端,它有一个作为查询参数的列表。根据文档,可以将列表作为查询参数(此信息也在@QueryParam javadoc),请查看:

In general the Java type of the method parameter may:

一般来说,Java类型的方法参数可以:

  1. Be a primitive type;
  2. 是一个原始类型;
  3. Have a constructor that accepts a single String argument;
  4. 具有接受单个字符串参数的构造函数;
  5. Have a static method named valueOf or fromString that accepts a single String argument (see, for example, Integer.valueOf(String) and java.util.UUID.fromString(String)); or
  6. 有一个名为valueOf或fromString的静态方法,它接受单个字符串参数(例如,Integer.valueOf(String)和java.util. uid .fromString(String));或
  7. Be List, Set or SortedSet, where T satisfies 2 or 3 above. The resulting collection is read-only.
  8. 为List, Set或SortedSet,其中T满足2或3以上。结果的集合是只读的。

Sometimes parameters may contain more than one value for the same name. If this is the case then types in 4) may be used to obtain all values.

有时参数可能包含相同名称的多个值。如果是这种情况,那么可以使用4)中的类型来获取所有值。

However, I can't figure out how to add a List query parameter using Jersey client.

但是,我不知道如何使用Jersey client添加列表查询参数。

I understand alternative solutions are:

我明白可供选择的解决方案是:

  1. Use POST instead of GET;
  2. 用POST代替GET;
  3. Transform the List into a JSON string and pass it to the service.
  4. 将列表转换为JSON字符串并将其传递给服务。

The first one is not good, because the proper HTTP verb for the service is GET. It is a data retrieval operation.

第一个不是很好,因为服务的合适的HTTP谓词是GET。它是一种数据检索操作。

The second will be my option if you can't help me out. :)

如果你不能帮我,我可以选择第二个。:)

I'm also developing the service, so I may change it as needed.

我也在开发这个服务,所以我可以根据需要修改它。

Thanks!

谢谢!

Update

更新

Client code (using json)

客户端代码(使用json)

Client client = Client.create();

WebResource webResource = client.resource(uri.toString());

SearchWrapper sw = new SearchWrapper(termo, pagina, ordenacao, hits, SEARCH_VIEW, navegadores);

MultivaluedMap<String, String> params = new MultivaluedMapImpl();
params.add("user", user.toUpperCase()); 
params.add("searchWrapperAsJSON", (new Gson()).toJson(sw));

ClientResponse clientResponse = webResource .path("/listar")
                                            .queryParams(params)
                                            .header(HttpHeaders.AUTHORIZATION, AuthenticationHelper.getBasicAuthHeader())
                                            .get(ClientResponse.class);

SearchResultWrapper busca = clientResponse.getEntity(new GenericType<SearchResultWrapper>() {});

4 个解决方案

#1


86  

@GET does support List of Strings

@GET支持字符串列表

Setup:
Java : 1.7
Jersey version : 1.9

安装:Java: 1.7 Jersey版本:1.9

Resource

资源

@Path("/v1/test")

Subresource:

子资源:

// receive List of Strings
@GET
@Path("/receiveListOfStrings")
public Response receiveListOfStrings(@QueryParam("list") final List<String> list){
    log.info("receieved list of size="+list.size());
    return Response.ok().build();
}

Jersey testcase

泽testcase

@Test
public void testReceiveListOfStrings() throws Exception {
    WebResource webResource = resource();
    ClientResponse responseMsg = webResource.path("/v1/test/receiveListOfStrings")
            .queryParam("list", "one")
            .queryParam("list", "two")
            .queryParam("list", "three")
            .get(ClientResponse.class);
    Assert.assertEquals(200, responseMsg.getStatus());
}

#2


25  

If you are sending anything other than simple strings I would recommend using a POST with an appropriate request body, or passing the entire list as an appropriately encoded JSON string. However, with simple strings you just need to append each value to the request URL appropriately and Jersey will deserialize it for you. So given the following example endpoint:

如果您发送的不是简单的字符串,我建议您使用一个适当的请求主体的POST,或者将整个列表作为适当编码的JSON字符串传递。但是,对于简单的字符串,您只需适当地将每个值附加到请求URL, Jersey将为您反序列化它。因此,给定以下示例端点:

@Path("/service/echo") public class MyServiceImpl {
    public MyServiceImpl() {
        super();
    }

    @GET
    @Path("/withlist")
    @Produces(MediaType.TEXT_PLAIN)
    public Response echoInputList(@QueryParam("list") final List<String> inputList) {
        return Response.ok(inputList).build();
    }
}

Your client would send a request corresponding to:

你的客户会发出相应的要求:

GET http://example.com/services/echo?list=Hello&list=Stay&list=Goodbye

得到http://example.com/services/echo?list=Hello&list=Stay&list=Goodbye

Which would result in inputList being deserialized to contain the values 'Hello', 'Stay' and 'Goodbye'

这将导致inputList被反序列化以包含值'Hello'、'Stay'和'Goodbye'

#3


4  

i agree with you about alternative solutions which you mentioned above

我同意你上面提到的替代方案

1. Use POST instead of GET;
2. Transform the List into a JSON string and pass it to the service.

and its true that you can't add List to MultiValuedMap because of its impl class MultivaluedMapImpl have capability to accept String Key and String Value. which is shown in following figure

而且,由于它的impl类MultivaluedMapImpl有能力接受字符串键和字符串值,所以不能将List添加到MultiValuedMap。如下图所示

Jersey客户端:如何添加一个列表作为查询参数

still you want to do that things than try following code.

您仍然希望做这些事情,而不是尝试下面的代码。

Controller Class

控制器类

package net.yogesh.test;

import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

import com.google.gson.Gson;

@Path("test")
public class TestController {
       @Path("testMethod")
       @GET
       @Produces("application/text")
       public String save(
               @QueryParam("list") List<String> list) {

           return  new Gson().toJson(list) ;
       }
}

Cleint Class

Cleint类

package net.yogesh.test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.ws.rs.core.MultivaluedMap;

import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.core.util.MultivaluedMapImpl;

public class Client {
    public static void main(String[] args) {
        String op = doGet("http://localhost:8080/JerseyTest/rest/test/testMethod");
        System.out.println(op);
    }

    private static String doGet(String url){
        List<String> list = new ArrayList<String>();
        list = Arrays.asList(new String[]{"string1,string2,string3"});

        MultivaluedMap<String, String> params = new MultivaluedMapImpl();
        String lst = (list.toString()).substring(1, list.toString().length()-1);
        params.add("list", lst);

        ClientConfig config = new DefaultClientConfig();
        com.sun.jersey.api.client.Client client = com.sun.jersey.api.client.Client.create(config);
        WebResource resource = client.resource(url);

        ClientResponse response = resource.queryParams(params).type("application/x-www-form-urlencoded").get(ClientResponse.class);
        String en = response.getEntity(String.class);
        return en;
    }
}

hope this'll help you.

希望这能对你有所帮助。

#4


1  

GET Request with JSON Query Param

使用JSON查询参数获取请求

package com.rest.jersey.jerseyclient;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

public class JerseyClientGET {

    public static void main(String[] args) {
        try {


            String BASE_URI="http://vaquarkhan.net:8080/khanWeb"; 




            Client client = Client.create();

            WebResource webResource = client.resource(BASE_URI);

            ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);

            /*if (response.getStatus() != 200) {
               throw new RuntimeException("Failed : HTTP error code : "
                + response.getStatus());
            }
*/
            String output = webResource.path("/msg/sms").queryParam("search","{\"name\":\"vaquar\",\"surname\":\"khan\",\"ext\":\"2020\",\"age\":\"34\""}").get(String.class);
            //String output = response.getEntity(String.class);

            System.out.println("Output from Server .... \n");



            System.out.println(output);




            //


        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

Post Request :

Post请求:

package com.rest.jersey.jerseyclient;

import com.rest.jersey.dto.KhanDTOInput;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.json.JSONConfiguration;

public class JerseyClientPOST {

    public static void main(String[] args) {
        try {

            KhanDTOInput khanDTOInput = new KhanDTOInput("vaquar", "khan", "20", "E", null, "2222", "8308511500");


            ClientConfig clientConfig = new DefaultClientConfig();

            clientConfig.getFeatures().put( JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);

            Client client = Client.create(clientConfig);
            //


               // final HTTPBasicAuthFilter authFilter = new HTTPBasicAuthFilter(username, password);
               // client.addFilter(authFilter);
               // client.addFilter(new LoggingFilter());

            //
            WebResource webResource = client
                    .resource("http://vaquarkhan.net:12221/khanWeb/messages/sms/api/v1/userapi");

              ClientResponse response = webResource.accept("application/json")
                .type("application/json").put(ClientResponse.class, khanDTOInput);


            if (response.getStatus() != 200) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + response.getStatus());
            }

            String output = response.getEntity(String.class);

            System.out.println("Server response .... \n");
            System.out.println(output);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

#1


86  

@GET does support List of Strings

@GET支持字符串列表

Setup:
Java : 1.7
Jersey version : 1.9

安装:Java: 1.7 Jersey版本:1.9

Resource

资源

@Path("/v1/test")

Subresource:

子资源:

// receive List of Strings
@GET
@Path("/receiveListOfStrings")
public Response receiveListOfStrings(@QueryParam("list") final List<String> list){
    log.info("receieved list of size="+list.size());
    return Response.ok().build();
}

Jersey testcase

泽testcase

@Test
public void testReceiveListOfStrings() throws Exception {
    WebResource webResource = resource();
    ClientResponse responseMsg = webResource.path("/v1/test/receiveListOfStrings")
            .queryParam("list", "one")
            .queryParam("list", "two")
            .queryParam("list", "three")
            .get(ClientResponse.class);
    Assert.assertEquals(200, responseMsg.getStatus());
}

#2


25  

If you are sending anything other than simple strings I would recommend using a POST with an appropriate request body, or passing the entire list as an appropriately encoded JSON string. However, with simple strings you just need to append each value to the request URL appropriately and Jersey will deserialize it for you. So given the following example endpoint:

如果您发送的不是简单的字符串,我建议您使用一个适当的请求主体的POST,或者将整个列表作为适当编码的JSON字符串传递。但是,对于简单的字符串,您只需适当地将每个值附加到请求URL, Jersey将为您反序列化它。因此,给定以下示例端点:

@Path("/service/echo") public class MyServiceImpl {
    public MyServiceImpl() {
        super();
    }

    @GET
    @Path("/withlist")
    @Produces(MediaType.TEXT_PLAIN)
    public Response echoInputList(@QueryParam("list") final List<String> inputList) {
        return Response.ok(inputList).build();
    }
}

Your client would send a request corresponding to:

你的客户会发出相应的要求:

GET http://example.com/services/echo?list=Hello&list=Stay&list=Goodbye

得到http://example.com/services/echo?list=Hello&list=Stay&list=Goodbye

Which would result in inputList being deserialized to contain the values 'Hello', 'Stay' and 'Goodbye'

这将导致inputList被反序列化以包含值'Hello'、'Stay'和'Goodbye'

#3


4  

i agree with you about alternative solutions which you mentioned above

我同意你上面提到的替代方案

1. Use POST instead of GET;
2. Transform the List into a JSON string and pass it to the service.

and its true that you can't add List to MultiValuedMap because of its impl class MultivaluedMapImpl have capability to accept String Key and String Value. which is shown in following figure

而且,由于它的impl类MultivaluedMapImpl有能力接受字符串键和字符串值,所以不能将List添加到MultiValuedMap。如下图所示

Jersey客户端:如何添加一个列表作为查询参数

still you want to do that things than try following code.

您仍然希望做这些事情,而不是尝试下面的代码。

Controller Class

控制器类

package net.yogesh.test;

import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

import com.google.gson.Gson;

@Path("test")
public class TestController {
       @Path("testMethod")
       @GET
       @Produces("application/text")
       public String save(
               @QueryParam("list") List<String> list) {

           return  new Gson().toJson(list) ;
       }
}

Cleint Class

Cleint类

package net.yogesh.test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.ws.rs.core.MultivaluedMap;

import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.core.util.MultivaluedMapImpl;

public class Client {
    public static void main(String[] args) {
        String op = doGet("http://localhost:8080/JerseyTest/rest/test/testMethod");
        System.out.println(op);
    }

    private static String doGet(String url){
        List<String> list = new ArrayList<String>();
        list = Arrays.asList(new String[]{"string1,string2,string3"});

        MultivaluedMap<String, String> params = new MultivaluedMapImpl();
        String lst = (list.toString()).substring(1, list.toString().length()-1);
        params.add("list", lst);

        ClientConfig config = new DefaultClientConfig();
        com.sun.jersey.api.client.Client client = com.sun.jersey.api.client.Client.create(config);
        WebResource resource = client.resource(url);

        ClientResponse response = resource.queryParams(params).type("application/x-www-form-urlencoded").get(ClientResponse.class);
        String en = response.getEntity(String.class);
        return en;
    }
}

hope this'll help you.

希望这能对你有所帮助。

#4


1  

GET Request with JSON Query Param

使用JSON查询参数获取请求

package com.rest.jersey.jerseyclient;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

public class JerseyClientGET {

    public static void main(String[] args) {
        try {


            String BASE_URI="http://vaquarkhan.net:8080/khanWeb"; 




            Client client = Client.create();

            WebResource webResource = client.resource(BASE_URI);

            ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);

            /*if (response.getStatus() != 200) {
               throw new RuntimeException("Failed : HTTP error code : "
                + response.getStatus());
            }
*/
            String output = webResource.path("/msg/sms").queryParam("search","{\"name\":\"vaquar\",\"surname\":\"khan\",\"ext\":\"2020\",\"age\":\"34\""}").get(String.class);
            //String output = response.getEntity(String.class);

            System.out.println("Output from Server .... \n");



            System.out.println(output);




            //


        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

Post Request :

Post请求:

package com.rest.jersey.jerseyclient;

import com.rest.jersey.dto.KhanDTOInput;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.json.JSONConfiguration;

public class JerseyClientPOST {

    public static void main(String[] args) {
        try {

            KhanDTOInput khanDTOInput = new KhanDTOInput("vaquar", "khan", "20", "E", null, "2222", "8308511500");


            ClientConfig clientConfig = new DefaultClientConfig();

            clientConfig.getFeatures().put( JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);

            Client client = Client.create(clientConfig);
            //


               // final HTTPBasicAuthFilter authFilter = new HTTPBasicAuthFilter(username, password);
               // client.addFilter(authFilter);
               // client.addFilter(new LoggingFilter());

            //
            WebResource webResource = client
                    .resource("http://vaquarkhan.net:12221/khanWeb/messages/sms/api/v1/userapi");

              ClientResponse response = webResource.accept("application/json")
                .type("application/json").put(ClientResponse.class, khanDTOInput);


            if (response.getStatus() != 200) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + response.getStatus());
            }

            String output = response.getEntity(String.class);

            System.out.println("Server response .... \n");
            System.out.println(output);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}