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

我正在为一个 GET 服务创建一个 Jersey 客户端,该服务将 List 作为查询参数。根据 文件,可以有一个 List 作为查询参数(这个信息也在 @ QueryParam javadoc 中) ,检查一下:

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

  1. 是原始类型;
  2. 有一个接受单个 String 参数的构造函数;
  3. 有一个名为 valueOf 或 FROM String 的静态方法,该方法接受单个 String 参数(例如,参见 Integer.valueOf (String)和 java.util.UUID.FROM String (String)) ; 或者
  4. Be List,Set 或 SortedSet,其中 T 满足上面的2或3。

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

但是,我不知道如何使用 Jersey 客户机添加 List 查询参数。

据我所知,替代解决方案包括:

  1. 使用 POST 代替 GET;
  2. 将 List 转换为 JSON 字符串并将其传递给服务。

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

如果你不能帮助我,第二个选择将是我的选择。 :)

我还在开发这项服务,所以我可能会根据需要进行更改。

谢谢!

更新

客户端代码(使用 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>() {});
268401 次浏览

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:

@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

Which would result in inputList being deserialized to contain the values 'Hello', 'Stay' and '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. which is shown in following figure

enter image description here

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 does support List of Strings

Setup:
Java : 1.7
Jersey version : 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());
}

GET Request with JSON Query Param

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:

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

Example (jersey-client 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:

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