Come impostare un'intestazione "Accept:" sulla richiesta Spring RestTemplate?


194

Voglio impostare il valore di Accept:in una richiesta che sto facendo usando Spring's RestTemplate.

Ecco il mio codice di gestione delle richieste di primavera

@RequestMapping(
    value= "/uom_matrix_save_or_edit", 
    method = RequestMethod.POST,
    produces="application/json"
)
public @ResponseBody ModelMap uomMatrixSaveOrEdit(
    ModelMap model,
    @RequestParam("parentId") String parentId
){
    model.addAttribute("attributeValues",parentId);
    return model;
}

ed ecco il mio client Java REST:

public void post(){
    MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
    params.add("parentId", "parentId");
    String result = rest.postForObject( url, params, String.class) ;
    System.out.println(result);
}

Questo funziona per me; Ricevo una stringa JSON dal lato server.

La mia domanda è: come posso specificare l' Accept:intestazione (ad es application/json. application/xml, ...) e il metodo di richiesta (ad es GET. POST, ...) quando utilizzo RestTemplate?

Risposte:


355

Suggerisco di utilizzare uno dei exchangemetodi che accetta un HttpEntityper cui è anche possibile impostare il HttpHeaders. (È inoltre possibile specificare il metodo HTTP che si desidera utilizzare.)

Per esempio,

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

HttpEntity<String> entity = new HttpEntity<>("body", headers);

restTemplate.exchange(url, HttpMethod.POST, entity, String.class);

Preferisco questa soluzione perché è fortemente tipizzata, cioè. exchangesi aspetta un HttpEntity.

Tuttavia, puoi anche passarlo HttpEntitycome requestargomento a postForObject.

HttpEntity<String> entity = new HttpEntity<>("body", headers);
restTemplate.postForObject(url, entity, String.class); 

Questo è menzionato nel RestTemplate#postForObjectJavadoc .

Il requestparametro può essere HttpEntitya per aggiungere ulteriori intestazioni HTTP alla richiesta .


132

È possibile impostare un intercettore "ClientHttpRequestInterceptor" in RestTemplate per evitare di impostare l'intestazione ogni volta che si invia una richiesta.

public class HeaderRequestInterceptor implements ClientHttpRequestInterceptor {

        private final String headerName;

        private final String headerValue;

        public HeaderRequestInterceptor(String headerName, String headerValue) {
            this.headerName = headerName;
            this.headerValue = headerValue;
        }

        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
            request.getHeaders().set(headerName, headerValue);
            return execution.execute(request, body);
        }
    }

Poi

List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
interceptors.add(new HeaderRequestInterceptor("Accept", MediaType.APPLICATION_JSON_VALUE));

RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(interceptors);

Spring Boot 1.3 ha un HttpHeaderInterceptor, quindi non è necessario creare la nostra implementazione di ClientHttpRequestInterceptor.
whistling_marmot

2
Per qualche motivo, HttpHeaderInterceptor è solo in spring-boot-devtools. Quindi dobbiamo ancora implementare ClientHttpRequestInterceptor da soli. Penso che dovrebbe essere spostato in primavera-web.
whistling_marmot,

2
È meglio aggiungere le intestazioni predefinite al clientHttpRequestFactory impostato sul modello restante invece di aggiungere intercettori? PS dovresti aggiungere la tua risposta in una domanda separata poiché si tratta di intestazioni predefinite. Ho dovuto cercare un po 'per raggiungere qui!
sbsatter,

se ci sono due servizi che usano due ID / pass diff che dobbiamo chiamare, questo intercettore a livello di modello è di livello troppo alto, giusto? ne hai bisogno a livello di richiesta - generalmente RestTemplate è un @Bean nella configurazione dello stivale primaverile
Kalpesh Soni

21

Se, come me, hai faticato a trovare un esempio che utilizza le intestazioni con autenticazione di base e l'API di scambio del modello rimanente, questo è quello che ho finalmente elaborato ...

private HttpHeaders createHttpHeaders(String user, String password)
{
    String notEncoded = user + ":" + password;
    String encodedAuth = Base64.getEncoder().encodeToString(notEncoded.getBytes());
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.add("Authorization", "Basic " + encodedAuth);
    return headers;
}

private void doYourThing() 
{
    String theUrl = "http://blah.blah.com:8080/rest/api/blah";
    RestTemplate restTemplate = new RestTemplate();
    try {
        HttpHeaders headers = createHttpHeaders("fred","1234");
        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
        ResponseEntity<String> response = restTemplate.exchange(theUrl, HttpMethod.GET, entity, String.class);
        System.out.println("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
    }
    catch (Exception eek) {
        System.out.println("** Exception: "+ eek.getMessage());
    }
}

11

Chiamare un'API RESTful utilizzando RestTemplate

Esempio 1:

RestTemplate restTemplate = new RestTemplate();
// Add the Jackson message converter
restTemplate.getMessageConverters()
                .add(new MappingJackson2HttpMessageConverter());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Basic XXXXXXXXXXXXXXXX=");
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
restTemplate.getInterceptors()
                .add(new BasicAuthorizationInterceptor(USERID, PWORD));
String requestJson = getRequetJson(Code, emailAddr, firstName, lastName);
response = restTemplate.postForObject(URL, requestJson, MYObject.class);
        

Esempio 2:

RestTemplate restTemplate = new RestTemplate();
String requestJson = getRequetJson(code, emil, name, lastName);
HttpHeaders headers = new HttpHeaders();
String userPass = USERID + ":" + PWORD;
String authHeader =
    "Basic " + Base64.getEncoder().encodeToString(userPass.getBytes());
headers.set(HttpHeaders.AUTHORIZATION, authHeader);
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity<String> request = new HttpEntity<String>(requestJson, headers);
ResponseEntity<MyObject> responseEntity;
responseEntity =
    this.restTemplate.exchange(URI, HttpMethod.POST, request, Object.class);
responseEntity.getBody()

Il getRequestJsonmetodo crea un oggetto JSON:

private String getRequetJson(String Code, String emailAddr, String name) {
    ObjectMapper mapper = new ObjectMapper();
    JsonNode rootNode = mapper.createObjectNode();
    ((ObjectNode) rootNode).put("code", Code);
    ((ObjectNode) rootNode).put("email", emailAdd);
    ((ObjectNode) rootNode).put("firstName", name);
    String jsonString = null;
    try {
        jsonString = mapper.writerWithDefaultPrettyPrinter()
                               .writeValueAsString(rootNode);
    }
    catch (JsonProcessingException e) {
        e.printStackTrace();
    }
    return jsonString;
}

4

Ecco una risposta semplice. Spero che aiuti qualcuno.

import org.springframework.boot.devtools.remote.client.HttpHeaderInterceptor;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;


public String post(SomeRequest someRequest) {
    // create a list the headers 
    List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
    interceptors.add(new HttpHeaderInterceptor("Accept", MediaType.APPLICATION_JSON_VALUE));
    interceptors.add(new HttpHeaderInterceptor("ContentType", MediaType.APPLICATION_JSON_VALUE));
    interceptors.add(new HttpHeaderInterceptor("username", "user123"));
    interceptors.add(new HttpHeaderInterceptor("customHeader1", "c1"));
    interceptors.add(new HttpHeaderInterceptor("customHeader2", "c2"));
    // initialize RestTemplate
    RestTemplate restTemplate = new RestTemplate();
    // set header interceptors here
    restTemplate.setInterceptors(interceptors);
    // post the request. The response should be JSON string
    String response = restTemplate.postForObject(Url, someRequest, String.class);
    return response;
}

10
Il tuo codice utilizzerà Spring Devtools come dipendenza dalla produzione (importando org.springframework.boot.devtools.remote.client.HttpHeaderInterceptor) ...
snorbi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.