如何在 Spring RestTemplate 请求上设置“Accept:”标头?
Posted
技术标签:
【中文标题】如何在 Spring RestTemplate 请求上设置“Accept:”标头?【英文标题】:How to set an "Accept:" header on Spring RestTemplate request? 【发布时间】:2013-10-14 20:17:34 【问题描述】:我想在使用 Spring 的 RestTemplate
发出的请求中设置 Accept:
的值。
这是我的 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;
这是我的 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);
这对我有用;我从服务器端得到一个 JSON 字符串。
我的问题是:我如何指定 Accept:
标头(例如 application/json
,application/xml
, ... )和请求方法(例如 GET
,POST
, ... )当我使用休息模板?
【问题讨论】:
【参考方案1】:我建议使用接受HttpEntity
的exchange
方法之一,您也可以为其设置HttpHeaders
。 (您也可以指定要使用的 HTTP 方法。)
例如,
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);
我更喜欢这个解决方案,因为它是强类型的,即。 exchange
需要 HttpEntity
。
但是,您也可以将 HttpEntity
作为 request
参数传递给 postForObject
。
HttpEntity<String> entity = new HttpEntity<>("body", headers);
restTemplate.postForObject(url, entity, String.class);
RestTemplate#postForObject
Javadoc 中提到了这一点。
request
参数可以是HttpEntity
,以便添加额外的 请求的 HTTP 标头。
【讨论】:
【参考方案2】:您可以在 RestTemplate 中设置一个拦截器“ClientHttpRequestInterceptor”,以避免每次发送请求时都设置标头。
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);
然后
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 有一个 HttpHeaderInterceptor,所以我们不需要创建自己的 ClientHttpRequestInterceptor 实现。 由于某种原因,HttpHeaderInterceptor 仅在 spring-boot-devtools 中。所以我们还是要自己实现ClientHttpRequestInterceptor。我认为应该把它移到 spring-web 中。 将默认标头添加到设置为其余模板的 ClientHttpRequestFactory 而不是添加拦截器是否更好?附:您应该在一个单独的问题中添加您的答案,因为这涉及默认标题。不得不寻找一段时间才能到达这里! 如果有两个服务使用我们必须调用的两个 diff id /pass,那么这个 resttemplate 级别的拦截器级别太高了吧?您在请求级别需要这个 - 通常 RestTemplate 是 Spring Boot 配置中的 @Bean【参考方案3】:如果像我一样,您很难找到一个使用带有基本身份验证的标头和其余模板交换 API 的示例,这就是我最终解决的问题...
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());
【讨论】:
【参考方案4】:使用 RestTemplate 调用 RESTful API
示例 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);
示例 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()
getRequestJson
方法创建一个 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;
【讨论】:
【参考方案5】:不创建HttpHeaders
的短解决方案:
RequestEntity<Void> request = RequestEntity.post(URI.create(url))
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
// any other headers
.header("PRIVATE-TOKEN", "token")
.build();
ResponseEntity<String> response = restTemplate.exchange(request, String.class);
return response.getBody();
【讨论】:
最有用,简洁和整体干净的答案。谢谢 我不明白为什么在您的本地环境中添加工作标头需要这样的 PIA,这就像我在网上看到的所有其他方法一样不起作用......跨度> 【参考方案6】:这是一个简单的答案。希望它可以帮助某人。
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;
【讨论】:
您的代码将使用 Spring Devtools 作为生产依赖项(通过导入 org.springframework.boot.devtools.remote.client.HttpHeaderInterceptor)...以上是关于如何在 Spring RestTemplate 请求上设置“Accept:”标头?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 spring 记录 RestTemplate 请求和响应?
如何在 Spring RestTemplate 请求上设置“Accept:”标头?
如何使用 OAuth2RestTemplate + Spring 4?
如何在 Java Spring boot 中模拟 RestTemplate?
如何使用 RestTemplate 在 Spring MVC 应用程序中访问来自(来自 Spring RESTful 服务)的巨大 JSON