【问题标题】:Add my custom http header to Spring RestTemplate request / extend RestTemplate将我的自定义 http 标头添加到 Spring RestTemplate 请求/扩展 RestTemplate
【发布时间】:2015-12-13 21:56:24
【问题描述】:

我当前的代码:

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-service 调用中自动添加,例如,通过扩展 RestTemplate 类并将所有自定义标头放在那里?然后,我需要做的就是简单地使用我的自定义扩展RestTemplate 而不是库存的,默认情况下我所有的自定义标题都将出现在那里。

【问题讨论】:

    标签: java spring rest custom-headers


    【解决方案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);
    

    编辑:下面是更新的代码。 This link has several ways of calling rest service with examples

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

    【讨论】:

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

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

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

    【讨论】:

    • 不知道为什么这个被否决到否定的地步,因为它对我来说似乎完全正确,一旦我从 RestTemplateBuilder(在我的情况下不是一个 spring-boot 项目)中删除它,它就完美地工作了.
    【解决方案3】:

    在您的请求中添加“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());
    

    【讨论】:

    • 为什么/如何设置标题的正确方法是“参数”?
    • 请注意HttpHeaders#addHttpHeaders#set之间的区别在于前者会添加一个新的标题,而后者会覆盖一个已经存在的标题。
    【解决方案4】:

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

    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
      }
    

    【讨论】:

      猜你喜欢
      • 2016-11-12
      • 2014-03-10
      • 2018-12-18
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      相关资源
      最近更新 更多