前言:
最近使用springmvc寫了很多rest api, 以爲真是一個好框架. 以前描述的幾篇關於rest api的文章, 其實仍是不夠完善. 好比當遇到參數缺失, 類型不匹配的狀況時, 直接拋出異常, 返回的內容是400+的錯誤頁面, 而不是json內容, 這讓移動端的調用方很難處理.
本文主要講述對於rest api, springmvc對異常的解決處理方案.html
系列整理:
springmvc學習筆記系列的文章目錄:
• idea建立springmvc項目
• 面向移動端的REST API
• Jackson的使用和定製
REST API的設計原則博文
• 移動互聯網實戰—Web Restful API設計和基礎架構java
場景構造:
大背景, 咱們已藉助使用Jackson框架和註解@ResonseBody來實現pojo對象以json形式返回.
先來構造幾個案例, 來描述咱們所要解決的問題.
共同的測試代碼:spring
@Controller @RequestMapping("/math") public class TestController { @RequestMapping(value="/div", method= RequestMethod.GET) @ResponseBody public int div(@RequestParam("a") int a, @RequestParam("b") int b) { // *) div zero error return a / b; } }
1). 場景一(參數缺失, 類型不匹配)
case 1:
http://localhost:8080/math/div?a=10
參數b缺失, 返回400錯誤頁
case 2:
http://localhost:8080/math/div?a=10&b=hehe
參數b類型不對, 類型轉換失敗
咱們的但願是, 將這些參數缺乏/類型不匹配的異常, 以JSON串的形式返回, 而不是以400的錯誤頁面返回.
2). 場景二(業務代碼拋出異常)
case 1:
http://localhost:8080/math/div/a=10&b=0
發生除零異常
內部拋出業務異常很是常見, 防不勝防, 返回是500+的錯誤頁面.json
解決方案:
基於上文的場景, 遇到異常時, 返回的都是400+/500+的錯誤頁面, 一方面客戶端sdk解析和處理麻煩, 另外一方面泄露了內部的錯誤細節. 那是否一種辦法攔截異常, 並返回本身定義的錯誤數據格式呢?
答案是確定的, springmvc引入了織入@ControlAdvice.
其對異常的處理, 很是的方便, 可簡單參考以下sample.api
@ControllerAdvice public class RestApiControlAdvice { @ExceptionHandler(value=RuntimeException.class) @ResponseBody public String handle(RuntimeException e) { // *記入異常日誌 return e.getMessage(); } @ExceptionHandler(value=Exception.class) @ResponseBody public String handle(Exception e) { // *記入異常日誌 return e.getMessage(); } }
經過結合註解@ExceptionHanlder, 來定義具體的異常處理, 以及返回的結果.
這邊須要注意的是, @ExceptionHandler可定義多個, 當多個匹配時, 按編寫最先的處理函數優先處理. 這邊就像try/catch那種常見的狀況了, 既順序敏感. 最佳實踐, 須要把處於頂層的異常類擱置到代碼最尾端.
固然對於參數缺失/類型不匹配的處理, 能夠以下定義.微信
@ExceptionHandler(value=MissingServletRequestParameterException.class) @ResponseBody public TResult<Void> handle(MissingServletRequestParameterException e) { return "Miss parameter " + e.getParameterName() + ":" + e.getParameterType(); } @ExceptionHandler(value= TypeMismatchException.class) @ResponseBody public String handle(TypeMismatchException e) { return e.getErrorCode() + ", required type: " + e.getRequiredType() + ", but value: " + e.getValue(); }
業務上的異常代碼, 每每能夠抽象出一個異常基類.架構
總結:
springmvc的入門和上手確實很是快, 但要真正的理解. 確實仍是須要花功夫, 這邊只是簡單介紹一下, 並無深刻源碼. 但願未來有一天有機會講講背後的技術原理.mvc
公衆號&遊戲站點:
我的微信公衆號: 木目的H5遊戲世界
我的遊戲做品集站點, www.mmxfgame.com, 請點擊訪問: http://120.26.221.54/. app