本來是一個風和日麗的下午,一個非常簡單的改動需求。接口返回的日期類型只需要年月日不需要時分秒。因爲我的項目json使用的是fastjson,而不是spring自帶的jackson(不要問我爲什麼)。因爲全局格式化爲yyyy-MM-dd HH:mmss
,於是我愉快的在javabean的屬性上加了個註解。
@JSONField(format="yyyy-MM-dd")
本地測試一下,沒問題,提交到生產環境,5分鐘搞定,完美。
然後就接到產品的電話,改動呢?
我登上去看了一下,唉,沒改到啊,日期還是帶了時分秒。爲了保持我的英明形象(並沒有),使用sql格式化,java用string接收返回前端,間接成功處理。
但是原來的問題還是沒解決。bug。如果是其它組件我可能不會這麼想,但這可是fastjson.
有個笑話這麼說的:
大爺:我算術很快。
記者:1234234乘以23523等於多少?
大爺:等於78!
記者:?????
大爺:你就說快不快吧?!
我覺得用來形容fastjson也很合適,你不知道它可能會從哪裏給你溫柔一擊。
既然懷疑是兩個系統導致的問題,那麼就在idea裏模擬一下linux系統。在
VM options 添加 -Dos.name=linux
啓動,沒有復現bug.
這只是簡單的一個設置環境變量爲linux,並不能完全模擬linux環境。
於是我想到了遠程調試。
一陣操作猛如虎,遠程調試倒是能進斷點,只是斷點進不了第三方jar包的源碼。等於白搞。
後來把fastjson的源碼拉下來,在關鍵的JSONSerializer#writeWithFormat
方法裏添加了一些日誌,重新打包,覆蓋測試環境的jar包,模擬遠程調試。
然後發現測試環境lib目錄,fastjson包居然有兩個版本1.2.1.2.53
和1.2.83
?!
WTF?
我完全搞忘了爲什麼會有兩個版本的包,或許是最初開發階段搞出來的,自己坑自己?
我隱隱約約有了思路,將高版本刪除,留下低版本,成功在本地環境復現了BUG。
應該就是這個原因,高版本里加了註釋。
/**
* #1868 爲了區分全局配置(FastJsonConfig)的日期格式配置以及toJSONString傳入的日期格式配置
* 建議使用以下調整:
* 1. dateFormatPattern、dateFormat只作爲toJSONString傳入配置使用;
* 2. 新增fastJsonConfigDateFormatPattern,用於存儲通過(FastJsonConfig)配置的日期格式
*/
粒度最小的配置應該優先級最高,而在低版本里卻恰恰相反,所以導致了這個bug。
更多的來龍去脈可以去看官方的PR描述.
解決問題的關鍵代碼:
所以,只要把版本升級到1.2.55以上版本,且沒有其它多餘的版本,即可避免上述問題。
後記:
發現fastjson源碼裏面的一些小槽點,比如在catch塊裏面做邏輯處理。這是非常影響性能的。
在阿里巴巴java開發規範當中也有這樣的強制規定:
當然一款廣泛使用的開源軟件,如果拿着放大鏡總是能找出很多問題。我們是不是一款優秀的開源軟件,更應該看大的框架,架構思想。總體來說,fastjson至少值得我去學習。也祝願fastjson2越來越好。