泽西岛客户端:如何添加列表作为查询参数
Posted
技术标签:
【中文标题】泽西岛客户端:如何添加列表作为查询参数【英文标题】:Jersey client: How to add a list as query parameter 【发布时间】:2012-12-06 18:20:39 【问题描述】:我正在为具有 List 作为查询参数的 GET 服务创建 Jersey 客户端。根据documentation,可以将List作为查询参数(此信息也在@QueryParam javadoc),请查看:
一般来说方法参数的Java类型可以:
是原始类型; 有一个接受单个字符串参数的构造函数; 有一个名为 valueOf 或 fromString 的静态方法,它接受单个 String 参数(例如,请参见 Integer.valueOf(String) 和 java.util.UUID.fromString(String));或 是 List、Set 或 SortedSet,其中 T 满足上述 2 或 3。生成的集合是只读的。
有时参数可能包含多个相同名称的值。如果是这种情况,则可以使用 4) 中的类型来获取所有值。
但是,我不知道如何使用 Jersey 客户端添加列表查询参数。
我了解替代解决方案是:
-
使用 POST 代替 GET;
将 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>() );
【问题讨论】:
你能在这里给球衣客户代码吗... yogesh,我添加了客户端代码。 如果我理解您的问题陈述,您可以通过将多个值添加到同一个键来将值列表作为查询参数传递。如果“searchWrapper”是键并且您想将多个值传递给它:像这样构建 URL: //YourURL?searchWrapper=value1&searchWrapper=value2&searchWrapper=value3 如果您的 MultivaluedMap 支持,您可能需要多次向同一个键插入值. 谢谢@ThammeGowda!我还没有测试过它,但它似乎可以像MultivaluedMap javadoc 那样对 add 方法状态进行测试:将值添加到提供的键的当前值列表中。 【参考方案1】:@GET
确实支持字符串列表
设置: Java : 1.7 球衣版本:1.9
资源
@Path("/v1/test")
子资源:
// 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();
球衣测试用例
@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());
【讨论】:
谢谢。它对我有帮助。 就像给其他人的注释一样,如果您是直接在浏览器中编写 URL,则必须重复参数名称:..?list=one&list=two&list=three 这真的是一个列表吗/是否保证遵守顺序?鉴于它似乎是 Jersey 作为列表返回的多值映射,我想知道是否存在订单未保留的问题 是的。 ?list=one&list=two&list=three 没那么有用。作为 list=one,two,three - 这就是为什么我手动将它从字符串解析到列表的原因。List<String> argList = List.of(argString.split("\\s*,\\s*"))
【参考方案2】:
如果您发送的不是简单字符串,我建议您使用带有适当请求正文的 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();
你的客户会发送一个对应的请求:
获取http://example.com/services/echo?list=Hello&list=Stay&list=Goodbye
这将导致 inputList
被反序列化为包含值“Hello”、“Stay”和“Goodbye”
【讨论】:
感谢您的回答知觉!但我想知道是否可以使用 Jersey 客户端使用 List 作为查询参数进行 GET。 你能告诉我如何在客户端创建这样的列表,因为我的客户是 android 和 ios。显然我们不想手动创建 key=value&key=value 如果它发送list[0]=Hello&list[1]=Stay
怎么办?如何管理?【参考方案3】:
我同意你上面提到的替代解决方案
1. Use POST instead of GET;
2. Transform the List into a JSON string and pass it to the service.
确实不能将List
添加到MultiValuedMap
,因为它的impl 类MultivaluedMapImpl
具有接受字符串键和字符串值的能力。如下图所示
您仍然想做那件事而不是尝试以下代码。
控制器类
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) ;
客户端类
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;
希望这会对你有所帮助。
【讨论】:
最佳答案在这里!谢谢+1【参考方案4】:使用 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();
发布请求:
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();
【讨论】:
查看客户端资源的示例是我所需要的 :) 谢谢【参考方案5】:可以使用 queryParam 方法,将参数名称和一组值传递给它:
public WebTarget queryParam(String name, Object... values);
示例(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();
这将向以下 URL 发出请求:
http://localhost/path?param_name=paramVal1¶m_name=paramVal2
【讨论】:
以上是关于泽西岛客户端:如何添加列表作为查询参数的主要内容,如果未能解决你的问题,请参考以下文章