简体   繁体   English

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

[英]Jersey client: How to add a list as query parameter

I'm creating a Jersey client for a GET service that has a List as query parameter.我正在为具有列表作为查询参数的 GET 服务创建 Jersey 客户端。 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:根据文档,可以将 List 作为查询参数(此信息也在@QueryParam javadoc 中),请查看:

In general the Java type of the method parameter may:一般来说,方法参数的 Java 类型可能是:

  1. Be a primitive type;是原始类型;
  2. Have a constructor that accepts a single String argument;有一个接受单个 String 参数的构造函数;
  3. 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));有一个名为 valueOf 或 fromString 的静态方法,它接受单个 String 参数(例如,参见 Integer.valueOf(String) 和 java.util.UUID.fromString(String)); or要么
  4. Be List, Set or SortedSet, where T satisfies 2 or 3 above.是 List、Set 或 SortedSet,其中 T 满足上面的 2 或 3。 The resulting collection is read-only.生成的集合是只读的。

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 客户端添加 List 查询参数。

I understand alternative solutions are:我了解替代解决方案是:

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

The first one is not good, because the proper HTTP verb for the service is GET.第一个不好,因为服务的正确 HTTP 动词是 GET。 It is a data retrieval operation.这是一个数据检索操作。

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>() {});

@GET does support List of Strings @GET支持字符串列表

Setup :设置
Java: 1.7爪哇:1.7
Jersey version: 1.9球衣版本: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球衣测试用例

@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());
}

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.如果您发送的不是简单字符串,我建议您使用带有适当请求正文的 POST,或者将整个列表作为适当编码的 JSON 字符串传递。 However, with simple strings you just need to append each value to the request URL appropriately and Jersey will deserialize it for you.然而,对于简单的字符串,您只需将每个值适当地附加到请求 URL,Jersey 将为您反序列化它。 So given the following example endpoint:因此,给出以下示例端点:

@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”

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.确实不能将List添加到MultiValuedMap ,因为它的 impl 类MultivaluedMapImpl具有接受字符串键和字符串值的能力。 which is shown in following figure如下图所示

在此处输入图像描述

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) ;
       }
}

Client Class客户端类

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.希望这会帮助你。

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:发布请求:

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();

        }    
    }    
}

One could use the queryParam method, passing it parameter name and an array of values:可以使用 queryParam 方法,将参数名称和一组值传递给它:

    public WebTarget queryParam(String name, Object... values);

Example (jersey-client 2.23.2):示例(球衣客户端 2.23.2):

    WebTarget target = ClientBuilder.newClient().target(URI.create("http://localhost"));
    target.path("path")
            .queryParam("param_name", Arrays.asList("paramVal1", "paramVal2").toArray())
            .request().get();

This will issue request to following URL:这将向以下 URL 发出请求:

    http://localhost/path?param_name=paramVal1&param_name=paramVal2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM