Como definir um cabeçalho "Accept:" na solicitação Spring RestTemplate?

193

Quero definir o valor de Accept:em uma solicitação que estou fazendo usando o Spring RestTemplate.

Aqui está o meu código de manipulação de solicitações do Spring

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

e aqui está o meu cliente 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);
}

Isso funciona para mim; Eu recebo uma string JSON do lado do servidor.

A minha pergunta é: como posso especificar o Accept:cabeçalho (por exemplo application/json, application/xml...) e método de solicitação (por exemplo GET, POST...) quando eu uso RestTemplate?

edaklij
fonte

Respostas:

353

Sugiro usar um dos exchangemétodos que aceita um HttpEntitypara o qual você também pode definir o HttpHeaders. (Você também pode especificar o método HTTP que deseja usar.)

Por exemplo,

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

Eu prefiro esta solução porque é fortemente tipada, ou seja. exchangeespera um HttpEntity.

No entanto, você também pode passar isso HttpEntitycomo requestargumento para postForObject.

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

Isso é mencionado no RestTemplate#postForObjectJavadoc .

O requestparâmetro pode ser a HttpEntitypara adicionar cabeçalhos HTTP adicionais à solicitação .

Sotirios Delimanolis
fonte
130

Você pode definir um interceptador "ClientHttpRequestInterceptor" em seu RestTemplate para evitar definir o cabeçalho toda vez que você enviar uma solicitação.

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

Então

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

RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(interceptors);
Ammar
fonte
O Spring Boot 1.3 possui um HttpHeaderInterceptor, portanto, não precisamos criar nossa própria implementação do ClientHttpRequestInterceptor.
whistling_marmot
2
Por alguma razão, o HttpHeaderInterceptor está apenas no spring-boot-devtools. Portanto, ainda temos que implementar ClientHttpRequestInterceptor. Eu acho que deveria ser movido para a web da primavera.
whistling_marmot
2
É melhor adicionar cabeçalhos padrão ao ClientHttpRequestFactory definido para o modelo restante em vez de adicionar interceptores? PS: você deve adicionar sua resposta em uma pergunta separada, pois isso lida com os cabeçalhos padrão. Tinha que procurar um tempo para chegar aqui!
Sbatter
se existem dois serviços que usam dois diff id / pass que precisamos chamar, esse interceptador no nível resttemplate é muito alto, certo? você precisa deste nível pedido - geralmente RestTemplate é um @Bean na configuração de inicialização primavera
Kalpesh Soni
21

Se, como eu, você se esforçou para encontrar um exemplo que use cabeçalhos com autenticação básica e a API de troca de modelos restantes, é isso que finalmente resolvi ...

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());
    }
}
Dave
fonte
11

Chamando uma API RESTful usando RestTemplate

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

Exemplo 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()

O getRequestJsonmétodo cria um objeto 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;
}
vaquar khan
fonte
4

Aqui está uma resposta simples. Espero que ajude alguém.

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;
}
Tunde Michael
fonte
10
Seu código irá usar Primavera Devtools como uma dependência de produção (por meio da importação org.springframework.boot.devtools.remote.client.HttpHeaderInterceptor) ...
snorbi