背景
项目中使用 fastjson 将 spring MVC 返回结果输出为 json 格式数据,有个需求是 null 对象不输出,即前端不会接收到 "obj": null
形式的 json 数据,然而在进行如下的配置后, null 对象始终输出,因此以阅读源码的方式解决该问题。
源码分析
DispatcherServlet
DispatcherServlet 是 spring MVC 的入口 Servlet,在其 doDispatch
方法中进行 debug 跟踪就能一步一步跟踪到 fastjson 的 api 中。
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
spring mvc 通过 HandlerMapping、HandlerAdapter 定位到最终的处理器方法,ha.handle()
方法调用的就是我们自己的 controller 层方法,该方法之后会被封装为 HandlerMethod
对象,再进一步封装为 ServletInvocableHandlerMethod
类型。
RequestMappingHandlerAdapter
在 RequestMappingHandlerAdapter#invokeHandlerMethod
方法中会将 controller 层方法包装为最终的 ServletInvocableHandlerMethod
对象,并进一步调用其 invokeAndHandle
方法。
ServletInvocableHandlerMethod
这里有一个 spring mvc 提供的扩展点,即 ServletInvocableHandlerMethod 类的 doInvoke(Object... args)
方法,该方法是 spring mvc 真正调用 controller 层方法的地方,而实际项目中我们往往在 controller 方法中对入参进行一些校验,而校验的这些参数是经过 @RequestParam 或 @RequestBody 注解并处理后的对象,如果要对这些参数进行统一处理,覆写 doInvoke 方法就是一个不错的选择,其中 args 入参数组的元素顺序对应 controller 层方法的参数定义顺序,在该方法中调用 super.doInvoke(args)
得到的即是 controller 层方法的返回值,亦可以对返回值进行统一处理。
举个栗子:
image.png
之后还有一个步骤是为 spring mvc 提供一个自定义的 RequestMappingHandlerAdapter
,在这个 HandlerAdapter
中覆写获取 ServletInvocableHandlerMethod
的方法,即 createInvocableHandlerMethod
方法:
@Configuration
public class WebConfig implements WebMvcRegistrations {
@Override
public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
return new RequestMappingHandlerAdapter() {
@Override
protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) {
return new HandlerMethodResultWrapper(handlerMethod);
}
};
}
}
ServletInvocableHandlerMethod#invokeAndHandle
invokeAndHandle 方法会调用一个类型为 HandlerMethodReturnValueHandlerComposite
的成员变量的 handleReturnValue
方法:
该方法中会从一个 HandlerMethodReturnValueHandler
的 List 中找到能处理当前 controller 返回值的 Handler,然后调用其 handleReturnValue
方法处理返回值。
RequestResponseBodyMethodProcessor
该类即为能处理 controller 返回值的 HandlerMethodReturnValueHandler
,最终调用到 fastjson 内部 api 的入口在 AbstractMessageConverterMethodProcessor
类的 writeWithMessageConverters
方法中,这里的类继承结构如下:RequestResponseBodyMethodProcessor extend
AbstractMessageConverterMethodProcessor implements
HandlerMethodReturnValueHandler 。
writeWithMessageConverters
方法会从一个类型为 HttpMessageConverter
的 Lsit 中找出配置的转换器,这里就会找到 FastJsonHttpMessageConverter
,即终于调用到了 fastjson 的 api。
接下篇:fastjson 始终将 null 对象以 "null " 的形式返回到前端引发的源码解析 - 下:来到 fasjson 内部,消除疑惑
网友评论