本篇文章給大家分享的是有關(guān)常見的SpringMVC故障排查及解決方案是什么,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
成都創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括瑪沁網(wǎng)站建設(shè)、瑪沁網(wǎng)站制作、瑪沁網(wǎng)頁制作以及瑪沁網(wǎng)絡(luò)營(yíng)銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,瑪沁網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到瑪沁省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!相信我們每個(gè)人在SpringMVC開發(fā)中,都遇到這樣的問題:當(dāng)我們的代碼正常運(yùn)行時(shí),返回的數(shù)據(jù)是我們預(yù)期格式,比如json或xml形式,但是一旦出現(xiàn)了異常(比如:NPE或者數(shù)組越界等等),返回的內(nèi)容確實(shí)服務(wù)端的異常堆棧信息,從而導(dǎo)致返回的數(shù)據(jù)不能使客戶端正常解析; 很顯然,這些并不是我們希望的結(jié)果。
我們知道,一個(gè)較為常見的系統(tǒng),會(huì)涉及控制層,服務(wù)(業(yè)務(wù))層、緩存層、存儲(chǔ)層以及接口調(diào)用等,其中每一個(gè)環(huán)節(jié)都不可避免的會(huì)遇到各種不可預(yù)知的異常需要處理。如果每個(gè)步驟都單獨(dú)try..catch會(huì)使系統(tǒng)顯的很雜亂,可讀性差,維護(hù)成本高;常見的方式就是,實(shí)現(xiàn)統(tǒng)一的異常處理,從而將各類異常從各個(gè)模塊中解耦出來;
在Spring中常見的全局異常處理,主要有三種:
(1)注解ExceptionHandler
(2)繼承HandlerExceptionResolver接口
(3)注解ControllerAdvice
在后面的講解中,主要以HTTP錯(cuò)誤碼:400(請(qǐng)求無效)和500(內(nèi)部服務(wù)器錯(cuò)誤)為例,先看一下測(cè)試代碼以及沒有任何處理的返回結(jié)果,如下:
(圖1:測(cè)試代碼)
(圖2:沒有異常的錯(cuò)誤返回)
注解ExceptionHandler作用對(duì)象為方法,最簡(jiǎn)單的使用方法就是放在controller文件中,詳細(xì)的注解定義不再介紹。如果項(xiàng)目中有多個(gè)controller文件,通??梢栽赽aseController中實(shí)現(xiàn)ExceptionHandler的異常處理,而各個(gè)contoller繼承basecontroller從而達(dá)到統(tǒng)一異常處理的目的。因?yàn)楸容^常見,簡(jiǎn)單代碼如下:
(圖3:Controller中的ExceptionHandler使用)
在返回異常時(shí),添加了所屬的類名,便于大家記憶理解。運(yùn)行看一下結(jié)果:
(圖4:添加ExceptionHandler之后的結(jié)果)
優(yōu)點(diǎn):ExceptionHandler簡(jiǎn)單易懂,并且對(duì)于異常處理沒有限定方法格式;
缺點(diǎn):由于ExceptionHandler僅作用于方法,對(duì)于多個(gè)controller的情況,僅為了一個(gè)方法,所有需要異常處理的controller都繼承這個(gè)類,明明不相關(guān)的東西,強(qiáng)行關(guān)聯(lián),不太好。
這里雖說是ControllerAdvice注解,其實(shí)是其與ExceptionHandler的組合使用。在上文中可以看到,單獨(dú)使用@ExceptionHandler時(shí),其必須在一個(gè)Controller中,然而當(dāng)其與ControllerAdvice組合使用時(shí)就完全沒有了這個(gè)限制。換句話說,二者的組合達(dá)到的全局的異常捕獲處理。
(圖5:注解ControllerAdvice異常處理代碼)
在運(yùn)行之前,需將之前Controller中的ExceptionHandler注釋掉,測(cè)試結(jié)果如下:
(圖6:注解ControllerAdvice異常處理結(jié)果)
通過上面結(jié)果可以看到,異常處理確實(shí)已經(jīng)變更為ExceptionHandlerAdvice類。這種方法將所有的異常處理整合到一處,去除了Controller中的繼承關(guān)系,并且達(dá)到了全局捕獲的效果,推薦使用此類方式;
HandlerExceptionResolver本身SpringMVC內(nèi)部的接口,其內(nèi)部只有resolveException一個(gè)方法,通過實(shí)現(xiàn)該接口我們可以達(dá)到全局異常處理的目的。
(圖7:實(shí)現(xiàn)HandlerExceptionResolver接口)
同樣在執(zhí)行之前,將上述兩個(gè)方法的異常處理都注釋掉,運(yùn)行結(jié)果如下:
(圖8:實(shí)現(xiàn)HandlerExceptionResolver接口運(yùn)行結(jié)果)
可以看到500的異常處理已經(jīng)生效了,但是400的異常處理卻沒有生效,并且根沒有異常前的返回結(jié)果一樣。這是怎么回事呢?不是說可以做到全局異常處理的么?沒辦法要想知道問題的原因,我們只能刨根問底,往Spring的祖墳上刨,下面我們結(jié)合Spring的源碼調(diào)試,去需要原因。
大家都知道,在Spring中第一個(gè)收到請(qǐng)求的類就是DispatcherServlet,而該類中核心的方法就是doDispatch,我們可以在該類中打斷點(diǎn),進(jìn)而一步步跟進(jìn)異常處理。
參照如下的跟進(jìn)步驟,在processHandlerException中斷點(diǎn),跟蹤的結(jié)果如下圖:
(圖9:processHandlerException斷點(diǎn))
可以看到在圖中箭頭【1】處,在遍歷 handlerExceptionResolvers 進(jìn)而來處理異常,而在箭頭【2】處,看到handlerExceptionResolvers 中一共有4個(gè)元素,其中最后一個(gè)就是2.3方法定義的異常處理類
當(dāng)前的請(qǐng)求query請(qǐng)求,根據(jù)上述現(xiàn)象可以推測(cè)出,該異常處理應(yīng)該是在前3個(gè)異常處理中被處理了,從而跳過我們自定義的異常;帶著這樣的猜測(cè),我們F8繼續(xù)跟進(jìn),可以跟蹤到該異常是被第三個(gè),即DefaultHandlerExceptionResolver所處理。
DefaultHandlerExceptionResolver :SpringMVC默認(rèn)裝配了DefaultHandlerExceptionResolver,該類的doResolveException方法中主要對(duì)一些特殊的異常進(jìn)行處理,并將這類異常轉(zhuǎn)換為相應(yīng)的響應(yīng)狀態(tài)碼。而query請(qǐng)求觸發(fā)的異常為MissingServletRequestParameterException,其恰好也是被DefaultHandlerExceptionResolver所針對(duì)的異常,故會(huì)在該類中被異常捕獲。
到此真相大白了,可以看到我們的自定義類MyHandlerExceptionResolver確實(shí)可以做到全局處理異常,只不過對(duì)于query請(qǐng)求的異常,中間被DefaultHandlerExceptionResolver插了一腳,所以就跳過了MyHandlerExceptionResolver類的處理,從而出現(xiàn)400的返回結(jié)果。而對(duì)于calc請(qǐng)求,中間沒有阻攔,所以就達(dá)到了預(yù)期效果。
到此我們一共介紹了3類全局異常處理,按照上面的分析可以看出,實(shí)現(xiàn)HandlerExceptionResolver接口的方式是排在最后處理,那么@ExceptionHandler和@ControllerAdvice這兩個(gè)的順序誰先誰后呢? 將三類異常處理全部打開(之前注釋掉了),運(yùn)行一下看看效果:
(圖10:異常處理全放開運(yùn)行結(jié)果)
通過現(xiàn)象可以看到,Controller中單獨(dú)@ExceptionHandle異常處理排在了首位,@ControllerAdvice排在了第二位。嚴(yán)謹(jǐn)?shù)耐梢詫憘€(gè)Controller02,將query和calc復(fù)制過去,異常處理就不要了,這樣請(qǐng)求c02的方法時(shí),異常捕獲的所屬類名就都是@ControllerAdvice所在類了。
以上都是我們根據(jù)現(xiàn)象得到的結(jié)論,下面去Spring源碼去找“證據(jù)”。在圖9中,handlerExceptionResolvers中有4類處理器,而@ExceptionHandler和@ControllerAdvice的處理就在第一個(gè)ExceptionHandlerExceptionResolver中(之前斷點(diǎn)跟進(jìn)即可獲知)。繼續(xù)跟進(jìn)直到進(jìn)入ExceptionHandlerExceptionResolver類的doResolveHandlerMethodException方法,這里的HandlerMethod就是Spring將HTTP請(qǐng)求映射到指定Controller中的方法,而Exception就是需要被捕獲的異常;繼續(xù)跟進(jìn),看看使用這兩個(gè)參數(shù)到底干了什么事兒。
(圖11:doResolveHandlerMethodException斷點(diǎn))
繼續(xù)跟進(jìn)getExceptionHandlerMethod方法,發(fā)現(xiàn)有兩個(gè)變量可能就是問題的關(guān)鍵:exceptionHandlerCache和exceptionHandlerAdviceCache。首先,兩者的變量名很值得懷疑;其次,前者在代碼中看,明顯是通過類作為key,從而得到一個(gè)處理器(resolver),這恰好Controller中@ExceptionHandler處理規(guī)則相吻合;最后,這兩個(gè)Cache的處理順序,也符合之前的得到的結(jié)論。正如之前猜測(cè)的那樣,Spring中確實(shí)是優(yōu)先根據(jù)Controller類名去查找對(duì)應(yīng)的ExceptionHandler,沒有找到的話,再進(jìn)行@ControllerAdvice異常處理。
(圖12:兩個(gè)異常處理Cache )
如有興趣可繼續(xù)深入挖掘Spring的源碼,這里針對(duì) ExceptionHandlerExceptionResolver 簡(jiǎn)單做個(gè)總結(jié):
exceptionHandlerCache中包含Controller中的ExceptionHandler異常處理,處理時(shí)通過HandlerMethod得到Controller,進(jìn)而再找到異常處理方法,需要注意的是,其是在異常處理過程中put值的;
exceptionHandlerAdviceCache則是在項(xiàng)目啟動(dòng)時(shí)初始化的,大概思路是找到帶有@ControllerAdvice注解的bean,從而緩存bean中的ExceptionHandler,在異常處理時(shí)需要對(duì)齊遍歷查找處理,進(jìn)而達(dá)到全局處理的目的。
介紹了這么多,簡(jiǎn)單畫張圖總結(jié)一下。藍(lán)色的部分是Spring默認(rèn)添加的3類異常處理器,黃色部分是我們添加的異常處理以及其所被調(diào)用的位置和順序??纯茨睦镞€有不太清楚的,往回翻翻看(ResponseStatusExceptionResolver是針對(duì)@ResponseStatus注解,這里不再詳述)。
(圖13:異??偨Y(jié))
如果有需要將MyHandlerExceptionResolver提前處理,甚至排在ExceptionHandlerExceptionResolver之前,能做到么?答案是肯定的,在Spring中如果想將MyHandlerExceptionResolver異常處理提前,需要再實(shí)現(xiàn)一個(gè)Ordered接口,實(shí)現(xiàn)里面的getOrder方法即可,這里返回-1,將其放在最上面,這次咸魚終于可以翻身了。
(圖14:實(shí)現(xiàn)Ordered接口)
運(yùn)行看一下結(jié)果是不是符合預(yù)期,提醒一下,我們?nèi)齻€(gè)異常處理都是生效的,如下圖:
(圖15:實(shí)現(xiàn)Ordered接口運(yùn)行結(jié)果)
以上就是常見的SpringMVC故障排查及解決方案是什么,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道。
網(wǎng)頁題目:常見的SpringMVC故障排查及解決方案是什么-創(chuàng)新互聯(lián)
文章分享:http://jinyejixie.com/article34/cescse.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、標(biāo)簽優(yōu)化、網(wǎng)站建設(shè)、響應(yīng)式網(wǎng)站、做網(wǎng)站、App開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容