fastjson 始終將 null 物件以 "null " 的形式返回到前端引發的原始碼解析 - 上:從 DispatcherServlet 出發
背景
專案中使用 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)
舉個栗子:
之後還有一個步驟是為 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 內部,消除疑惑