本文介绍了Java Spring RestTemplate设置不需要的标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用响应rest api的服务。但是,当我将Accept-Charset标头设置为long值的请求发送时,该服务会中断。一个显而易见的解决方案是明确设置此标头:Accept-Charset:utf-8。然而,这似乎不起作用:

I want to use a service that responds to a rest api. However, when I send a request with the Accept-Charset header set to a long value, that service breaks. An apparently easy solution would be to just set this header explicitly: "Accept-Charset": "utf-8". However this just does not seem to work:

    String requestBody = "{\"message\": \"I am very frustrated.\"}";
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    ArrayList<Charset> acceptCharset = new ArrayList<>();
    acceptCharset.add(StandardCharsets.UTF_8);
    headers.setAcceptCharset(acceptCharset);
    log.info(headers.toString());
    ResponseEntity<String> res = restTemplate.exchange("http://httpbin.org/post", HttpMethod.POST, new HttpEntity<>(requestBody, headers), String.class);
    String httpbin = res.getBody();

    log.info("httpbin result: " + httpbin);

这会返回此结果:

-> {Accept-Charset=[utf-8]}

-> INFO httpbin result: {
  "args": {},
  "data": "{\"message\": \"I am very frustrated.\"}",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "text/plain, application/json, application/*+json, */*",
    "Accept-Charset": "big5, big5-hkscs, cesu-8, euc-jp, euc-kr, gb18030, gb2312, gbk, ibm-thai, ibm00858, ibm01140, ibm01141, ibm01142, ibm01143, ibm01144, ibm01145, ibm01146, ibm01147, ibm01148, ibm01149, ibm037, ibm1026, ibm1047, ibm273, ibm277, ibm278, ibm280, ibm284, ibm285, ibm290, ibm297, ibm420, ibm424, ibm437, ibm500, ibm775, ibm850, ibm852, ibm855, ibm857, ibm860, ibm861, ibm862, ibm863, ibm864, ibm865, ibm866, ibm868, ibm869, ibm870, ibm871, ibm918, iso-2022-cn, iso-2022-jp, iso-2022-jp-2, iso-2022-kr, iso-8859-1, iso-8859-13, iso-8859-15, iso-8859-2, iso-8859-3, iso-8859-4, iso-8859-5, iso-8859-6, iso-8859-7, iso-8859-8, iso-8859-9, jis_x0201, jis_x0212-1990, koi8-r, koi8-u, shift_jis, tis-620, us-ascii, utf-16, utf-16be, utf-16le, utf-32, utf-32be, utf-32le, utf-8, windows-1250, windows-1251, windows-1252, windows-1253, windows-1254, windows-1255, windows-1256, windows-1257, windows-1258, windows-31j, x-big5-hkscs-2001, x-big5-solaris, x-compound_text, x-euc-jp-linux, x-euc-tw, x-eucjp-open, x-ibm1006, x-ibm1025, x-ibm1046, x-ibm1097, x-ibm1098, x-ibm1112, x-ibm1122, x-ibm1123, x-ibm1124, x-ibm1166, x-ibm1364, x-ibm1381, x-ibm1383, x-ibm300, x-ibm33722, x-ibm737, x-ibm833, x-ibm834, x-ibm856, x-ibm874, x-ibm875, x-ibm921, x-ibm922, x-ibm930, x-ibm933, x-ibm935, x-ibm937, x-ibm939, x-ibm942, x-ibm942c, x-ibm943, x-ibm943c, x-ibm948, x-ibm949, x-ibm949c, x-ibm950, x-ibm964, x-ibm970, x-iscii91, x-iso-2022-cn-cns, x-iso-2022-cn-gb, x-iso-8859-11, x-jis0208, x-jisautodetect, x-johab, x-macarabic, x-maccentraleurope, x-maccroatian, x-maccyrillic, x-macdingbat, x-macgreek, x-machebrew, x-maciceland, x-macroman, x-macromania, x-macsymbol, x-macthai, x-macturkish, x-macukraine, x-ms932_0213, x-ms950-hkscs, x-ms950-hkscs-xp, x-mswin-936, x-pck, x-sjis_0213, x-utf-16le-bom, x-utf-32be-bom, x-utf-32le-bom, x-windows-50220, x-windows-50221, x-windows-874, x-windows-949, x-windows-950, x-windows-iso2022jp",
    "Connection": "close",
    "Content-Length": "36",
    "Content-Type": "text/plain;charset=ISO-8859-1",
    "Host": "httpbin.org",
    "User-Agent": "Java/1.8.0_131"
  },
  "json": {
    "message": "I am very frustrated."
  },
  "origin": "###.###.###.###",
  "url": "http://httpbin.org/post"
}

如何覆盖此默认标头?

推荐答案

问题是您使用的是默认配置的 RestTemplate 并正在编写字符串正文。这种组合导致默认配置,其中 writeAcceptCharset 设置为 true 。这将导致所有可用的字符集被添加为标题。

The problem is that you are using a default configured RestTemplate and are writing a String body. This combination leads to a default configured StringHttpMessageConverter being used, which has the writeAcceptCharset set to true. Which will lead to all available charsets being added as a header.

现在你有2种方法可以解决这个问题。

Now you have 2 ways of fixing this.


  1. 不写一个普通的字符串但是写另一个对象,它会将对象编组为 String 绕过 StringHttpMessageConverter

  2. 重新配置 StringHttpMessageConverter 并设置 writeAcceptCharset false

  1. Don't write a plain String but write another object which will marshal the object to a String bypassing the StringHttpMessageConverter.
  2. Reconfigure the StringHttpMessageConverter and set the writeAcceptCharset to false.



使用编组



Using Marshalling

public class Message {
    private String message;
    Message() {}
    public String getMessage() { this.message;}
    public void setMessage(String message) { this.message=message;}
}

接下来使用此消息类而不是普通字符串 JSON正文。

Next use this Message class instead of the plain String JSON body.

Message msg = new Message();
msg.setMessage("I am very frustrated.");
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
List<Charset> acceptCharset = Collections.singletonList(StandardCharsets.UTF_8);
headers.setAcceptCharset(acceptCharset);
log.info(headers.toString());

HttpEntity<Message> entity = new HttpEntity<>(msg, headers);
ResponseEntity<String> res = restTemplate.exchange("http://httpbin.org/post", HttpMethod.POST, entity, String.class);
String httpbin = res.getBody();

log.info("httpbin result: " + httpbin);

但请求中有轻微变化, Content-Type 标题从 text / plain 更改为 application / json 。不确定这是否是您想要的(虽然您实际上是发送JSON而不是纯文本)。

However there is a slight change in the request, the Content-Type header changes from text/plain to application/json. Not sure if that is what you want (although you are actually sending JSON and not plain text).

 RestTemplate restTemplate = new RestTemplate();
 for (HttpMessageConverter converter : restTemplate.getMessageConverters) {
     if (converter instanceof StringHttpMessageConverter) {
         ((StringHttpMessageConverter) converter).setWriteAcceptCharset(false);
     }
 }

这只会将配置的字符集写入响应。

This will only write the configured charsets to the response.

这篇关于Java Spring RestTemplate设置不需要的标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 05:29