【原文链接】:https://blog.tecchen.xyz ,博文同步发布到博客园。

由于精力有限,对文章的更新可能不能及时同步,请点击上面的原文链接访问最新内容。

欢迎访问我的个人网站:https://www.tecchen.xyz

在开发扇贝-每日一句时,使用RestTemplate请求扇贝接口,并保存返回的数据。原本正常的代码,经过架构升级后,请求接口时,会返回乱码数据。经过直接访问接口等形式,最终确认是RestTemplate这个bean有问题。

对RestTemplate的声明也比较简单,通过对apache的httpclient进行封装,返回bean实例。代码如下:

  1. @Bean
  2. RestTemplate restTemplate() {
  3. return new RestTemplate(httpRequestFactory());
  4. }

通过断点debug发现以String格式接收数据时,底层采用的是StringHttpMessageConverter来处理请求。查看RestTemplate的构造方法如下:

  1. public RestTemplate() {
  2. this.messageConverters = new ArrayList();
  3. this.errorHandler = new DefaultResponseErrorHandler();
  4. this.uriTemplateHandler = new DefaultUriBuilderFactory();
  5. this.headersExtractor = new RestTemplate.HeadersExtractor();
  6. this.messageConverters.add(new ByteArrayHttpMessageConverter());
  7. this.messageConverters.add(new StringHttpMessageConverter());
  8. this.messageConverters.add(new ResourceHttpMessageConverter(false));
  9. this.messageConverters.add(new SourceHttpMessageConverter());
  10. this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
  11. if (romePresent) {
  12. this.messageConverters.add(new AtomFeedHttpMessageConverter());
  13. this.messageConverters.add(new RssChannelHttpMessageConverter());
  14. }
  15. if (jackson2XmlPresent) {
  16. this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
  17. } else if (jaxb2Present) {
  18. this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
  19. }
  20. if (jackson2Present) {
  21. this.messageConverters.add(new MappingJackson2HttpMessageConverter());
  22. } else if (gsonPresent) {
  23. this.messageConverters.add(new GsonHttpMessageConverter());
  24. } else if (jsonbPresent) {
  25. this.messageConverters.add(new JsonbHttpMessageConverter());
  26. }
  27. if (jackson2SmilePresent) {
  28. this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
  29. }
  30. if (jackson2CborPresent) {
  31. this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
  32. }
  33. }

其中的StringHttpMessageConverter构造方法使用了默认字符集:ISO-8859-1。

  1. public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
  2. public static final Charset DEFAULT_CHARSET;
  3. ……
  4. public StringHttpMessageConverter() {
  5. this(DEFAULT_CHARSET);
  6. }
  7. ……
  8. static {
  9. DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;
  10. }
  11. }

private final List<HttpMessageConverter<?>> messageConverters

根据RestTemplate的构造方法的源码得知所有的HttpMessageConverter都是放在final List<HttpMessageConverter<?>> messageConverters这个常量集合中。虽然集合不可修改,但是可以对其中的元素StringHttpMessageConverter进行修改。

解决方案思路都是将ISO-8859-1的StringHttpMessageConverter替换为UTF-8的StringHttpMessageConverter。

  • 示例代码一
  1. restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
  • 示例代码二
  1. for (HttpMessageConverter<?> httpMessageConverter : restTemplate.getMessageConverters()) {
  2. if (httpMessageConverter instanceof StringHttpMessageConverter) {
  3. ((StringHttpMessageConverter) httpMessageConverter).setDefaultCharset(Charset.forName("UTF-8"));
  4. }
  5. }
  • 示例代码三
  1. // stream .findFirst(); 也是可以的
  2. Optional<HttpMessageConverter<?>> converter = restTemplate.getMessageConverters().stream().filter(c -> c instanceof StringHttpMessageConverter).findAny();
  3. if(converter.isPresent()) {
  4. ((StringHttpMessageConverter) converter.get()).setDefaultCharset(Charset.forName("UTF-8"));
  5. }

RestTemplate--解决中文乱码的更多相关文章

  1. 增加UBUNTU字符集 解决中文乱码问题

    对GBK,GB2312,GB18030字符集的支持是UBUNTU中文乱码的罪魁祸首,其实我们可以在保持UTF-8为默认编码的条件下添加对这几个编码的支持,以解决中文乱码问题. 我想这个问题肯定有其他人 ...

  2. Sublime Text 2—解决中文乱码

    Sublime Text 2是一个非常棒的代码及文本编辑器,绿色小巧.速度飞快,跨平台支持Win/Mac/Linux,支持32与64位,支持各种流行编程语言的语法高亮.代码补全等,有着许多其他编辑器没 ...

  3. zabbix解决中文乱码问题(没有测试成功)

    zabbix解决中文乱码问题 1.在windows系统中找一个自己喜欢的字体,这里我们用:msyh.ttf 2.将字体上传至/var/www/html/zabbix/fonts目录下 [root@za ...

  4. 【原创】通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 ‘incorrect string value: '\xF0...

    这篇blog重点在解决问题,如果你对字符编码并不是特别了解,建议先看看 < [原创]通俗易懂地解决中文乱码问题(1) --- 跨平台乱码 >. 当然,如果只是针对解决这个Mysql插入报错 ...

  5. Debian 6解决中文乱码

    DEBIAN下中文显示 一.首先检查LOCALE情况 说明:DEBIAN因为基于GNU所以,对不同地域进行了不同的包支持,以LOCALE形式存在. 1.挂载ISO文件包,前8个ISO包就可以(这里不在 ...

  6. 04_过滤器Filter_02_Filter解决中文乱码问题

    [过滤器解决中文乱码问题实例] [工程截图] [web.xml] <?xml version="1.0" encoding="UTF-8"?> &l ...

  7. Web---演示servlet技术(servlet生命周期),解决中文乱码问题

    本节讲解决中文乱码问题的4种方法. 还有更好的方法,也就是用过滤器,这里就不演示了,博主目前也不会~呼♪(^∇^*)~过段时间才会学. servlet生命周期演示: index.jsp: <%@ ...

  8. 通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 ‘incorrect string value: '\xF0...

    原文:[原创]通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 'incorrect string value: '\xF0... 这篇blog重点在解决问题,如果你对 ...

  9. 解决中文乱码( jsp表单提交中文时出现乱码)

    有三种方法: 1.建立一个filter中文解决乱码 2.Struts2在struts.xml中修改默认的编码设定 3.用Spring解决中文乱码 4.直接在jsp中修改解决 1.建立一个filter解 ...

  10. java web 中有效解决中文乱码问题-pageEncoding与charset区别, response和request的setCharacterEncoding 区别

    这里先写几个大家容易搞混的编码设置代码: 在jsp代码中的头部往往有这两行代码 pageEncoding是jsp文件本身的编码contentType的charset是指服务器发送给客户端时的内容编码J ...

随机推荐

  1. Java 设计模式系列(一)单例模式

    Java 设计模式系列(一)单例模式 保证一个类只有一个实例,并且提供一个访可该实例的全局访问点. 一.懒汉式单例 /** * 懒汉式单例类:在第一次调用的时候实例化自己 * 1. 构造器私有化,避免 ...

  2. java 对象直接序列化

    序列化类,加字段后, 使用该类从现有文件反序列化时,以前字段可以正常读出 但是反序列化后,那些未对应字段会被设置成null ,即使在类的定义种已设置了初始值 --------------------- ...

  3. awk基础03-分支和循环语句

        awk既然是一门解释型语言,则就可以支持如分支语句.循环语句等.今天就来学习一下在awk中的分支和循环语句.如果您有过任何一门编程语言的基础,则下面所讲内容也是很好理解的. 分支语句 if-e ...

  4. 用 Servlet 进行上载的原理和实现

    Servlet 是用 Java 编写的.协议和平台都独立的服务器端组件,使用请求/响应的模式,提供了一个基于 Java 的服务器解决方案.使用 Servlet 可以方便地处理在 HTML 页面表单中提 ...

  5. Android-FileIOUtils工具类

    文件读写相关工具类 public final class FileIOUtils { private FileIOUtils() { throw new UnsupportedOperationExc ...

  6. [Postgres]Postgres复制表

    在需要把含有分表的总表备份的时候想到的笨办法,如果有什么更先进的办法万望告知. 比如TableOld是由TableOld1,TableOld2,TableOld3组合而成,现在需要对TableOld进 ...

  7. mybatis如何直接 执行传入的任意sql语句 并按照顺序取出查询的结果集

    需求: 1.直接执行前端传来的任何sql语句,parameterType="String", 2.对于任何sql语句,其返回值类型无法用resultMap在xml文件里配置或者返回 ...

  8. iperf命令 +speedtest-cli

    iperf工具可以用来测量TCP或者是UDP的网络吞吐量,即bandwidth(带宽)测试.  iPerf的主要目标是帮助调整特定路径上的TCP连接. 众所周知,TCP最基本的调整问题是调整TCP窗口 ...

  9. Python2.4+ 与 Python3.0+ 主要变化与新增内容

    Python2                          Python3print是内置命令                 print变为函数print >> f,x,y     ...

  10. byte[] 数组和字符串的转换,与byte[] 数组和int类型的之间的转化

    我们先来看看byte bool  int ushort  等的定义 首先时byte[]数组与string之间的转换 string 转换位byte[] 数组 string str = "1-1 ...