fastjson 始终将 null 对象以 "null " 的形式返回到前端引发的源码解析 - 上:从 DispatcherServlet 出发

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/aimeimeiTS/article/details/83821986

背景

项目中使用 fastjson 将 spring MVC 返回结果输出为 json 格式数据,有个需求是 null 对象不输出,即前端不会接收到 "obj": null 形式的 json 数据,然而在进行如下的配置后, null 对象始终输出,因此以阅读源码的方式解决该问题。
image.png

源码分析

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 方法:
image.png

该方法中会从一个 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 内部,消除疑惑

猜你喜欢

转载自blog.csdn.net/aimeimeiTS/article/details/83821986