Jersey-Client: Hinzufügen einer Liste als Abfrageparameter

81

Ich erstelle einen Jersey-Client für einen GET-Dienst, der eine Liste als Abfrageparameter enthält. Laut Dokumentation ist es möglich, eine Liste als Abfrageparameter zu haben (diese Informationen finden Sie auch unter @QueryParam javadoc). Schauen Sie sich das an:

Im Allgemeinen kann der Java-Typ des Methodenparameters:

  1. Sei ein primitiver Typ;
  2. Haben Sie einen Konstruktor, der ein einzelnes String-Argument akzeptiert;
  3. Haben Sie eine statische Methode namens valueOf oder fromString, die ein einzelnes String-Argument akzeptiert (siehe z. B. Integer.valueOf (String) und java.util.UUID.fromString (String)); oder
  4. Sei List, Set oder SortedSet, wobei T 2 oder 3 oben erfüllt. Die resultierende Sammlung ist schreibgeschützt.

Manchmal können Parameter mehr als einen Wert für denselben Namen enthalten. Wenn dies der Fall ist, können die Typen 4) verwendet werden, um alle Werte zu erhalten.

Ich kann jedoch nicht herausfinden, wie ein Listenabfrageparameter mit dem Jersey-Client hinzugefügt wird.

Ich verstehe, dass alternative Lösungen sind:

  1. Verwenden Sie POST anstelle von GET.
  2. Transformieren Sie die Liste in eine JSON-Zeichenfolge und übergeben Sie sie an den Dienst.

Das erste ist nicht gut, weil das richtige HTTP-Verb für den Dienst GET ist. Es ist eine Datenabrufoperation.

Der zweite ist meine Option, wenn Sie mir nicht helfen können. :) :)

Ich entwickle den Service auch, damit ich ihn nach Bedarf ändern kann.

Vielen Dank!

Aktualisieren

Client-Code (mit 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
quelle
1
Können Sie hier Trikot Client Code geben ...
Yogesh Prajapati
1
Yogesh, ich habe den Client-Code hinzugefügt.
lsborg
2
Wenn ich Ihre Problemstellung verstehe, können Sie eine Werteliste als Abfrageparameter übergeben, indem Sie demselben Schlüssel mehrere Werte hinzufügen. Wenn "searchWrapper" der Schlüssel ist und Sie mehrere Werte an ihn übergeben möchten: Erstellen Sie eine URL wie folgt: // YourURL? SearchWrapper = value1 & searchWrapper = value2 & searchWrapper = value3 Möglicherweise müssen Sie Werte mehrmals in denselben Schlüssel einfügen, wenn Ihre MultivaluedMap dies unterstützt .
Thamme Gowda
1
Danke, @ThammeGowda! Ich habe es nicht getestet, aber es scheint den Trick als MultivaluedMap-Javadoc für das Hinzufügen von Methodenzuständen zu tun : Fügen Sie der aktuellen Werteliste für den angegebenen Schlüssel einen Wert hinzu .
lsborg

Antworten:

116

@GET unterstützt List of Strings

Setup :
Java: 1.7
Jersey Version: 1.9

Ressource

@Path("/v1/test")

Unterressource :

// 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 Testfall

@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
quelle
1
Danke. Es hilft mir.
Sapikelio
60
Nur als Hinweis für andere, wenn Sie die URL direkt in einem Browser schreiben, müssen Sie den Parameternamen wiederholen: ..? List = one & list = two & list = three
endian
2
Ist das wirklich eine Liste / wird die Reihenfolge garantiert eingehalten? Angesichts der Tatsache, dass es sich um eine mehrwertige Karte handelt, die Jersey als Liste zurückgibt, frage ich mich, ob es Probleme geben kann, wenn die Ordnung nicht erhalten bleibt
Hayduke,
Ja. ? list = eins & list = zwei & list = drei ist nicht so nützlich. als Liste = eins, zwei, drei - deshalb analysiere ich es manuell von Zeichenfolge zu Liste.List<String> argList = List.of(argString.split("\\s*,\\s*"))
ses
30

Wenn Sie etwas anderes als einfache Zeichenfolgen senden, würde ich empfehlen, einen POST mit einem geeigneten Anforderungshauptteil zu verwenden oder die gesamte Liste als entsprechend codierte JSON-Zeichenfolge zu übergeben. Mit einfachen Zeichenfolgen müssen Sie jedoch nur jeden Wert entsprechend an die Anforderungs-URL anhängen, und Jersey deserialisiert ihn für Sie. Geben Sie also den folgenden Beispielendpunkt an:

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

Ihr Kunde würde eine Anfrage senden, die entspricht:

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

Dies würde dazu führen inputList, dass die Werte "Hallo", "Bleiben" und "Auf Wiedersehen" deserialisiert werden.

Wahrnehmung
quelle
2
Danke für deine Antwort Wahrnehmung! Ich möchte jedoch herausfinden, ob es möglich ist, mit dem Jersey-Client ein GET mit einer Liste als Abfrageparameter durchzuführen.
lsborg
1
Können Sie bitte sagen, wie man eine solche Liste auf der Client-Seite erstellt, da meine Kunden Android und iOS sind? Offensichtlich wollen wir nicht key = value & key = value manuall
nilesh
Was ist, wenn es sendet list[0]=Hello&list[1]=Stay? wie geht das?
user1735921
6

Ich stimme Ihnen in Bezug auf alternative Lösungen zu, die Sie oben erwähnt haben

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

und es ist wahr, dass Sie aufgrund seiner impl-Klasse nicht hinzufügen können List, MultiValuedMapob MultivaluedMapImplString-Schlüssel und String-Wert akzeptiert werden können. Dies ist in der folgenden Abbildung dargestellt

Geben Sie hier die Bildbeschreibung ein

Trotzdem möchten Sie diese Dinge tun, als den folgenden Code zu versuchen.

Controller-Klasse

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-Klasse

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

hoffe das hilft dir

Yogesh Prajapati
quelle
Beste Antwort hier! Danke +1
Haramoz
3

GET-Anforderung mit JSON-Abfrageparam

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 Anfrage:

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
quelle
Ein Beispiel für eine Client-Ressource zu sehen war das, was ich brauchte :) Danke
Mobigital