事件:記一次在開發(fā)支付時(shí)候NPE的問(wèn)題
前言
最近有一個(gè)關(guān)于系統(tǒng)支付的功能需求,是系統(tǒng)所有的支付渠道都支持積分抵扣的功能,其實(shí)這個(gè)功能還蠻容易的,只是在支付中加入對(duì)用戶積分的扣減、在支付異常時(shí),對(duì)用戶積分的回填,至于為什么不能在創(chuàng)建訂單的時(shí)候凍結(jié)用戶積分,是因?yàn)榈谌椒e分接口不支持凍結(jié)、解凍功能。
UML圖

代碼示例

支付流程代碼步驟如下:
根據(jù)訂單號(hào)獲取訂單集合
根據(jù)訂單獲取訂單的積分
如果訂單存在積分的話調(diào)用三方積分API,抵扣積分
調(diào)用支付API,扣減金額
這段代碼看起來(lái)沒(méi)有問(wèn)題,對(duì)各種情況都做了判斷,尤其是各種為空的問(wèn)題,但在轉(zhuǎn)測(cè)的時(shí)候,在測(cè)試環(huán)境,測(cè)試同事在手機(jī)上點(diǎn)擊去支付的時(shí)候,發(fā)現(xiàn)服務(wù)日志一直報(bào)“用戶授權(quán)失敗”!why?
我們首先問(wèn)了下前端同事,前端支付這塊是否有改動(dòng)過(guò),確認(rèn)沒(méi)有,并且在最近一周內(nèi)也成功支付過(guò)。然后又在日志中確認(rèn)token一直是有傳的,并且是正確的。所以,我們把問(wèn)題定位到是不是這次修改的支付代碼有問(wèn)題。
經(jīng)本地啟動(dòng),購(gòu)買一個(gè)商品去支付,發(fā)現(xiàn)出現(xiàn)了在上面第19行報(bào)“空指針”的異常,原來(lái)支付的時(shí)候,沒(méi)有花積分,只是全金額支付。那points這個(gè)字段是默認(rèn)不賦值的嗎?我們的訂單是存放在mongodb中,拉取歷史訂單發(fā)現(xiàn)當(dāng)不花積分的時(shí)候,文檔是不存這個(gè)字段的,那問(wèn)題找到了,只要加個(gè)非空處理就ok了,改完重新編譯,可以支付了。

拓展
我在本地又寫了一個(gè)demo,研究是哪里報(bào)的這個(gè)NPE的問(wèn)題。

報(bào)錯(cuò)如下所示:

根據(jù)日志來(lái)看,是sum()方法報(bào)錯(cuò),我通過(guò)debug源碼發(fā)現(xiàn),sum()方法就是循環(huán)調(diào)用mapToLong中的accept()方法,即mapToLong(i.getPoints())這塊。
這塊獲取一定是空的,因?yàn)槲覀儧](méi)有賦值,以后寫lambda一定要謹(jǐn)慎對(duì)待“java.lang.NullPointerException”!
寫在最后
好兄弟可以點(diǎn)贊并關(guān)注我的公眾號(hào)“javaAnswer”,全部都是干貨。