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 ...
随机推荐
- vue项目中使用canvas
canvas API 文档:https://www.canvasapi.cn/ 一.在html中使用canvas canvas 元素用于在网页上绘制图形. 在html中,使用 document.ge ...
- Matlab流体后处理中的奇淫巧术总结
Matlab流体后处理中的奇淫巧术总结 主要参考\demos\volvec.m示例 1.等值面绘制 %% Isosurface of MRI Data cla load mri D = squeeze ...
- 毕业设计之dns搭建:
[apps@dns_sever ~]$ sudo yum install -y bind [apps@dns_sever ~]$ sudo vim /etc/named.conf // // name ...
- addict, address, adequate
addict Addiction is a biopsychosocial disorder characterized by repeated use of drugs, or repetitive ...
- Spark的shuffle和MapReduce的shuffle对比
目录 MapperReduce的shuffle Spark的shuffle 总结 MapperReduce的shuffle shuffle阶段划分 Map阶段和Reduce阶段 任务 MapTask和 ...
- 商业爬虫学习笔记day7-------解析方法之bs4
一.Beautiful Soup 1.简介 Beautiful Soup 是python的一个库,最主要的功能是从网页抓取数据.其特点如下(这三个特点正是bs强大的原因,来自官方手册) a. Beau ...
- keil 报错 expected an identifier
该报错是因为命名重复,可能是因为你加的头文件里面的命名和原程序中的有重复,所以产生了错误.
- 100个Shell脚本——【脚本5】数字求和
[脚本5]数字求和 编写shell脚本,要求输入一个数字,然后计算出从1到输入数字的和,要求,如果输入的数字小于1,则重新输入,直到输入正确的数字为止,示例: 一.脚本 #!/bin/bash whi ...
- Shell脚本的条件控制和循环语句
条件判断:if语句 语法格式: if [ expression ] then Statement(s) to be executed if expression is true fi 注意:expre ...
- shell脚本实现网站日志分析统计
如何用shell脚本分析与统计每天的访问日志,并发送到电子邮箱,以方便每天了解网站情况.今天脚本小编为大家介绍一款不错的shell脚本,可以实现如上功能. 本脚本统计了:1.总访问量2.总带宽3.独立 ...