Cliente de Jersey: Cómo agregar una lista como parámetro de consulta

81

Estoy creando un cliente de Jersey para un servicio GET que tiene una lista como parámetro de consulta. De acuerdo con la documentación , es posible tener una Lista como parámetro de consulta (esta información también se encuentra en @QueryParam javadoc), compruébalo:

En general, el tipo de Java del parámetro de método puede:

  1. Sea un tipo primitivo;
  2. Tener un constructor que acepte un solo argumento de cadena;
  3. Tener un método estático llamado valueOf o fromString que acepte un solo argumento String (ver, por ejemplo, Integer.valueOf (String) y java.util.UUID.fromString (String)); o
  4. Sea List, Set o SortedSet, donde T satisface 2 o 3 arriba. La colección resultante es de solo lectura.

A veces, los parámetros pueden contener más de un valor para el mismo nombre. Si este es el caso, se pueden usar los tipos 4) para obtener todos los valores.

Sin embargo, no puedo averiguar cómo agregar un parámetro de consulta List usando el cliente Jersey.

Entiendo que las soluciones alternativas son:

  1. Utilice POST en lugar de GET;
  2. Transforma la lista en una cadena JSON y pásala al servicio.

El primero no es bueno, porque el verbo HTTP adecuado para el servicio es GET. Es una operación de recuperación de datos.

La segunda será mi opción si no puedes ayudarme. :)

También estoy desarrollando el servicio, por lo que puedo cambiarlo según sea necesario.

¡Gracias!

Actualizar

Código de cliente (usando 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>() {});
lsborg
fuente
1
¿Puedes dar el código de cliente de jersey aquí ...?
Yogesh Prajapati
1
yogesh, agregué el código del cliente.
lsborg
2
Si entiendo la declaración de su problema, puede pasar la lista de valores como parámetro de consulta agregando varios valores a la misma clave. Si "searchWrapper" es la clave y desea pasarle varios valores: cree una URL como esta: // YourURL? SearchWrapper = value1 & searchWrapper = value2 & searchWrapper = value3 puede ser que necesite insertar valores varias veces en la misma clave si su MultivaluedMap lo admite .
Thamme Gowda
1
¡Gracias, @ThammeGowda! No lo he probado, pero parece funcionar como javadoc MultivaluedMap para agregar estados de método: agregue un valor a la lista actual de valores para la clave proporcionada .
lsborg

Respuestas:

116

@GET admite Lista de cadenas

Configuración :
Java: 1.7
Versión de Jersey: 1.9

Recurso

@Path("/v1/test")

Subrecurso :

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

Caso de prueba de Jersey

@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());
}
Dharmi
fuente
1
Gracias. Me ayuda.
Sapikelio
60
Como una nota para los demás, si está escribiendo la URL directamente en un navegador, debe repetir el nombre del parámetro: ..? List = one & list = two & list = three
endian
2
¿Es esto realmente una lista / se garantiza que se respetará el orden? Dado que parece que es un mapa de
varios valores
Si. ? list = one & list = two & list = three no es tan útil. as list = one, two, three - es por eso que lo emparejo manualmente de cadena a lista ..List<String> argList = List.of(argString.split("\\s*,\\s*"))
ses
30

Si está enviando algo más que cadenas simples, le recomendaría usar un POST con un cuerpo de solicitud apropiado, o pasar la lista completa como una cadena JSON codificada apropiadamente. Sin embargo, con cadenas simples, solo necesita agregar cada valor a la URL de solicitud de manera adecuada y Jersey lo deserializará por usted. Entonces, dado el siguiente punto final de ejemplo:

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

Su cliente enviaría una solicitud correspondiente a:

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

Lo que resultaría en inputListser deserializado para contener los valores 'Hola', 'Quedarse' y 'Adiós'

Percepción
fuente
2
Gracias por tu respuesta Perception! Pero me gustaría saber si es posible hacer un GET con una lista como parámetro de consulta usando el cliente Jersey.
lsborg
1
¿Puede decirnos cómo crear dicha lista en el lado del cliente, ya que mis clientes son Android e iOS? Obviamente, no queremos crear key = value & key = value manuall
nilesh
¿y si envía list[0]=Hello&list[1]=Stay? como manejar eso?
user1735921
6

estoy de acuerdo con usted sobre las soluciones alternativas que mencionó anteriormente

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

y es cierto que no se puede añadir Lista MultiValuedMapcausa de su clase impl MultivaluedMapImpltienen capacidad de aceptar Cadena de clave y valor de cadena. que se muestra en la siguiente figura

ingrese la descripción de la imagen aquí

todavía quieres hacer esas cosas que intentar seguir el código.

Clase de controlador

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

Clase de cliente

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

Espero que esto te ayude.

Yogesh Prajapati
fuente
¡La mejor respuesta aquí! Gracias +1
Haramoz
3

Solicitud GET con parámetro de consulta 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();    
        }    
    }    
}

Solicitud de publicación:

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

        }    
    }    
}
vaquar khan
fuente
lo que necesitaba era ver un ejemplo de recurso de cliente :) gracias
Mobigital