2011-11-28 30 views
123

Tengo que hacer una llamada REST que incluya encabezados personalizados y parámetros de consulta. Me puse mi HttpEntity con sólo las cabeceras (sin cuerpo) y utilizo el método RestTemplate.exchange() de la siguiente manera:Spring RestTemplate GET con los parámetros

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

Esta falla al final del cliente con el servlet despachador ser incapaz de resolver la solicitud a una entrenador de animales. Havinf lo depuró, parece que los parámetros de solicitud no se envían.

Cuando realizo un intercambio con un POST utilizando un Cuerpo de solicitud y sin parámetros de consulta, funciona muy bien.

¿Alguien tiene alguna idea?

Respuesta

30

OK, así que estoy siendo un idiota y estoy confundiendo los parámetros de consulta con los parámetros de la URL. Esperaba que hubiera una manera más agradable de completar mis parámetros de consulta en lugar de una cadena concatenada fea, pero ahí estamos. Simplemente es un caso de construir la URL con los parámetros correctos. Si lo pasa como un String Spring también se encargará de la codificación por usted.

+0

¿funcionó para usted? Seguí el mismo enfoque de usar UriComponentsBuilder pero, en la URL de destino, cuando hago un request.getAttribute(), obtengo nulo. – yathirigan

+0

Vea arriba: https://stackoverflow.com/a/16676827 – Marc

77

Las uriVariables también se expanden en la cadena de consulta. Por ejemplo, la siguiente llamada se expandirá valores tanto, cuenta y nombre:

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

por lo que la solicitud de URL real será

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

Mira HierarchicalUriComponents.expandInternal (UriTemplateVariables) para más detalles. La versión de Spring es 3.1.3.

+7

Wow, esto no fue en absoluto obvio de los documentos. – Deadron

+0

Gracias - Solución muy simple –

15

estaba intentando algo similar, y the RoboSpice example helped me work it out:

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

para manipular fácilmente las direcciones URL/ruta/params/etc, puede utilizar la clase de la primavera UriComponentsBuilder. Es más limpio que las cadenas de concatenación de forma manual y que se encarga de la codificación URL para usted:

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.build().encode().toUri(), 
     HttpMethod.GET, 
     entity, 
     String.class); 
+4

Un gran consejo. Sólo cambiado '' 'exchange''' a' '' getForEntity''': '' 'restTemplate.getForEntity;' '' por simplicidad (builder.build() codificar() Touri(), String.class..). –

+6

@ FernandoM.Pinheiro: Está en lo correcto, pero si espera un tipo genérico en la respuesta, entonces necesita usar 'exchange' y proporcionar' ParameterizedTypeReference'. El ejemplo puede ser aún más simplificada, sin embargo, la sustitución de 'builder.build(). Codificar(). Touri()' 'con builder.toUriString()'. – mirzmaster

+0

@Christophe L ¿Puede mostrar cómo puedo recibir estos parámetros de cadena en el servidor? – KJEjava48

2

tomo enfoque diferente, puede estar de acuerdo o no, pero quiero controlar desde el archivo .properties en lugar de código Java compilado

presentar

application.properties interior

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

código

Java va aquí, se puede escribir o cambiar si la condición para averiguar si endpo int URL en el archivo .properties tiene @PathVariable (contiene {}) o @RequestParam (yourURL? key = value) etc ... luego invoca el método en consecuencia ... de esta manera es dinámico y no necesita cambiar el código en una ventanilla única futura ...

estoy tratando de dar más de la idea de código real aquí ... tratar de escribir cada método genérico para @RequestParam y @PathVariable etc ... luego llamar a consecuencia cuando sea necesario

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