首頁  >  問答  >  主體

javaWeb项目使用aop处理异常?

1.dao层我是直接抛出异常,都是比较“底层”的异常,比如DataAccessException. 不捕获的原因是,假如service调用了多个dao方法,其中有一个发生了异常,如果该dao方法自己捕获了又没有重新抛出来。这时候,service事务没法回滚,因为它以为都执行正确了。
2.在service里, 调用的dao方法有可能抛出DataAccessException的话,那么service也不捕获。因为DataAccessException是runtime异常,无需强制try-catch,况且,如果你捕获了又没有抛出来,配置的事务没法感知到,因为默认只处理runtime异常,当然可以配置。
3.还可以这样,在service方法里,dao方法外面直接try-catch(Throwable e). 然后重新抛出自定义的业务相关的异常。比如TopicUpdateException.

问题:上面1,2,3我对dao层,service层的方法处理是否合理。2,3哪种更好些?为什么?

4.接上面,这个自定义的业务异常的粒度要控制到什么级别?能否举个例子
5.上面2,3 我都是用的aop统一处理异常。我看大部分人也推荐这么做。因为service层各个方法里catch里的逻辑大都相似。使用aop统一处理,好处是显而易见的。我想知道,有什么弊端吗?因为我发现公司项目几乎没有这么做的。都是直接try-catch,返回结果。要么就是上面2里提到的不捕获。出了异常反正可以记录在log里

请大家帮忙看看

黄舟黄舟2726 天前801

全部回覆(4)我來回復

  • 迷茫

    迷茫2017-04-18 09:27:59

    謝邀! 不過我得聲明我不是專家|_|

    問題:上面1,2,3我對dao層,service層的方法處理是否合理。 2,3哪一種比較好些?

    首先我同意你在1, 2, 3步驟的分析與理解。其次,我認為3的处理更为妥帖,因为service层就已经不是纯粹的数据交互,而是包含了一系列业务逻辑的操作,通过捕获Throwable然後再拋出更有意義的(能準確描述錯誤的)異常,無論是記入日誌還是事物處理,這個對於後續可能存在的補救/錯誤排查更合適

    4.接上面,這個自訂的業務異常的粒度要控製到什麼級別?能否舉例

    粒度取決於需求,譬如你只想做回滾,那麼只要能夠定位到什麼service错了对你来说就够了。但如果还希望进一步排查root cause,那是不是異常信息裡再多一些關於源錯誤的描述更好些?

    5.上面2,3 我都是用的aop統一處理異常。我看大部分人也推薦這麼做。因為service層各個方法裡catch裡的邏輯大都相似。使用aop統一處理,好處是顯而易見的。我想知道,有什麼弊端嗎?因為我發現公司專案幾乎沒有這麼做的。都是直接try-catch,回傳結果。要嘛就是上面2裡提到的不捕獲。出了異常反正可以記錄在log裡

    先談你們公司為什麼沒那麼做,這可能是歷史原因,之前搭建框架的人對aop认识不足,或者把个人喜好带到了工作中导致选择了直接到处try catch(这种方式简单粗暴,最易掌握),aop是算是一種設計範式,無論架構師還是程式設計師,要想熟練並且運用自如還是需要學習成本的(這可能算是弊端吧)。如果你對原因有興趣,最好找幾個老資格同事私底下聊聊看,說不定好能套出些其他內幕^^

    關於"出了異常反正可以記錄在log裡",想法沒有錯,但真的在海量日誌裡處理過錯誤訊息的人是會有體會的。明明可以統一處理,卻沒做,這算是設計缺陷或失誤。不是解決問題最有效的方案

    我是外行,輕點拍磚^^

    回覆
    0
  • 天蓬老师

    天蓬老师2017-04-18 09:27:59

    使用Spring AOP對異常進行統一處理,當然是第三種方法更好了。使用Spring AOP對serivce層拋出的異常進行攔截,記錄所有未處理的異常日誌,並將所有未處理異常轉換成統一自訂的系統異常,以便讓controller層或Rpc層能夠將這些自訂的異常資訊回饋到前端,在瀏覽器端進行展示。
    不要忘了,使用Spring AOP對異常進行攔截,其真正作用是實現:將異常的處理邏輯和正常的處理邏輯進行解耦。所以你說異常的粒度控制在什麼層次?這個是根據你的業務邏輯來的。諸如,操作資料庫增刪改查失敗?呼叫外部介面失敗?其他異常資訊等等。 
    你們公司的方式是不規範的,不合適的。處理日誌時,需要在每一個try-catch區塊包含一些處理程式碼,有時候異常處理的程式碼比正常執行程式碼還多,污染正常執行程式碼。 異常處理程式碼散落,修改起來時非常麻煩。無法對某些異常進行統一處理和修改。
    Service中的商業方法命名不按照事前定義好的規則進行命名的話,AOP是攔截不到的。也就是說事務控制是無法載入的。這些命名的規範什麼的需要在設定檔中指定。

    回覆
    0
  • 天蓬老师

    天蓬老师2017-04-18 09:27:59

    我們都是在controller層做aop異常處理的
    異常分為非ajax異常和ajax異常, 因為我們是使用jquery,沒有做到前後端完全分離,有的前端數據是後端直接渲染

    1. ajax異常: 在header中包含X-Requested-With來判斷

    2. 非ajax異常: ajax異常之外的
      肯定你前台顯示給客戶錯誤的方式是不同的, 所以在Interceptor(filter)(aop)中分別處理

    在service類別的每個方法中, 沒有說整個用try catch包住的, 太二了,異常分為你控制不了的比如數據庫異常,空指針什麼的, 這些都不用catch的, 在service中是根據業務中的異常業務拋出, 例如用戶名重複了, 我就throw 一個BizException("用戶名重複"),其中BizException是繼承了RuntimeException的

    lz說的aop來處理異常, 我不知道你是在service層還是controller層, 顯然按照我上面的分析應該是在controller層做的

    如果我這個不是最佳答案,就太沒天理了

    回覆
    0
  • 怪我咯

    怪我咯2017-04-18 09:27:59

    你是用spring mvc的吧? spring mvc有全域的異常處理,你可以去搜下,具體的我在手機上不能方便的表達出來。

    回覆
    0
  • 取消回覆