记录一次fastjson调用的奇怪问题
一、项目背景
研究什么时候会调用fastjson,什么时候调用默认的jackson
二、使用对比
1.Spring项目开启fastjson支持
<!-- 启动spring mvc的注解功能 -->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<!-- 配置Fastjson支持 -->
<bean
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json</value>
</list>
</property>
<!-- <property name="features">
<list>
<value>WriteMapNullValue</value>
<value>QuoteFieldNames</value>
</list>
</property>-->
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
此时如果在代码里手动调用JSON.toJSONString(map, SerializerFeature.WriteMapNullValue)(map是一个hashmap的实例)并且Controller层的方法家还是那个@Responsebody注解。将会出现手动调用fastjson然后调用fastjson的writeInternal(Object obj, HttpOutputMessage outputMessage)方法
但是此时去掉<value>application/json</value>这一项会出现不会手动调用writeInternal方法,此时接口的实现类调用的是StringHttpMessageConverter,实现方法是writeInternal(String s, HttpOutputMessage outputMessage)。
三、结果原因分析 :
1.一开始我以为是更细化的实现类优先调用,即先调用默认的String类型。
找不到再调用fastjson的writeInternal方法。然而类型确定会这样,但是此时最主要的区别是请求头的区别,请看
Content-Type: application/json;charset=UTF-8
X-Requested-With: XMLHttpRequest
Accept: application/json
此时接收的请求正好符合我们预定义好的属性。也就是说不是类型问题。
2.那么是Accept类型导致了fastjson两次序列化的问题。
请求头去掉accept属性后,List<MediaType> producibleMediaTypes = this.getProducibleMediaTypes(servletRequest, returnValueClass); 的属性接受变为*/*。
List<MediaType> producibleMediaTypes = this.getProducibleMediaTypes(servletRequest, returnValueClass);的值
加一个*/*,其他如application/json等等。
此时还会调用fastjson方法。
3.去掉<value>application/json</value>支持
此时调用的是默认的StringHttpMessageConverter。很奇怪,进入源码分析。此时请求头依旧为Accept: application/json,返回的是一次手动序列化的结果,没有调用fastjson。那么意味着只要fastjson没有配置application/json支持,并且accept配置为Accept: application/json将不会调用fastjson。
也就是说,如果fastjson这边配置了supportedMediaTypes,如果请求头的accept不在这个支持范围内,调用的是默认的转换器。
推荐阅读
-
WEB上调用HttpWebRequest奇怪问题的解决方法
-
记录第一次搭建Dubbo遇到的一个问题
-
记一次NET Core 2.0在macOS 10.13出现的奇怪Build IO共享冲突问题
-
记录一次排查使用HttpWebRequest发送请求的发生“基础连接已关闭:接收时发生错误”异常问题的过程
-
记录一次springsecurity5.0.6做权限登录异常缓慢的问题解决记录
-
Android记录一次InstallerPackage apk报错的问题分析
-
使用ForkJoin解决0到1百亿的求和问题-----一次测试和调优记录,掌握ForkJoinPool的核心用法
-
记录一次使用NPOI遇到的问题
-
记一次更新Mysql表记录时,PreparedStatement.setTimestamp抛出NullPointerException的问题
-
记录一次大对象导致的Java堆内存溢出问题