Spring RestTemplate传递混合类型的参数MultipartFormData字符串中文乱码问题

问题描述

由于系统需要,使用restTemplate调用外部系统提供的接口,接口描述如图所示(已确认使用postman直接调用时可以正常使用):
被调用的接口描述
项目中调用代码如下图所示:
参数乱码的rest接口调用代码
出现参数中文变?乱码问题:
中文传递的参数存储后变成问号

思路与原因探究

既然确定了是restTemplate调用产生的乱码,通过从网上检索的各种资料不难想到是MessageConverter导致的问题,网上使用较多的解决思路主要有以下两种:

  • 设置StringHttpMessageConverter的编码为UTF-8,StringHttpMessageConverter的默认编码为ISO-8859-1,即:
    修改StringHttpMessageConverter的编码
    如果参数均为String类型,这样设置是有用的,对于我的问题,可以看到在代码中已经进行了设置,但是仍然存在乱码问题
  • 在HttpHeader中设置Content-Type的编码为UTF-8,类似如下代码:
    设置content-type
    其实网上并没有对于multipartFormData设置编码的例子,这里我稍微尝试了一下,不起作用
  • 找到引发问题的本质原因
    step by step对restTemplate.postForEntity的请求进行追踪:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    进入doWithRequest方法的实现查看
    在这里插入图片描述
    断点可以看到,doWithRequest中调用的messageConverter为FormHttpMessageConverter,进入write方法查看
    在这里插入图片描述
    进入writeMultipart方法查看
    在这里插入图片描述
    进入writeParts方法查看
    在这里插入图片描述
    进入writePart方法
    在这里插入图片描述
    查看this.partConverters的值,从而查看StringHttpMessageConverter的编码情况
    在这里插入图片描述
    让我们看一看this.partConverters的初始化赋值情况
    在这里插入图片描述
    查看StringHttpMessageConverter的无参构造函数
    在这里插入图片描述
    由此我们已经找出混合类型参数传输时乱码的原因所在

解决方案

  1. 利用FormHttpMessageConverter提供的setPartConvetrters方法替换默认的partConverters,然后再替换restTemplate中原先的FormHttpMessageConverter在这里插入图片描述
  2. 直接修改FormHttpMessageConverter的源码,将编码由ISO改为UTF-8,然后替换jar包
  3. 修改被调用的接口为纯String类型的参数(修改被调用接口的实现)
    这里我采用的解决方案是直接修改了被调用的接口格式,当然这一点建立在可以修改被调用接口的前提下,项目中Spring的版本为 4.2.8,毕竟这个问题可以说是框架代码的bug了,所以我顺便去查了下spring 5.0.10中的实现情况:
    在这里插入图片描述
    在这里插入图片描述
    尽管StringHttpMessageConverter的默认编码还是ISO,但Spring 5.0.10在FormHttpMessageConverter的构造函数中多了一步applyDefaultCharset的操作,我们来看看这个方法的实现:
    在这里插入图片描述
    从代码上来看,applyDefaultCharset会将converters中的默认编码全部重置为UTF-8,混合类型参数的中文乱码问题已经不复存在,根据网上查阅的资料,这一问题最早在Spring 4.3.0中被修复。
  4. 所以如果大家遇到这个问题,升级Spring的版本到4.3.0及以上也是可以解决的

总结

混合类型参数的中文乱码问题存在于Spring4.3.0之前的RestTemplate实现中,主要是由于:

  • MultipartFormData使用FormHttpMessageConverter来做参数转换
  • FormHttpMessageConverter中使用默认无参构造的StringHttpMessageConverter来做String类型的参数转换
  • 默认无参构造的StringHttpMessageConverter的默认编码为ISO-8859-1

所以导致了中文乱码问题。实际使用中如果碰到需要特别关注一下这个问题。

参考

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值