FastJsonHttpMessageConverter请求中参数序列化问题排查
问题
前几天帮忙其他部门的多个祖先级项目改造开发,服务间使用Feign方式调用,发现接口提供方接收到的请求,没有请求参数,经过排查发现服务调用方的FastJsonHttpMessageConverter配置方式存在问题,导致请求中RequestBody的序列化出现问题。
排查步骤
- 服务提供方排查
经debug DispatcherServlet发现request中各请求参数名发生了变化—命名规则由camel变成了snake_case(蛇形命名规则),接口的请求参数名的命名规则是camel,所以导致接口中各个参数没有值,判定很有可能是请求调用方的HttpMessageConverter的配置有问题;
- 服务调用方排查
debug查发出请求时请求的所有的messageConverter,发现项目里添加了FastJsonHttpMessageConverter,在经过FastJsonHttpMessageConverter 对请求参数的处理后,HttpOutputMessage输出的请求参数名发生了变化—把原来camel规则的请求参数统一进行了snake_case转换;
- 至此基本定位问题原因-FastJsonHttpMessageConverter的配置导致参数命名发生改变,进而导致服务提供方接收不到原有的参数。
解决方法
深入阅读FastJsonHttpMessageConverter源码,在writeInternal 和 readInternal时,会使用FastJsonConfig-> SerializeConfig,来进行请求体的序列化和反序列化,如图-1

图-1
方法一:
- 自定义FeignClient的configuration覆盖默认的FeignClientsConfiguration,在自定义的FeignConfiguration中去重新定义SpringEncoder和SpringDecoder,在Encoder和Decoder中去重新配置FastJsonHttpMessageConverter;
- 针对此FeignClient的configuration定义一个此feign实例的FastJsonConfig->SerializeConfig,而非使用全局的SerializeConfig(之所以不用全局,因为项目比较庞杂,怕影响其他三方服务调用),设置其propertyNameStrategy = CamelCase
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import feign.Logger.Level;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder;
import org.springframework.cloud.netflix.feign.support.SpringDecoder;
import org.springframework.cloud.netflix.feign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter; public class FeignConfiguration {
HttpMessageConverters converters;
ObjectFactory<HttpMessageConverters> httpMessageConverters; public FeignConfiguration() {
} @PostConstruct
public void init() {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
List<MediaType> supportedMediaTypes = new ArrayList();
supportedMediaTypes.add(MediaType.APPLICATION_JSON);
supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
supportedMediaTypes.add(MediaType.APPLICATION_PDF);
supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
supportedMediaTypes.add(MediaType.APPLICATION_XML);
supportedMediaTypes.add(MediaType.IMAGE_GIF);
supportedMediaTypes.add(MediaType.IMAGE_JPEG);
supportedMediaTypes.add(MediaType.IMAGE_PNG);
supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
supportedMediaTypes.add(MediaType.TEXT_HTML);
supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
supportedMediaTypes.add(MediaType.TEXT_PLAIN);
supportedMediaTypes.add(MediaType.TEXT_XML);
converter.setSupportedMediaTypes(supportedMediaTypes);
this.converters = new HttpMessageConverters(new HttpMessageConverter[]{converter});
this.httpMessageConverters = () -> {
return this.converters;
};
} @Bean
public Level feignLoggerLevel() {
return Level.FULL;
} @Bean
public ErrorDecoder businessErrorDecoder() {
return new FeignErrorDecoder();
} @Bean
public Decoder feignDecoder() {
return new ResponseEntityDecoder(new SpringDecoder(this.httpMessageConverters));
} @Bean
public Encoder feignEncoder() {
return new SpringEncoder(this.httpMessageConverters);
} }
方法二:
服务提供方,feign接口的@RequestBody 对应的请求实体类添加@JSONType(naming=PropertyNamingStrategy.CamelCase)
SerializeConfig在getWriter时会读取这个注解来决定序列化/反序列化时的请求体中参数的命名规则。

1 import com.alibaba.fastjson.PropertyNamingStrategy;
2 import com.alibaba.fastjson.annotation.JSONType;
3
4 import java.io.Serializable;
5
6 /**
7 * @author zhaoxinbo
8 * @name: UserRequest
9 * @description: 请求参数-user RequestBody
10 * @date 2021/9/24 20:22
11 */
12 @JSONType(naming = PropertyNamingStrategy.CamelCase)
13 public class UserRequest implements Serializable {
14 private Long userId;
15
16 private String userName;
17
18 public Long getUserId() {
19 return userId;
20 }
21
22 public void setUserId(Long userId) {
23 this.userId = userId;
24 }
25
26 public String getUserName() {
27 return userName;
28 }
29
30 public void setUserName(String userName) {
31 this.userName = userName;
32 }
33 }
建议使用第二种方式,服务提供方明确告知请求参数的命名规则,当然第一种方法中如果有服务提供方来提供FeignConfiguration的话更方便。
FastJsonHttpMessageConverter请求中参数序列化问题排查的更多相关文章
- axio 请求中参数是数组
前言 最近在做 Vue 项目中,Get 请求中有的参数是数组,传 JSON 字符串是没有问题的,但是直接传数组就一直报错,有问题. 参数后面无故加了 [],例如:UserIds 变成 UserIds[ ...
- ajax 之POST请求,参数序列化
比如,,我们在没有使用jquery的时候,没有$.post来让我们使用,那我们像下面这样直接发送: var params1 = { username: username, passwrod: pass ...
- 解决backbone url请求中参数有中文,存入数据库是乱码
最近项目用到了backbone 做前后端的分离方案,遇见了中文乱码问题,解决方案总结如下: 假设需要存一条课程记录到后台 model定义如下: var AddCourse= Backbone.Mo ...
- PHP中get请求中参数的key不能是para
¶会被转化成¶,然后就无法进行下去了. 仅作记录.
- Spring MVC如何获取请求中的参数
目录 一.获取URL中路径参数 1.1 @PathVariable 注解 1.2 @PathParam 注解 二.获取请求参数: 2.1 GET请求 2.1.1 获取请求中的单个参数:@Request ...
- http请求中的中文乱码问题
通过浏览器访问服务器页面和资源时,不可避免地要传送中文字串,如果客户机与服务器不能用同一码表解析字串,肯定会出现各种各样的乱码问题.我总结了几个乱码场景及解决办法,如下 1.服务器上的中文字串被客户端 ...
- AJAX请求 $.ajaxSetup方法的使用:设置AJAX请求的默认参数选项,当程序中需要发起多个AJAX请求时,则不用再为每一个请求配置请求的参数
定义和用法ajaxSetup() 方法为将来的 AJAX 请求设置默认值.语法$.ajaxSetup({name:value, name:value, ... }) 该参数为带有一个或多个名称/值对的 ...
- (三)Asp.net web api中的坑-【http post请求中的参数】
接上篇, HttpPost 请求 1.post请求,单参数 前端 var url = 'api/EnterOrExit/GetData2';var para = {};para["Phone ...
- post请求中的参数形式和form-data提交数据时取不到的问题
@Controller页面form表单请求时不会丢数据返回json数据时需要加 注解@ResponseBody请求格式如下 @ResponseBody public Object login(Sign ...
随机推荐
- 题解 P5320 - [BJOI2019]勘破神机(推式子+第一类斯特林数)
洛谷题面传送门 神仙题(为什么就没能自己想出来呢/zk/zk) 这是我 AC 的第 \(2\times 10^3\) 道题哦 首先考虑 \(m=2\) 的情况,我们首先可以想到一个非常 trivial ...
- 自助分析工具Power BI的简介和应用
作为一名资深的IT技术人,特别喜欢学习和尝试新技术,也勇于接受挑战,勇于创新,不仅能发现问题,更要解决实际的疑难杂症,闲暇时光也乐于分享一些技术干货.记得2017年的时候,华章出版社的编辑通过网上找到 ...
- 混合(Pooling)样本测序研究
目录 1.混合测序基础 2. 点突变检测 3. BSA 4. BSR 5. 混合样本GWAS分析 6. 混合样本驯化研究 7. 小结 1.混合测序基础 测序成本虽然下降了,但对于植物育种应用研究来说还 ...
- Linux终端命令行的快捷键列表
tab键:命令.文件名等自动补全功能. Ctrl+a:光标回到命令行首.Ctrl+e:光标回到命令行尾.Ctrl+k:删除光标处到行尾的字符.Ctrl+u:删除整个命令行文本字符.ctrl+y: 粘贴 ...
- 错误笔记: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable) E: Unable to lock the administration di
亲测可用 --jack alexander@alexander-virtual-machine:~$ sudo apt-get install -y httpdE: Could not get loc ...
- javaSE中级篇3——集合体系(另外一种存储容器)——更新完毕
集合还是一种工具,所以它们的包都在java.util包下 1.集合的整个体系结构(是需要掌握的体系,完全体系不是这样) 对图中所说的 序和重复 这两词的说明: 序:指的是添加进去的元素和取出来的元素 ...
- 详解 Rainbond Ingress 泛解析域名机制
Rainbond 作为一款云原生应用管理平台,天生带有引导南北向网络流量的分布式网关 rbd-gateway.区别于一般的 Ingress 配置中,用户需要自行定义域名的使用体验,Rainbond 的 ...
- 日常Java测试 2021/11/14
课堂测试三 package word_show; import java.io.*;import java.util.*;import java.util.Map.Entry; public clas ...
- 学习java 7.16
学习内容: 线程安全的类 Lock锁 生产者消费者模式 Object类的等待唤醒方法 明天内容: 网络编程 通信程序 遇到问题: 无
- Redis6 新特性
Redis6新特性 ACL安全策略 ACL(access control list): 访问控制列表,可以设置多个用户,并且给每个用户单独设置命令权限和数据权限 default用户和使用require ...