it-swarm.com.de

Spring RestTemplate GET mit Parametern

Ich muss einen Aufruf von REST machen, der benutzerdefinierte Header und Abfrageparameter enthält. Ich setze meine HttpEntity nur mit den Kopfzeilen (ohne Körper) und verwende die RestTemplate.exchange()-Methode wie folgt:

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");

Map<String, String> params = new HashMap<String, String>();
params.put("msisdn", msisdn);
params.put("email", email);
params.put("clientVersion", clientVersion);
params.put("clientType", clientType);
params.put("issuerName", issuerName);
params.put("applicationName", applicationName);

HttpEntity entity = new HttpEntity(headers);

HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class, params);

Dies schlägt auf der Clientseite fehl, da der dispatcher servlet die Anforderung an einen Handler nicht auflösen kann. Nach dem Debuggen scheinen die Anforderungsparameter nicht gesendet zu werden.

Wenn ich mit einer POST einen Austausch mit einem Anfragetext und keinen Abfrageparametern durchführe, funktioniert das einwandfrei.

Hat jemand irgendwelche Ideen?

173
Elwood

OK, also bin ich ein Idiot und verwechsle Abfrageparameter mit URL-Parametern. Ich hatte irgendwie gehofft, dass es eine schönere Möglichkeit gibt, meine Abfrageparameter zu füllen, als einen hässlichen verketteten String, aber da sind wir. Es ist einfach ein Fall, bei dem die URL mit den richtigen Parametern erstellt wird. Wenn Sie es als String übergeben, übernimmt Spring die Codierung für Sie.

33
Elwood

Um URLs/Pfad/Parameter/usw. einfach zu bearbeiten, können Sie die Spring-Klasse UriComponentsBuilder verwenden. Es ist sauberer, dass Zeichenketten manuell verkettet werden, und kümmert sich um die URL-Kodierung für Sie:

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
        .queryParam("msisdn", msisdn)
        .queryParam("email", email)
        .queryParam("clientVersion", clientVersion)
        .queryParam("clientType", clientType)
        .queryParam("issuerName", issuerName)
        .queryParam("applicationName", applicationName);

HttpEntity<?> entity = new HttpEntity<>(headers);

HttpEntity<String> response = restTemplate.exchange(
        builder.toUriString(), 
        HttpMethod.GET, 
        entity, 
        String.class);
334
Christophe L

Die uriVariables werden auch in der Abfragezeichenfolge erweitert. Mit dem folgenden Aufruf werden beispielsweise Werte für Konto und Name erweitert:

restTemplate.exchange("http://my-rest-url.org/rest/account/{account}?name={name}",
    HttpMethod.GET,
    httpEntity,
    clazz,
    "my-account",
    "my-name"
);

die tatsächliche Anforderungs-URL wird also sein

http://my-rest-url.org/rest/account/my-account?name=my-name

Weitere Informationen finden Sie unter HierarchicalUriComponents.expandInternal (UriTemplateVariables) .. _. Die Version von Spring ist 3.1.3.

113
pavel

Ich habe etwas Ähnliches versucht, und das RoboSpice-Beispiel hat mir geholfen, es herauszufinden :

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", "application/json");

HttpEntity<String> request = new HttpEntity<>(input, createHeader());

String url = "http://awesomesite.org";
Uri.Builder uriBuilder = Uri.parse(url).buildUpon();
uriBuilder.appendQueryParameter(key, value);
uriBuilder.appendQueryParameter(key, value);
...

String url = uriBuilder.build().toString();

HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, request , String.class);
17
elBradford

Seit mindestens Spring 3 verwenden viele der UriComponentsBuilder-Methoden anstelle von RestTemplate zum Erstellen der URL (was ein wenig ausführlich ist) Platzhalter im Pfad für Parameter (nicht nur exchange).

Aus der Dokumentation:

Viele der RestTemplate-Methoden akzeptieren eine URI-Vorlage und einen URI Vorlagenvariablen, entweder als String vararg oder als Map<String,String>.

Zum Beispiel mit einer String vararg:

restTemplate.getForObject(
   "http://example.com/hotels/{hotel}/rooms/{room}", String.class, "42", "21");

Oder mit einem Map<String, String>:

Map<String, String> vars = new HashMap<>();
vars.put("hotel", "42");
vars.put("room", "21");

restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", 
    String.class, vars);

Referenz: https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#rest-resttemplate-uri

Wenn Sie sich das JavaDoc für RestTemplate ansehen und nach "URI-Vorlage" suchen, können Sie sehen, mit welchen Methoden Sie Platzhalter verwenden können.

10
dustin.schultz

Ich gehe von einem anderen Ansatz aus, Sie können dem zustimmen oder nicht, aber ich möchte die Kontrolle über die .properties-Datei anstelle von kompiliertem Java-Code

In der Datei application.properties

endpoint.url = https: // yourHost/resource? requestParam1 = {0} & requestParam2 = {1}

Java-Code geht hier, Sie können schreiben, ob Sie die Bedingung ändern möchten, um herauszufinden, ob die Endpunkt-URL in der .properties-Datei @PathVariable (enthält {}) oder @RequestParam (yourURL? Key = value) usw. enthält. Dann rufen Sie die Methode entsprechend auf. auf diese Weise seine Dynamik und nicht die Notwendigkeit, Änderungen in zukünftigen One-Stop-Shops zu kodieren ... 

Ich versuche hier mehr von der Idee als vom tatsächlichen Code zu geben ... versuchen Sie, eine generische Methode für @RequestParam und @PathVariable usw. zu schreiben ... und rufen Sie sie entsprechend auf, wenn sie benötigt wird 

  @Value("${endpoint.url}")
  private String endpointURL;
  // you can use variable args feature in Java
  public String requestParamMethodNameHere(String value1, String value2) {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate
           .getMessageConverters()
           .add(new MappingJackson2HttpMessageConverter());

    HttpHeaders headers = new HttpHeaders();
    headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
    HttpEntity<String> entity = new HttpEntity<>(headers);

    try {
      String formatted_URL = MessageFormat.format(endpointURL, value1, value2);
      ResponseEntity<String> response = restTemplate.exchange(
                    formatted_URL ,
                    HttpMethod.GET,
                    entity,
                    String.class);
     return response.getBody();
    } catch (Exception e) { e.printStackTrace(); }
3

Wenn Sie nicht-parametrisierte Parameter für RestTemplate übergeben, haben Sie eine Metrik für jeden einzelnen URL, den Sie übergeben, unter Berücksichtigung der Parameter. Sie möchten parametrisierte URLs verwenden:

http://my-url/action?param1={param1}&param2={param2}

anstatt

http://my-url/action?param1=XXXX&param2=YYYY

Im zweiten Fall erhalten Sie die UriComponentsBuilder-Klasse.

Eine Möglichkeit, das erste Verhalten zu implementieren, ist folgende:

Map<String, Object> params = new HashMap<>();
params.put("param1", "XXXX");
params.put("param2", "YYYY");

String url = "http://my-url/action?%s";

String parametrizedArgs = params.keySet().stream().map(k ->
    String.format("%s={%s}", k, k)
).collect(Collectors.joining("&"));

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> entity = new HttpEntity<>(headers);

restTemplate.exchange(String.format(url, parametrizedArgs), HttpMethod.GET, entity, String.class, params);
2
Dalton
public static void main(String[] args) {
         HttpHeaders httpHeaders = new HttpHeaders();
         httpHeaders.set("Accept", MediaType.APPLICATION_JSON_VALUE);
         final String url = "https://Host:port/contract/{code}";
         Map<String, String> params = new HashMap<String, String>();
         params.put("code", "123456");
         HttpEntity<?> httpEntity  = new HttpEntity<>(httpHeaders); 
         RestTemplate restTemplate  = new RestTemplate();
         restTemplate.exchange(url, HttpMethod.GET, httpEntity,String.class, params);
    }
0
Neeraj Gahlawat

Eine andere Lösung mit dem riComponentsBuilder (Konvertieren einer vorhandenen HashMap):

 HttpHeaders headers = new HttpHeaders();
 headers.set("Accept", "application/json");

 Map<String, String> params = new HashMap<>();
 params.put("msisdn", msisdn);
 params.put("email", email);
 params.put("clientVersion", clientVersion);
 params.put("clientType", clientType);
 params.put("issuerName", issuerName);
 params.put("applicationName", applicationName);

 HttpEntity entity = new HttpEntity(headers);

 UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
 for (Map.Entry<String, String> entry : params.entrySet()) {
     builder.queryParam(entry.getKey(), entry.getValue());
 }
 HttpEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, entity, String.class);
0
Ilya Lysenko

In Spring Web 4.3.6 sehe ich auch

public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)

Das bedeutet, dass Sie keine hässliche Karte erstellen müssen

Wenn Sie also diese URL haben

http://my-url/action?param1={param1}&param2={param2}

Sie können entweder tun

restTemplate.getForObject(url, Response.class, param1, param2)

oder

restTemplate.getForObject(url, Response.class, param [])
0
Kalpesh Soni
    String uri = http://my-rest-url.org/rest/account/{account};

    Map<String, String> uriParam = new HashMap<>();
    uriParam.put("account", "my_account");

    UriComponents builder = UriComponentsBuilder.fromHttpUrl(uri)
                .queryParam("pageSize","2")
                        .queryParam("page","0")
                        .queryParam("name","my_name").build();

    HttpEntity<String> requestEntity = new HttpEntity<>(null, getHeaders());

    ResponseEntity<String> strResponse = restTemplate.exchange(builder.toUriString(),HttpMethod.GET, requestEntity,
                        String.class,uriParam);

    //final URL: http://my-rest-url.org/rest/account/my_account?pageSize=2&page=0&name=my_name

RestTemplate: Dynamische URI mit UriComponents erstellen (URI-Variable und Request-Parameter)

0
Kripesh Bista