什么情況下需要拋出異常,什么情況下需要catch住異常?
站在代碼開發(fā)者的角度
在進行異常處理的時候,可以try catch住這些異常,然后在catch那里打印錯誤日志,方便定位問題。
還有一種在發(fā)現(xiàn)異常的時候,可以把這部分異常拋出來,讓上游調(diào)用方可以知道這里會出現(xiàn)哪些異常,上游調(diào)用方在獲取到這些異常時,可以根據(jù)業(yè)務(wù)特點來處理這部分異常。
站在調(diào)用方的角度
在調(diào)取其他模塊接口的時候,需要知道被調(diào)用方接口有哪些異常,調(diào)用方根據(jù)業(yè)務(wù)特點來處理這部分異常。異常有2種處理方式:
1.try catch住這些異常,其他接口的異常并不影響當前接口
2.拋出異常,其他接口異常后,當前接口也異常。具體哪種處理方式需要根據(jù)自己的業(yè)務(wù)特點選擇。
總體來說
如果你的服務(wù)就是請求鏈路的最上游或者你寫了一個沒有人調(diào)用的接口,你根據(jù)自己的業(yè)務(wù)特點catch住異常是沒有問題的。
如果你的代碼有其他人調(diào)用,那么出現(xiàn)異常你需要把異常拋出來。
代碼講解之前先解釋一些名詞,不要因為這些名詞而引起對代碼理解的偏差;
服務(wù)A在接收到前端請求后,需要調(diào)取接口B查詢一部分數(shù)據(jù),需要調(diào)取接口N查詢一部分數(shù)據(jù),然后進行數(shù)據(jù)拼裝返回。這叫請求鏈路。
對于接口B,接口A就是接口B的接口調(diào)用方,接口B的上游就是接口A。
前端想要獲取數(shù)據(jù),那么接口A就是最上游。接口A沒有后端調(diào)用者。接口B或者接口N,都有調(diào)用者,調(diào)用者是接口A。
業(yè)務(wù)場景:
用戶在外賣商品頁面選擇完商品后,點擊提交訂單,后端服務(wù)需要保存訂單數(shù)據(jù)和將商品的庫存數(shù)量減1。
接下來看代碼:
這個代碼里面包含2部分邏輯,邏輯1是保存訂單數(shù)據(jù),邏輯2是更新商品庫存數(shù)據(jù)。
問題:
負責(zé)開發(fā)更新商品庫存接口的同學(xué)把異常給try{}catch{}住了。當用戶點擊提交訂單時,請求落到了訂單服務(wù),OrderService.saveOrder()方法將訂單數(shù)據(jù)保存后,調(diào)取更新商品庫存數(shù)量的接口,更新商品庫存數(shù)量的接口異常了,商品庫存數(shù)量并沒有更新成功,但是因為異常try{} catch{}住了,對于訂單服務(wù)而言,訂單服務(wù)又不知道商品庫存接口異常了,返回給用戶保存成功,但是現(xiàn)在商品庫存數(shù)據(jù)卻沒有保存成功;
發(fā)現(xiàn)問題后,讓商品庫存的同學(xué)把代碼修改下,把異常拋出來,不要自己把異常處理(吃)了。
代碼變成如下形式,當更新商品庫存數(shù)據(jù)異常后,訂單服務(wù)也拋出異常,讓用戶知道提交訂單異常,用戶可以選擇再次下單。
業(yè)務(wù)場景:
這個是商品詳情頁,包含商品數(shù)據(jù)和評價數(shù)據(jù)。 如果評價數(shù)據(jù)可以查詢到就展示,查詢評價數(shù)據(jù)異常時,頁面降級不展示評價數(shù)據(jù)。
接下來看代碼:
這個代碼里面包含2部分邏輯,邏輯1是查詢商品數(shù)據(jù),邏輯2是查詢評價數(shù)據(jù)。因為GoodsService的getGoodsById()方法將查詢評價數(shù)據(jù)接口try{}catch{}住了,查詢評價數(shù)據(jù)接口異常時,并不會影響查詢商品數(shù)據(jù)接口的穩(wěn)定性。
總結(jié):
如果這個方法在調(diào)用鏈路的下游,有其他系統(tǒng)去調(diào)用這個方法時,出現(xiàn)異常了需要將異常拋出來;上游調(diào)用方可以根據(jù)自己的業(yè)務(wù)特點選擇拋出異?;蛘遲ry{}catch{}住異常。
接下來看另一個場景:
業(yè)務(wù)場景:
用戶下單,取消訂單或者其他訂單關(guān)聯(lián)的業(yè)務(wù),需要將訂單狀態(tài)流轉(zhuǎn)數(shù)據(jù)保存到訂單日志表中,當訂單數(shù)據(jù)出現(xiàn)問題時,通過訂單日志表,很方便的可以定位出問題。
接下來看代碼:
創(chuàng)建訂單和取消訂單主要包含3部分邏輯:
1.保存或者更新訂單數(shù)據(jù)
2.將訂單操作日志數(shù)據(jù)寫入到數(shù)據(jù)庫中
3.如果訂單操作日志數(shù)據(jù)寫入數(shù)據(jù)庫異常時,發(fā)送一條MQ消息,讓MQ消息的重試機制保證日志數(shù)據(jù)寫入成功。
問題:
OrderLogService除了OrderService調(diào)用外,不會有其他類會調(diào)用。OrderService對OrderLogService的異常處理邏輯一樣,處理邏輯為發(fā)送一條MQ消息,通過MQ消息的重試機制保證日志數(shù)據(jù)寫入成功。一個異常,超過2個方法處理(修改訂單未實現(xiàn)),而且處理邏輯一樣。 異常不如讓OrderLogService自己來處理。
將代碼改成如下形式:如果操作日志數(shù)據(jù)寫入失敗后,讓OrderLogService內(nèi)部自己處理。
這樣做的好處:
1.OrderService代碼簡潔,不用再去處理OrderLogService異常;
2.現(xiàn)在日志數(shù)據(jù)寫入失敗后,OrderLogService會發(fā)送一條MQ消息。 以后需要修改異常處理方式,只需要修改OrderLogService里面的邏輯就好。
總結(jié):
如果這個方法只有同一個系統(tǒng)的接口去調(diào)用,而且內(nèi)部對這個異常有相同的處理邏輯,出現(xiàn)異常了可以讓這個方法將異常處理掉,這樣其他調(diào)用方就不需要處理異常了
#大廠##面試題目#