springmvc學習筆記--REST API的異常處理


 

前言:
  最近使用springmvc寫了不少rest api, 覺得真是一個好框架. 之前描述的幾篇關於rest api的文章, 其實還是不夠完善. 比如當遇到參數缺失, 類型不匹配的情況時, 直接拋出異常, 返回的內容是400+的錯誤頁面, 而不是json內容, 這讓移動端的調用方很難處理.
  本文主要講述對於rest api, springmvc對異常的解決處理方案.

系列整理:
  springmvc學習筆記系列的文章目錄:
  • idea創建springmvc項目
  • 面向移動端的REST API
  • Jackson的使用和定制
  REST API的設計原則博文
  • 移動互聯網實戰—Web Restful API設計和基礎架構

場景構造:
  大背景, 我們已借助使用Jackson框架和注解@ResonseBody來實現pojo對象以json形式返回.
  先來構造幾個案例, 來描述我們所要解決的問題.
  共同的測試代碼:

@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+的錯誤頁面.

解決方案:
  基於上文的場景, 遇到異常時, 返回的都是400+/500+的錯誤頁面, 一方面客戶端sdk解析和處理麻煩, 另一方面泄露了內部的錯誤細節. 那是否一種辦法攔截異常, 並返回自己定義的錯誤數據格式呢?
  答案是肯定的, springmvc引入了織入@ControlAdvice.
  其對異常的處理, 非常的方便, 可簡單參考如下sample.

@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的入門和上手確實非常快, 但要真正的理解. 確實還是需要花功夫, 這邊只是簡單介紹一下, 並沒有深入源碼. 希望將來有一天有機會講講背后的技術原理.

公眾號&游戲站點:
  個人微信公眾號: 木目的H5游戲世界
  
  個人游戲作品集站點,
 www.mmxfgame.com 請點擊訪問http://120.26.221.54/.  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM