使用fastjson打印日志的坑

 

一、前言

项目打印日志是使用AOP实现的,把controller方法上的参数和返回值全部使用fastjson转换为json字符串打印出来,方便观察方法调用情况.最近同事遇到了一个在打印日志的时候,fastjson 序列化的异常,这个异常不影响业务逻辑,作为一个有强迫症的人,始终是觉得有问题的,于是跟着错误信息就找了下去.

二、症状

看看异常信息吧!

1CfMpX

从异常的信息可以看出,在fastjson把对象转json字符串的时候遇到了问题,貌似从这个图片中看不出啥问题,该图片下面还有一段异常信息,如下:

java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
at org.apache.catalina.connector.Request.getAsyncContext(Request.java:1740)
at org.apache.catalina.connector.RequestFacade.getAsyncContext(RequestFacade.java:1047)
at com.alibaba.fastjson.serializer.ASMSerializer_1_RequestFacade.write(Unknown Source)
at com.alibaba.fastjson.serializer.JSONSerializer.write(JSONSerializer.java:280)
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:673)
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:611)
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:576)
at com.me.Aspect.LoggerAspect.After(LoggerAspect.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:620)

三、分析

​ 上面这段信息可以看出,调用getAsyncContext方法出现了问题.表示当前这个request对象不是异步模式的,所以不能调用getAsyncContext这个方法.这个request的异步模式,是servlet3中的一个新特性,可以使用注解或者配置xml的方式进行开启,一般用于异步请求,这个request的异步模式的使用场景,就不多论述了.回到问题中来,fastjson序列化出错,出错的原因是fastjson调用了getAsyncContext方法,由于request不是异步模式,所以报错了,那么结果就是fastjson序列化出错了.

​ 再看一下异常信息,按照打印的栈信息来看,是RequestFacade对象中的getAsyncContext方法被调用了,但是工程里面并没用用到RequestFacade对象呀,查看RequestFacade类的源码过后发现RequestFacade其实是HttpServletRequest的一个具体实现.那么问题就定位到了,fastjson把HttpServletRequest序列化了,只要把方法上的HttpServletRequest 参数去掉就可以了.

MZ7BAI

四、总结

有时候问题很简单,可能只是你没遇到过而已,多做记录,积累经验!