故事背景
某次开心的写完一段代码后,进入了前后端联调阶段,眼看需求提测在即,突然前端发来条消息说:“接口报错,400了!” 我心想肯定又是前端不守规矩乱调接口了,便回复道:“好好检查一下,我这边swagger上测过的。”
10分钟后,前端又发来了消息:“没问题啊我这。”还发来了他的DevTools截图,力证清白。400 bad request,我眉头一皱,发现事情没有那么简单。
我打开fiddler,分别使用swagger和前端界面操作了两次,然后将两次请求的完整session拷贝出来,使用在线文本比对工具对比了下,尼玛没有什么不同啊。再仔细瞧瞧,似乎多出一个入参字段来,会是这玩意导致的?
抱着试试看的心态,我编辑了下这个请求,去掉多出的字段,retry了一下,果不其然,通了!还有这样的事?
正要查查原因,pm发消息要聊新需求,再看下消息列表,测试问啥时候提测、客诉群@我排查问题、一个外部门的哥们问某某接口文档地址……算了,下次再查吧。于是回复前端:“把那个xxx字段去掉。”
时光荏苒,两三个月过去了,"又400了!“前端又喊起来。我心想又搞事,便回复:"是不是又有多余字段?"前端虽然回复是,但不耐烦于总要发送请求前修剪入参。虽然前端给后端多传一堆垃圾字段过来不是什么好事,但我也疲于跟他们掰扯了。嗯,是时候查下原因了。
原因排查
SpringMVC默认使用的是jackson,默认不允许出现bean中未知的字段,配置一下FAIL_ON_UNKNOWN_PROPERTIES=false就好了。
解决方法
SpringMVC用的是MappingJackson2HttpMessageConverter这个类,可以通过继承ObjectMapper来重写默认配置,来为其设置新的转换规则。
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
public class MyObjectMapper extends ObjectMapper {
public MyObjectMapper() {
super();
// 当前端传入json包含未知字段时,不抛异常(默认值为true)
this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
}
修改spring配置:
<mvc:annotation-driven>
<mvc:message-converters register-defaults="false">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
<property name="objectMapper">
<!--这里设置为自定义的objectMapper,覆盖默认设置-->
<bean class="com.cafeboy.common.MyObjectMapper"></bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
后记
修改过配置后,前端再也没有找过我排查400的问题。嗯,世界又清静了一点点……