美文网首页spring boot
fastjson 始终将 null 对象以 "null

fastjson 始终将 null 对象以 "null

作者: DJN_ | 来源:发表于2018-11-07 10:36 被阅读13次

    背景

    项目中使用 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 内部,消除疑惑

    相关文章

      网友评论

        本文标题:fastjson 始终将 null 对象以 "null

        本文链接:https://www.haomeiwen.com/subject/wuouxqtx.html