交代背景
在和第三方系统接口联调时,我们作为服务端,就是一个简单的 http 接口,开发时用 postman 测试没有任何问题,但是在外部系统请求时,如果报文中存在中文,接口就会报错:
org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing
调用方系统用的是 GBK 编码,他们用的是 SOAPUI 来发的请求,当时最纳闷的是,用 postman 请求一点问题没有,但是用 SOAPUI 调用就是不行。百思不得其解。对方说 SOAPUI 默认用的是 GBK 编码,而 postman 用的是 UTF-8,报错原因是字符集问题。
问题排查
虽说定位到是因为字符集不一致引起的报错,但是怎么也想不通,为什么字符集不一致会导致拿不到请求体,一般也是会出现乱码呀。刚开始想的是可能是 SpringMVC 的字符集过滤器对数据流做了什么操作造成的,但是发现并不是的。通过异常栈一步一步 debug 排查,最后定位到是项目用的 convertor 是 fastjson 的,由于 fastjson 读取请求体数据时,用的是 UTF-8 编码,而请求体中的数据流是用 GBK 编码的,这就导致直接报错了。
问题解决
问题找到了,当然是要要用 GBK 来读取请求体内数据了,第一时间想到的是通过自定义过滤器,指定 GBK 的字符集来读取请求体数据,然后把数据通过 UTF-8 来序列化成流放到 request 中去。但是很可惜,请求体中的内容不能篡改。
然后就想到了在过滤器中调用 Contrllr 接口,直接把拿到的数据直接通过参数的形式给到 Controller 层。但是由于过滤器不是由 Spring 托管的,不能注入 bean。
现在最大的问题就是如果通过 Spring 直接注入接口类,于是想用 spring 的拦截器来实现,但是发现会先执行请求体读取操作,再执行拦截器。
想了很多办法,最后为了解决问题想到了一个最蠢的,就是在过滤器中通过 GBK 拿到数据实体后,发送 HttpClient 请求到之前的 Controller 接口,然后返回结果。完美,大功告成。虽然解决办法有瑕疵但是能解决问题就行,如果谁有更好的办法欢迎指教。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于