Клієнт Джерсі: Як додати список як параметр запиту


81

Я створюю клієнт Джерсі для служби GET, що має параметр "Список" як запит. Згідно з документацією , можна мати List як параметр запиту (ця інформація також знаходиться на @QueryParam javadoc), перевірте це:

Загалом тип Java параметра параметра може:

  1. Бути примітивним типом;
  2. Мати конструктор, який приймає один аргумент String;
  3. Мати статичний метод з іменем valueOf або fromString, який приймає один аргумент String (див., Наприклад, Integer.valueOf (String) та java.util.UUID.fromString (String)); або
  4. Будьте списком, встановіть або відсортуйте, де T відповідає 2 або 3 вище. Отримана колекція доступна лише для читання.

Іноді параметри можуть містити більше одного значення для одного і того ж імені. Якщо це так, тоді типи 4) можуть бути використані для отримання всіх значень.

Однак я не можу зрозуміти, як додати параметр запиту List, використовуючи клієнт Джерсі.

Я розумію, що альтернативними рішеннями є:

  1. Використовуйте POST замість GET;
  2. Перетворіть Список у рядок 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>() {});

1
Ви можете дати тут код клієнта джерсі ...
Йогеш Праджапаті

1
yogesh, я додав код клієнта.
lsborg

2
Якщо я розумію вашу заяву про проблему, ви можете передати список значень як параметр запиту, додавши кілька значень до одного ключа. Якщо "searchWrapper" є ключем, і ви хочете передати йому кілька значень: побудуйте URL-адресу так: // YourURL? SearchWrapper = value1 & searchWrapper = value2 & searchWrapper = value3, можливо, вам доведеться вставляти значення кілька разів в один і той же ключ, якщо ваша MultivaluedMap це підтримує .
Thamme Gowda

1
Дякую, @ThammeGowda! Я його не тестував, але, схоже, він робить фокус, оскільки у Java Java Multi-Value Map вказано метод додавання: Додайте значення до поточного списку значень для наданого ключа .
Ісборг

Відповіді:


119

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

1
Дякую. Мені це допомагає.
Сапікеліо,

62
Як примітка для інших, якщо ви пишете URL-адресу безпосередньо у браузері, ви повинні повторити назву параметра: ..? List = one & list = two & list = three
endian

2
Це справді список / чи гарантовано дотримання порядку? Зважаючи на те, що це багатозначна карта, яку Джерсі повертає як список, мені цікаво, чи можуть бути проблеми із збереженням порядку
hayduke

так ? list = one & list = two & list = three не так корисно. як список = один, два, три - ось чому я переглядаю його вручну від рядка до списку ..List<String> argList = List.of(argString.split("\\s*,\\s*"))
ses

30

Якщо ви надсилаєте що-небудь, крім простих рядків, я б рекомендував використовувати POST із відповідним тілом запиту або передати весь список як відповідним чином закодований рядок JSON. Однак за допомогою простих рядків вам просто потрібно додати кожне значення до URL-адреси запиту, і Джерсі десеріалізує його для вас. Отже, враховуючи наступний приклад кінцевої точки:

@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=Прощання

Що призведе до inputListдесериалізації, щоб містити значення "Привіт", "Залишитися" та "До побачення"


2
Дякуємо за вашу відповідь Сприйняття! Але я хотів би з'ясувати, чи можна зробити GET із списком як параметром запиту, використовуючи клієнт Джерсі.
lsborg

1
Підкажіть, будь ласка, як створити такий список на стороні клієнта, оскільки моїми клієнтами є android та ios. Очевидно, що ми не хочемо створювати мануал key = value & key = value
nilesh

що якщо надсилає list[0]=Hello&list[1]=Stay? як цим керувати?
user1735921

6

Я згоден з вами щодо альтернативних рішень, про які ви згадали вище

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

і це правда , що ви не можете додати Listдо MultiValuedMapз - за його здійс класом 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
Харамоз

3

ОТРИМАТИ запит за допомогою 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();    
        }    
    }    
}

Запит на публікацію:

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

        }    
    }    
}

бачачи приклад ресурсу Клієнта, було те, що мені потрібно :) дякую
Mobigital

0

Можна використати метод queryParam, передавши йому ім'я параметра та масив значень:

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

Приклад (джерсі-клієнт 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&param_name=paramVal2
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.