利用Spring優(yōu)雅處理Java異常

如何解決業(yè)務(wù)開(kāi)發(fā)中的異常情況

在我們的業(yè)務(wù)開(kāi)發(fā)中昏兆,經(jīng)常會(huì)碰到一些業(yè)務(wù)方面的異常情況,比如購(gòu)買(mǎi)商品發(fā)現(xiàn)余額不足盾鳞,用戶(hù)未被授權(quán)該操作、以及接收到惡意偽造的請(qǐng)求等等瞻离,這些時(shí)候腾仅,都會(huì)導(dǎo)致我們的業(yè)務(wù)操作終止,返回失敗琐脏。
對(duì)上述類(lèi)似的業(yè)務(wù)異常場(chǎng)景,有兩種方案可供選擇:

  1. 對(duì)于異常場(chǎng)景返回異常狀態(tài)碼缸兔,在上層日裙,對(duì)異常狀態(tài)碼進(jìn)行處理;
  2. 拋出異常惰蜜,交由上層邏輯處理昂拂。

這兩種方案都是可行的,但是狀態(tài)碼機(jī)制抛猖,會(huì)給我們的系統(tǒng)帶來(lái)耦合格侯,我們需要維護(hù)一個(gè)統(tǒng)一的狀態(tài)碼機(jī)制,而且容易導(dǎo)致controller層和service層之間的耦合财著。

如何拋出联四、并處理異常?

那我們來(lái)看一下拋出異常的解決方案撑教,我們可以定義一個(gè)ServiceException繼承自RuntimeException朝墩,并通過(guò)ServiceException傳入發(fā)生異常的具體原因提示信息,在Controller層進(jìn)行統(tǒng)一捕獲伟姐,不過(guò)這樣寫(xiě)有點(diǎn)難看收苏。
然而,考慮這樣一種情況愤兵,對(duì)于業(yè)務(wù)異常鹿霸,有些需要我們返回用戶(hù)提示信息,比如“余額不足”等秆乳;有些返回提示信息則可能導(dǎo)致安全隱患懦鼠,比如返回“用戶(hù)不存在”,可以讓黑客發(fā)起“撞庫(kù)”攻擊,這事葛闷,我們對(duì)Exception的處理就要分化了憋槐,可能會(huì)派生出ServiceException1,ServiceException2兩個(gè)異常類(lèi)淑趾,另外對(duì)于可能發(fā)生的代碼問(wèn)題(空指針阳仔、越界等bug),我們還要捕獲RuntimeException扣泊,這又造成了Controller層的耦合和摻雜的業(yè)務(wù)邏輯近范。
有沒(méi)用什么辦法可以規(guī)避這一問(wèn)題呢?
可以借助Spring的ControllerAdvice采用AOP機(jī)制可以對(duì)Controller方法的異常進(jìn)行統(tǒng)一攔截延蟹,并可以針對(duì)不同類(lèi)型的Exception進(jìn)行不同的處理评矩。

  @ControllerAdvice
  public class ExceptionAdvice {

  private static Logger logger =     
  LoggerFactory.getLogger(AlgoController.class);

  @ExceptionHandler({ RuntimeException.class })
  @ResponseBody
  public ResultSet handleRuntimeException(Exception e){
      logger.error("RuntimeException", e);
      ResultSet result = ResultSet.valueOf(ResultSetCode.SYSTEM_ERROR);
      result.setResult("服務(wù)器開(kāi)小差了");
      return result;
  }

  @ExceptionHandler({ ServiceException.class })
  @ResponseBody
  public ResultSet handleServiceException(ServiceException e){
      logger.warn("ServiceException", e);
      ResultSet result = ResultSet.valueOf(ResultSetCode.PARAM_ERROR);
      result.setResult(e.getReason());
      return result;
  }
}

使用異常的注意事項(xiàng)

  1. 不要通過(guò)異常來(lái)編寫(xiě)業(yè)務(wù)邏輯(使用異常進(jìn)行條件判斷,性能低阱飘,且難維護(hù))

  2. 注意日志的維護(hù)斥杜,捕獲異常(包括在拋出其它異常),要留下詳細(xì)合適的Log信息(也可以將之前的異常傳入拋出的異常)

  3. 注意在finally中釋放系統(tǒng)資源

  4. 注意try-catch的性能問(wèn)題沥匈,比如不要將其放入循環(huán)內(nèi)

  5. 不要捕獲unchecked異常(不可恢復(fù)的場(chǎng)景蔗喂、程序錯(cuò)誤)
    ...

異常的性能問(wèn)題

在對(duì)性能敏感的場(chǎng)景,異常對(duì)性能會(huì)有一定影響高帖。
下面分析下一場(chǎng)對(duì)性能的影響問(wèn)題:

  1. 拋出異常缰儿,并捕獲異常
  2. 獲得異常的調(diào)用棧
  3. 打印異常日志
    其中,最耗費(fèi)性能的肯定是打印日志散址,比獲得異常調(diào)用棧要高一個(gè)量級(jí)乖阵,而2是1的數(shù)倍,當(dāng)然拋出異常并捕獲異常的性能損耗要遠(yuǎn)高于分支判斷(高幾個(gè)量級(jí))预麸。

這里猜測(cè)異常對(duì)于性能的影響主要來(lái)源于對(duì)調(diào)用棧的記錄瞪浸。

不過(guò),不能因噎廢食吏祸,一般情況下默终,合理使用異常,不會(huì)對(duì)系統(tǒng)造成性能負(fù)擔(dān)犁罩,反而會(huì)讓代碼更整潔清晰齐蔽,邏輯合理。

參考文獻(xiàn):

  1. https://mp.weixin.qq.com/s/9KXrpkJ13qwWpsLPzAz33w(優(yōu)雅處理Java異常)
  2. https://www.cnblogs.com/lq147760524/p/8475531.html(Java異常及日志注意事項(xiàng))
  3. https://blog.csdn.net/hustspy1990/article/details/78075394(對(duì)java 異常性能問(wèn)題的分析)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末床估,一起剝皮案震驚了整個(gè)濱河市含滴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丐巫,老刑警劉巖谈况,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勺美,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡碑韵,警方通過(guò)查閱死者的電腦和手機(jī)赡茸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)祝闻,“玉大人占卧,你說(shuō)我怎么就攤上這事×” “怎么了华蜒?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)豁遭。 經(jīng)常有香客問(wèn)我叭喜,道長(zhǎng),這世上最難降的妖魔是什么蓖谢? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任捂蕴,我火速辦了婚禮,結(jié)果婚禮上闪幽,老公的妹妹穿的比我還像新娘啥辨。我一直安慰自己,他們只是感情好沟使,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布委可。 她就那樣靜靜地躺著渊跋,像睡著了一般腊嗡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拾酝,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天燕少,我揣著相機(jī)與錄音,去河邊找鬼蒿囤。 笑死客们,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的材诽。 我是一名探鬼主播底挫,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼脸侥!你這毒婦竟也來(lái)了建邓?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤睁枕,失蹤者是張志新(化名)和其女友劉穎官边,沒(méi)想到半個(gè)月后沸手,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡注簿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年契吉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诡渴。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捐晶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出玩徊,到底是詐尸還是另有隱情租悄,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布恩袱,位于F島的核電站泣棋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏畔塔。R本人自食惡果不足惜潭辈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望澈吨。 院中可真熱鬧把敢,春花似錦、人聲如沸谅辣。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)桑阶。三九已至柏副,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蚣录,已是汗流浹背割择。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萎河,地道東北人荔泳。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像虐杯,于是被迫代替她去往敵國(guó)和親玛歌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,180評(píng)論 25 707
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法擎椰,類(lèi)相關(guān)的語(yǔ)法支子,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法确憨,異常的語(yǔ)法译荞,線(xiàn)程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,641評(píng)論 18 399
  • 林相有一家店瓤的,開(kāi)在西郊,知道的人不是很多吞歼,但是客流量也夠林相每天吃上熱飯圈膏。 這家書(shū)店開(kāi)了很久,林相是日本人篙骡,四年前...
    涼生荒年閱讀 319評(píng)論 0 0
  • 體驗(yàn)入:要想讓別人做到首先自己要做到稽坤。 找核心:以身作則 轉(zhuǎn)身用:在大大小小團(tuán)隊(duì)中,各級(jí)領(lǐng)袖都要付出比別人多糯俗,并引...
    熊毅濱1349閱讀 247評(píng)論 0 0
  • 描述 我們的iOS客戶(hù)端有個(gè)頁(yè)面尿褪,底層是UIPageController,也就是有個(gè)UIScrollview在底層...
    xiaotei閱讀 3,120評(píng)論 1 0