web-dev-qa-db-fra.com

codage de l'url du reste du printemps

J'essaie de faire un appel de repos simple avec ressorts resttemplate:

private void doLogout(String endpointUrl, String sessionId) {
    template.getForObject("http://{enpointUrl}?method=logout&session={sessionId}", Object.class,
            endpointUrl, sessionId);
}

Où la variable endpointUrl contient quelque chose comme service.hôte.com/api/service.php

Malheureusement, mon appel génère un org.springframework.web.client.ResourceAccessException: erreur d'E/S: service.Host.com% 2Fapi% 2Fservice.php

Donc, spring semble encoder ma chaîne endpointUrl avant lors de la création de l'URL. Existe-t-il un moyen simple d'empêcher le printemps de faire cela?

Cordialement

8
user1145874

Il n'y a pas de moyen facile de faire cela. Les variables URI sont généralement destinées à un élément de chemin ou à un paramètre de chaîne de requête. Vous essayez de faire passer plusieurs éléments. 

Une solution de contournement consiste à utiliser UriTemplate pour générer l'URL avec les variables URI telles que vous les avez, puis le décoder par URL et le transmettre à votre RestTemplate.

String url = "http://{enpointUrl}?method=logout&session={sessionId}";
URI expanded = new UriTemplate(url).expand(endpointUrl, sessionId); // this is what RestTemplate uses 
url = URLDecoder.decode(expanded.toString(), "UTF-8"); // Java.net class
template.getForObject(url, Object.class);
13

Cela dépend de la version de Spring que vous utilisez. Si votre version est trop ancienne, par exemple la version 3.0.6.RELEASE, vous ne disposerez pas de la même facilité que UriComponentsBuilder avec votre fichier jar spring-web.

Ce dont vous avez besoin est d'empêcher Spring RestTemplate de coder l'URL. Ce que tu pourrais faire c'est:

import Java.net.URI;

StringBuilder builder = new StringBuilder("http://");
builder.append(endpointUrl);
builder.append("?method=logout&session=");
builder.append(sessionId);

URI uri = URI.create(builder.toString());
restTemplate.getForObject(uri, Object.class);

Je l'ai testé avec Spring version 3.0.6.LELEASE, et cela fonctionne. 

Dans un mot, au lieu d'utiliser restTemplate.getForObject(String url, Object.class), utilisez restTemplate.getForObject(Java.net.URI uri, Object.class)

Voir la section rest-resttemplate-uri du document Spring

6
Yuci

Vous pouvez utiliser la variante surchargée qui utilise un fichier Java.net.URI à la place getForObject public (URL URI, Classe responseType) lève RestClientException

De La propre documentation de Spring

UriComponents uriComponents =
    UriComponentsBuilder.fromUriString("http://example.com/hotels/{hotel}/bookings/{booking}").build()
        .expand("42", "21")
        .encode();

URI uri = uriComponents.toUri();
3
Not a code monkey

Exemple complet avec en-têtes, corps, pour tout HttpMethod et ResponseType pourrait ressembler à

String url = "http://google.com/{path}?param1={param1Value}&param2={param2Value}";
Object body = null;
HttpEntity request = new HttpEntity(body, new HttpHeaders());

Map<String, String> uriVariables = new HashMap<>();
uriVariables.put("path", "search");
uriVariables.put("param1Value", "value1");
uriVariables.put("param2Value", "value2");

ResponseEntity<Void> responseEntity = restTemplate.exchange(url, HttpMethod.POST, request, Void.class, uriVariables)
//responseEntity.getBody()

En fait, il utilisera la même méthode UriTemplate et expand

0
Geniy