測試開發專題:spring-boot自定義異常返回

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

統一錯誤響應定義

咱們但願在程序發生異常的時候,可以給用戶返回一個比較友好且明確的信息,對於api接口來講,一種比較好的格式是json,相似於下面這種格式前端

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

因此須要一個對象來描述這種數據格式:java

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;
    }
}

錯誤響應處理

上文咱們談到從開發者的角度來講,異常分爲已知異常和未知異常,針對不一樣的異常使用不一樣的異常處理函數進行處理,咱們以前定義兩個處理函數spring

@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,序列化後返回給用戶json

@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寫到日誌裏,方便後面問題查詢。api

返回給用戶的message能夠自定義一個通用的,好比服務器錯誤什麼的。瀏覽器

咱們來測試一下,在Controller裏拋出一個Exception:服務器

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

而後再瀏覽器裏訪問,發現出錯了app

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
歡迎你們去 個人博客 瞅瞅,裏面有更多關於測試實戰的內容哦!!

相關文章
相關標籤/搜索