使用自定义标头的Resttemplate GET请求

8

我需要发送一个包含头部信息Content-Type: application/camiant-msr-v2.0+xml的GET请求。我期望从服务器端收到一个XML格式的响应。 我使用Postman测试了这个请求和响应,一切都很顺利。但是当我尝试在Spring中使用RestTemplate时,我总是得到一个400错误的响应。Spring抛出的异常如下:

Jul 09, 2016 12:53:38 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [/smp] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request] with root cause
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:641)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:597)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:557)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:475)

我的代码:

MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.add("Content-Type", "application/camiant-msr-v2.0+xml");

HttpEntity<?> entity = new HttpEntity<Object>(headers);
log.debug("request headers: " + entity.getHeaders());
ResponseEntity<String> response = restTemplate.exchange(queryUrl, HttpMethod.GET, entity, String.class);

调试信息显示标头为{Content-Type=[application/camiant-msr-v2.0+xml]},看起来是正确的。我想知道我的请求有什么问题,是否有一种方法可以查看请求以进行调试。


1
如果你发送的是 GET 请求,为什么提供了 Content-Type 头部?你是想用 Accept 替代吗? - nicholas.hauschild
@nicholas.hauschild 因为服务器期望如此,只有提供该标头,我才能获得XML响应。 - J Freebird
@nicholas.hauschild 我有点理解你的意思,但API规范是这样规定的,而且Postman也运行良好。 - J Freebird
@nicholas.hauschild 实际上,将其更改为Accept对我有效! 我认为这是因为Java库防止不规则使用,例如在GET请求中设置Content-Type。非常感谢! - J Freebird
3个回答

7
以下方法对我有效:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

@Service
public class Http {

    @Autowired
    private RestTemplate restTemplate;

    public String doGet(final String url) throws Exception {
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
        headers.add(HttpHeaders.USER_AGENT, "Mozilla/5.0");
        headers.add(HttpHeaders.ACCEPT_LANGUAGE, "en-US,en;q=0.8");
        HttpEntity<?> entity = new HttpEntity<Object>(headers);
        HttpEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
        return response.getBody();
    }

}

3
< p > 400 可能的解释是内容类型不适合请求或URL不匹配。

根据我的个人经验,我强烈感觉你搞乱了 queryUrl,为了调整这些问题,我建议你使用 Spring 的 UriComponentsBuilder 类。

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
        .queryParam("data", data);

HttpEntity<?> entity = new HttpEntity<>(headers);

HttpEntity<String> response = restTemplate.exchange(
        builder.build().encode().toUri(), 
        HttpMethod.GET, 
        entity, 
        String.class);

请告诉我它仍然无法工作。

非常感谢您的回复。但是,使用您的方法仍然出现了错误的请求错误。我打印出了URL,它与我在Postman中使用的完全相同,而那个是正常工作的。 - J Freebird

2
实际上,应该将要传递的标题命名为接受而不是内容类型,因为这是一个GET方法。但是服务器API文档某种程度上说它期望内容类型,并且命令行/Postman中的API在内容类型接受上都可以正常工作。我认为是Java库阻止内容类型标题被传递到GET请求中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接