字符集引起的请求体不存在:Required request body is missing

本贴最后更新于 1504 天前,其中的信息可能已经事过境迁

交代背景

在和第三方系统接口联调时,我们作为服务端,就是一个简单的 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 接口,然后返回结果。完美,大功告成。虽然解决办法有瑕疵但是能解决问题就行,如果谁有更好的办法欢迎指教。

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    943 引用 • 1460 回帖 • 3 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...