将我的自定义 http 标头添加到 Spring RestTemplate 请求/扩展 RestTemplate

Add my custom http header to Spring RestTemplate request / extend RestTemplate

提问人:user1209216 提问时间:9/17/2015 最后编辑:djm.imuser1209216 更新时间:1/17/2021 访问量:182807

问:

我目前的代码:

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
Mall[] malls = restTemplate.getForObject(url, Mall[].class);

我需要为我的请求添加一些自定义标头,格式如下:

X-TP-DeviceID : <GUID>

就我而言,最简单的方法是什么?在将请求发送到服务器之前,有没有办法将自定义标头定义添加到我的对象?restTemplate

[编辑]

这是对的吗?

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

HttpHeaders headers = new HttpHeaders();
headers.set("X-TP-DeviceID", "1234567890");
HttpEntity entity = new HttpEntity(headers);

HttpEntity<Mall[]> response = restTemplate.exchange(url, HttpMethod.GET, entity, Mall[].class);

Mall[] malls = response.getBody();

[已添加]

所以,我设法让它工作。但是,我对此并不完全满意。就我而言,我需要为我所做的所有调用提供相同的自定义标头。

因此,我的下一个问题是 - 是否可以将我的自定义标头设置为在每次调用时自动添加,例如,通过扩展类并将所有自定义标头放在那里?然后,我需要做的就是简单地使用我的自定义扩展而不是库存扩展,默认情况下,我的所有自定义标题都将在那里出现。web-serviceRestTemplateRestTemplate

Java Spring Rest 自定义标头

评论


答:

62赞 kswaughs 9/17/2015 #1

您可以使用 RestTemplate 交换方法传递自定义 http 标头,如下所示。

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(new MediaType[] { MediaType.APPLICATION_JSON }));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("X-TP-DeviceID", "your value");

HttpEntity<RestRequest> entityReq = new HttpEntity<RestRequest>(request, headers);

RestTemplate template = new RestTemplate();

ResponseEntity<RestResponse> respEntity = template
    .exchange("RestSvcUrl", HttpMethod.POST, entityReq, RestResponse.class);

编辑:下面是更新的代码。此链接提供了几种调用 rest 服务的方法,并提供了示例

RestTemplate restTemplate = new RestTemplate();

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("X-TP-DeviceID", "your value");

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

ResponseEntity<Mall[]> respEntity = restTemplate.exchange(url, HttpMethod.POST, entity, Mall[].class);

Mall[] resp = respEntity.getBody();

评论

0赞 user1209216 9/17/2015
对不起,我还不清楚。你能提供我的代码的修改版本吗?你的意思是我会有 Mall[] 而不是 RestRresponse?什么是“请求”?我应该将您的 respEntity 对象作为参数添加到 getForObject 调用中吗?在我的情况下,我还需要http方法
0赞 user1209216 9/17/2015
谢谢,我也找到了略有不同的解决方案,也正确吗?我更新了我的问题。顺便说一句,我可以使用 headers.add 或 headers.set,它们之间有什么区别?
1赞 user1209216 9/17/2015
我可以以某种方式检查我的自定义标题是否已设置吗?无法访问服务器日志。它有效,我可以成功获得响应,但我不知道我的应用程序是否真的发送了我的自定义标题
2赞 chrisinmtown 5/15/2018
请澄清 HttpEntity ctor 中“参数”的含义。这是一个神奇的值(一定是那个),是否有可以使用的常量,还是被忽略了?谢谢在adv。
1赞 dustinevan 10/26/2019
哎呀。这真是太糟糕了。这有点像使用 RestTemplate 的交易破坏者。Web 服务客户端传递一些自定义默认标头是很常见的。
8赞 Sean Gildea 1/10/2019 #2

将“User-Agent”标头添加到您的请求中。

一些服务器试图阻止爬虫程序和爬虫访问他们的服务器,因为在早期,请求没有发送用户代理标头。

您可以尝试设置自定义用户代理值,也可以使用一些标识浏览器的值,例如“Mozilla/5.0 Firefox/26.0”

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();

headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("user-agent", "Mozilla/5.0 Firefox/26.0");
headers.set("user-key", "your-password-123"); // optional - in case you auth in headers
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<Game[]> respEntity = restTemplate.exchange(url, HttpMethod.GET, entity, Game[].class);

logger.info(respEntity.toString());

评论

1赞 beauXjames 2/20/2020
为什么/如何“参数”是设置标头的正确方法?
1赞 Tim Biegeleisen 4/1/2021
请注意,和 之间的区别在于,前者将添加一个新的标头,而后者将覆盖标头(如果标头已经存在)。HttpHeaders#addHttpHeaders#set
43赞 k_o_ 3/31/2020 #3

如果目标是拥有一个可重用的 RestTemplate,这通常可用于将相同的标头附加到一系列类似的请求,则参数可以与以下参数一起使用:org.springframework.boot.web.client.RestTemplateCustomizerRestTemplateBuilder

 String accessToken= "<the oauth 2 token>";
 RestTemplate restTemplate = new RestTemplateBuilder(rt-> rt.getInterceptors().add((request, body, execution) -> {
        request.getHeaders().add("Authorization", "Bearer "+accessToken);
        return execution.execute(request, body);
    })).build();

评论

3赞 Filippo Possenti 5/14/2020
不知道为什么这个被否决到否定的地步,因为它对我来说似乎完全正确,一旦我从 RestTemplateBuilder(在我的情况下不是弹簧启动项目)中清除它,它就可以完美无缺地工作。
0赞 Boss Man 9/9/2022
我想做同样的事情,但用于 POST 正文而不是标题。我想在 POST urlformencoded 有效负载中发送相同的键:值对。知道怎么做吗?
0赞 k_o_ 9/12/2022
@BossMan 修改之前怎么样?bodyreturn execution.execute(request, body);
0赞 Boss Man 9/13/2022
@k_o_ 的类型是 。我想我应该说“知道如何有效地做到这一点吗?bodybyte[]
0赞 k_o_ 9/13/2022
@BossMan:好吧,也许还有其他选择,但为什么不解析正文,也许将其转换为字符串并附加、过滤、预置任何你想要的东西?如果发现静态模式,可以以某种方式预初始化此数据并重用它。
2赞 Jose Quijada 12/24/2020 #4

这是我编写的一种方法,用于检查 URL 是否存在。我需要添加请求标头。它是Groovy,但适应Java应该相当简单。从本质上讲,我正在使用 API 方法。我想你得到的解决方案至少在一定程度上取决于你要执行的HTTP方法。从下面的示例中得到的关键是,我正在传递一个 Groovy 闭包(方法的第三个参数,它或多或少是 Java 世界中的 Lambda),它由 Spring API 作为回调执行,以便能够在 Spring 执行命令之前操作请求对象,org.springframework.web.client.RestTemplate#execute(java.lang.String, org.springframework.http.HttpMethod, org.springframework.web.client.RequestCallback, org.springframework.web.client.ResponseExtractor<T>, java.lang.Object...)restTemplate.execute()

boolean isUrlExists(String url) {
    try {
      return (restTemplate.execute(url, HttpMethod.HEAD,
              { ClientHttpRequest request -> request.headers.add('header-name', 'header-value') },
              { ClientHttpResponse response -> response.headers }) as HttpHeaders)?.get('some-response-header-name')?.contains('some-response-header-value')
    } catch (Exception e) {
      log.warn("Problem checking if $url exists", e)
    }
    false
  }