Wie setze ich einen "Accept:" - Header für eine Spring RestTemplate-Anforderung?

193

Ich möchte den Wert von Accept:in einer Anfrage festlegen, die ich mit Spring's mache RestTemplate.

Hier ist mein Code für die Bearbeitung von Spring-Anfragen

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

und hier ist mein Java REST Client:

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

Das funktioniert bei mir; Ich erhalte eine JSON-Zeichenfolge von der Serverseite.

Meine Frage ist: wie ich die angeben Accept:Header (zB application/json, application/xml, ...) und Anforderungsmethode (zB GET, POST...) , wenn ich RestTemplate verwenden?

edaklij
quelle

Antworten:

353

Ich schlage vor, eine der exchangeMethoden zu verwenden, die eine akzeptiert, HttpEntityfür die Sie auch die festlegen können HttpHeaders. (Sie können auch die HTTP-Methode angeben, die Sie verwenden möchten.)

Beispielsweise,

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

Ich bevorzuge diese Lösung, weil sie stark typisiert ist, dh. exchangeerwartet eine HttpEntity.

Sie können dies jedoch auch HttpEntityals requestArgument an übergeben postForObject.

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

Dies wird im RestTemplate#postForObjectJavadoc erwähnt .

Der requestParameter kann a HttpEntitysein, um der Anforderung zusätzliche HTTP-Header hinzuzufügen .

Sotirios Delimanolis
quelle
130

Sie können in Ihrem RestTemplate einen Interceptor "ClientHttpRequestInterceptor" festlegen, um zu vermeiden, dass der Header jedes Mal festgelegt wird, wenn Sie eine Anforderung senden.

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

Dann

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

RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(interceptors);
Ammar
quelle
Spring Boot 1.3 verfügt über einen HttpHeaderInterceptor, sodass wir keine eigene Implementierung von ClientHttpRequestInterceptor erstellen müssen.
whistling_marmot
2
Aus irgendeinem Grund ist HttpHeaderInterceptor nur in Spring-Boot-Devtools enthalten. Wir müssen ClientHttpRequestInterceptor also noch selbst implementieren. Ich denke, es sollte in Spring-Web verschoben werden.
whistling_marmot
2
Ist es besser, Standard-Header zu ClientHttpRequestFactory hinzuzufügen, die auf die Restvorlage festgelegt sind, anstatt Interceptors hinzuzufügen? PS Sie sollten Ihre Antwort in einer separaten Frage hinzufügen, da dies Standardheader behandelt. Musste eine Weile suchen, um hierher zu gelangen!
sbsatter
Wenn es zwei Dienste gibt, die zwei diff id / pass verwenden, die wir aufrufen müssen, ist dieser Interceptor auf Resttemplate-Ebene zu hoch, oder? Sie benötigen dies auf Anfrageebene - im Allgemeinen ist RestTemplate eine @ Bean im Frühjahr Boot-Konfiguration
Kalpesh Soni
21

Wenn Sie wie ich Schwierigkeiten hatten, ein Beispiel zu finden, das Header mit Basisauthentifizierung und der API zum Austausch von Restvorlagen verwendet, habe ich dies schließlich herausgefunden ...

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
quelle
11

Aufrufen einer RESTful-API mit RestTemplate

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

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

Die getRequestJsonMethode erstellt ein JSON-Objekt:

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
quelle
4

Hier ist eine einfache Antwort. Hoffe es hilft jemandem.

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
quelle
10
Ihr Code verwendet Spring Devtools als Produktionsabhängigkeit (durch Importieren von org.springframework.boot.devtools.remote.client.HttpHeaderInterceptor) ...
snorbi