spring-boot自定義異常返回


上文測試開發專題:spring-boot統一異常捕獲我們討論了java異常以及如何使用Spring-Boot捕獲異常,但是沒有去說捕獲異常后該如何進一步處理,這篇文章我們將對這個遺留的問題進行討論.

統一錯誤響應定義

我們希望在程序發生異常的時候,能夠給用戶返回一個比較友好且明確的信息,對於api接口來說,一種比較好的格式是json,類似於下面這種格式

{
	"code": "10001", "message": "消息", "uri":"Get /v2/banner" } 

所以需要一個對象來描述這種數據格式:

public class UnifyResponse { private int code; private String message; private String requestUri; public UnifyResponse(int code, String message, String requestUri){ this.code = code; this.message = message; this.requestUri = requestUri; } } 

錯誤響應處理

上文我們談到從開發者的角度來說,異常分為已知異常和未知異常,針對不同的異常使用不同的異常處理函數進行處理,我們之前定義兩個處理函數

@ControllerAdvice public class GlobalExceptionAdvice { /** * 處理未知異常 * @param req * @param ex */ @ExceptionHandler(value = Exception.class) public void handleHttpException(HttpServletRequest req, Exception ex){ System.out.println("發生異常了"); } /** * 處理已知異常 * @param req * @param ex */ @ExceptionHandler(value = HttpException.class) public void handleHttpException(HttpServletRequest req, HttpException ex){ System.out.println("發生了 HttpException"); } } 

當未知異常發生時,需要將異常信息存儲進 UnifyResponse,序列化后返回給用戶

@ExceptionHandler(value = Exception.class) public UnifyResponse handleHttpException(HttpServletRequest req, Exception ex){ String uri = req.getRequestURI(); String method = req.getMethod(); System.out.println(ex.getMessage()); return new UnifyResponse(9999, "服務器錯誤", method + " " + uri); } 

對於未知異常我們也不知道發生了什么,所以這里的code碼就定義一個通用的,雖然Exception里面有message,但是這里不建議將這個異常里的message返回給用戶,這位可能涉及到代碼結構的一些東西,而且即使將這個信息返回給前端,他也不知道是啥問題,沒什么意義,所以可以將這個message寫到日志里,方便后面問題查詢。

返回給用戶的message可以自定義一個通用的,比如服務器錯誤什么的。

我們來測試一下,在Controller里拋出一個Exception:

 @RequestMapping(value = "/v2/banner", method = {RequestMethod.GET}) public String test() throws Exception{ throw new Exception("我拋出來的"); } 

然后再瀏覽器里訪問,發現出錯了

image-20200510110158872

這里的這個異常,看不太懂,回到異常處理方法當中去,我們直接是返回UnifyResponse對象,如果這里返回的是一個字符串,那會不會出錯呢,再是試一下看看,結果還是會報這個錯,也就是說無論這里返回自定義對象還是字符串,都會出現問題,那就是說spring-boot壓根兒就可能不識別我們返回的東西。

在spring-boot里有一個注解@ResponseBody,可以將我們的返回值,綁定的響應的body上,我們來試一下看看能否解決這個問題。

會發現,上面改的返回String是可以成功的,但是返回UnifyResponse對象還是報錯,而且報錯和之前的還不一樣

image-20200510114815064

剛才報的還是404的錯誤,現在變成了500,哪里錯了呢。

我們來看一下UnifyResponse的定義,我們定義了三個私有的成員變量,但是確沒有定義getter方法,那在序列化的時候是無法獲取到成員變量的值的,所以報錯,這里我們加上:

image-20200510152644882

然后在運行程序,訪問路由:

image-20200510115919104

返回的響應就和我們預期的一樣了,但是從上面的圖中,看到返回的狀態碼是200,這顯然是不對的,因為服務器已經出錯了,狀態碼應該是500,所以這里要對狀態碼進行自定義。

自定義狀態碼

spring-boot提供了兩種可以自定義狀態碼的方式:

注解

直接在異常處理函數上標記一個叫做

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)並制定狀態碼的枚舉值

image-20200510152620279

重啟程序,訪問路由:

image-20200510121218008

可以看到狀態碼已經變成500了。

上面使用注解的的形式雖然能夠實現我們的目的,但是這種方式不太靈活,,這里很多的response的設置都是spring-boot幫我們做了,如果需要做一些自定義就不是太方便,接下來的這種方式確可以讓我們通過代碼靈活的進行控制。

ResponseEntity

ResponseEntity是一個泛型類,是可以直接return回去的,可以設置很多屬性,包括status、headers、body等。

用ResponseEntity來自定義已知異常處理方法的返回信息:

image-20200510152555316

然后再Controller里拋出一個NotFoundException,重新運行程序,訪問路由:

image-20200510152800514

可以看到也能夠返回正確的狀態碼。

總結

本篇文章我們介紹了,定義錯誤響應以及如何返回自定義的錯誤信息,多種方式進行定制狀態碼,但是我們在文章的錯誤信息都是硬編碼在代碼里的,這樣很不好管理,所以下篇文章我們將介紹如何對錯誤信息管理,敬請關注!!!

本文鏈接:https://www.immortalp.com/articles/2020/05/10/1589096782703.html


免責聲明!

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



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