最近涉及到與先後端的數據對接,按道理來講沒一點壓力結果被一前端童鞋帶坑裏去了(不過也是好久沒寫過這種先後端分離進行聯調的事情了,若是是一我的全套弄的話就不會出現下面問題)。前端
進入正文,跟前端進行數據聯調時,別人聯調都正常,到聯調個人接口(進行數據獲取)就出現了問題。web
下面進行異常場景還原(後端環境:Spring MVC4.0.5):spring
一、前端訪問我這邊的接口拋出錯誤碼:405 Method not allowed 。當時就感受奇怪,我本身用postman都能調通啊,爲何你那邊不能容許訪問呢。看到這個錯誤碼,因而我就拋出兩個問題給他:json
而後他堅決果斷的說都是。
二、因而我看下後端請求的日誌,SpringMVC日誌提示:「[org.springframework.web.servlet.PageNotFound] >>> Request method 'POST' not supported」 。 後端
提示這個錯誤,我就納悶了。條件反射讓我想起是否是在@RequestMapping中Method 沒有指定爲post? 其實我指定了post方法的,這個確定排除了。緩存
@RequestMapping(value = "/home/test", method = RequestMethod.POST) @ResponseBody public Object test(@RequestBody UserEntity userEntity) { return "1234"; }
難道真的是我後端的問題?查了網上不少問題一堆不靠譜:(,一直沉迷於Request method 'POST' not supported這個信息沒法自拔,難道這配置不支持post方法?。因而就嘗試瞭如下手段:mvc
a、ResourceHttpRequestHandler在springMVC配置文件配置強制支持post方法。可想而知,ResourceHttpRequestHandler針對靜態資源的獲取及其緩存設置。很明顯不符合場景,試了也是白試。若是你這種場景請參考這裏獲取對你有幫助:https://stackoverflow.com/questions/15588001/spring-not-accept-post-request-under-mvcresources-how-to-fix-that。app
b、嘗試將RequestMapping中請求的方法改爲get,前端也用get請求,並無用。前後端分離
三、嘗試了上面方法後無果,有位前輩說不妨你跟蹤下SpringMVC中日誌代碼。post
第一步:查看PageNotFound是否存在對應的類(這一步其實一出現我就查看是沒有的),怎麼驗證它是否存在呢?很簡單:在代碼中輸入它看是否有對應的引用包。
第二步:第一步最直接的入口失敗,因而想到了SpringMVC的核心Servlet:DispatcherServlet, 而它的核心方法則是:doDispatch,因而在方法中進行斷點調試找到出錯緣由。通過調試後,終於發現問題所在,發如今解析json是實體的屬性出錯,以下圖:
上述案例是說不能解析namqe這個屬性,而我UserEntity對象中的屬性是name,因此解析類就拋出異常(至於在哪一步解析出錯,這就不一一說了)。
通過上面一步一步的探索終於找到問題的所在:原來是前端童鞋傳json的時候,把參數名稱弄錯了。
四、拓展
雖然問題解決了,可是爲啥Spring MVC 爲啥拋出那樣的日誌,而不是具體的錯誤信息呢?若是是具體的錯誤信息那不簡單明瞭嘛,也不至於花了這麼時間去定位問題所在。因而繼續調試看看這個錯誤信息爲何被轉換了?看上面圖的971行,最終結果都會進入到這個方法processDispatchResult,而它的第一步就是檢測是否有異常,若是有異常則先處理異常:
裏面流程也不一一顯示了,直接跳到具體解析異常的類:DefaultHandlerExceptionResolver,咱們看看這個類中有什麼又是怎麼處理異常的。
看到上圖就應該想到以前提示的日誌爲何有[org.springframework.web.servlet.PageNotFound],而找不到對應的類了吧,由於它只是一個日誌的Event_Name。
繼續跟蹤:最終它是走入了HttpMessageNotReadableException類,表示讀取信息錯誤。
繼續進入handleHttpMessageNotReadable方法,看到這裏就知道結果了,它把原來的錯誤信息給修改並返回了。
另外這裏不是真的返回信息,上面錯誤信息返回以後還會再次進入DispatcherServlet類從新又走了一遍,因此錯誤信息又從新判斷一次最終進入了下面這個方法,真正的輸入日誌的地方在這:
因此這個是Spring MVC 4.0.5.RELEASE版本的問題,升級到4.2.0以上就不會拋出這個問題,它會識別能識別的參數繼續運行,不會拋出錯誤。
針對這種405錯誤,總結一下幾點:
一、首先第一個須要確認請求方法類型是否一致?
二、請求數據類型 和 接收的數據類型是否一致?
三、請求參數是否正確?
以上都正確的話,而後在具體問題具體分析,一步一步跟蹤纔是最有效的。
趕上問題要冷靜,盲目從醫只會浪費時間,須要對症下藥,一步一步來。