spring-boot 自定義異常

需求:小程序登陸時,後臺須要將異常拋出,並將錯誤信息交給前臺。spring

1、後臺異常處理

1.自定義微信登陸異常

public class WechatLoginException extends RuntimeException {
    /**
     * @Description 自定義狀態碼
     * 510: 未找到該學號或該學號的狀態已凍結
     * 509: 該學號已被其餘微信賬號綁定,請聯繫老師或者管理員解除綁定
     * 508: 該微信賬號已綁定學號,請解除綁定後從新登陸
     **/
    private HttpStatus status = null;
    public WechatLoginException(String message, HttpStatus httpStatus) {
        super(message);
        status = httpStatus;
    }

     public HttpStatus getStatus() {
        return status;
    }
}

2.userService拋出異常

if (student.getWechat() != null && !student.getWechat().getOpenid().equals(openId)) {
         throw new WechatLoginException("該學號已被其餘微信賬號綁定,請聯繫老師或者管理員解除綁定", HttpStatus.valueOf(509));
    }

3. 全局異常處理

// 處理微信登陸的異常
@ExceptionHandler(WechatLoginException.class)
public ResponseEntity<JsonErrorResult> wechatLoginHandler(HttpServletRequest request, WechatLoginException e){
    logger.error("微信登陸異常:---Host {} invokes url {} ERROR: {}", request.getRemoteHost(), request.getRequestURL(), e.getMessage());
    return new ResponseEntity<>(new JsonErrorResult(request, e), e.getStatus());
}

存在的問題

後來,潘老師和張喜碩學長評論說這樣寫很差,由於開放異常信息,異常的狀態碼只靠註釋約束,當返回未知狀態碼前臺不知道如何處理。小程序

2、改進

根據潘老師的建議,作出以下修改:微信

1. 添加異常狀態枚舉

public enum  HttpStatusEnum {
    StudentNotFound("未找到該學生", 601),
    StudentIsForzen("該學生的狀態已凍結", 602),
    StudentISBinded("該學號已被其餘微信賬號綁定,請聯繫老師或者管理員解除綁定", 603),
    WecahtIsBinded("該微信賬號已綁定學號,請解除綁定後從新登陸", 604);

    private String description;
    private int code;

    private HttpStatusEnum (String description, int code) {
        this.description = description;
        this.code = code;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }
}

2. 異常類修改,構造時傳入枚舉體

public class WechatLoginException extends RuntimeException {
    private int code;   // 異常狀態碼
    public WechatLoginException(HttpStatusEnum httpStatusEnum) {
        super(httpStatusEnum.getDescription());
        code = httpStatusEnum.getCode();
    }

    public int getCode() {
        return code;
    }
}

3. service拋出異常

throw new WechatLoginException(HttpStatusEnum.StudentISBinded);

4. 全局異常處理

//處理微信登陸的異常
@ExceptionHandler(WechatLoginException.class)
public ResponseEntity<JsonErrorResult> wechatLoginHandler(HttpServletRequest request, WechatLoginException e){
    logger.error("微信登陸異常:---Host {} invokes url {} ERROR: {}", request.getRemoteHost(), request.getRequestURL(), e.getMessage());
    return new ResponseEntity<>(new JsonErrorResult(request, e), e.getStatus());
}

而後這一步就出現了問題,使用ResponseEntity返回異常信息時,第二個參數須要傳入HttpStatus,如圖:
clipboard.pngspring-boot

而張喜碩學長指出,spring-boot的HttpStatus枚舉是不可擴展的,即我沒法經過繼承來增長自定義的http狀態碼
clipboard.png測試

因此,此時陷入一個僵局,要麼放棄使用自定義狀態碼,要麼放棄使用ResponseEntity,這時,張喜碩學長說了一下他的解決方案,即不返回ResponseEntity了,而是注入HttpServletResponse,調取setStatus()直接改返回的狀態碼:this

// 處理微信登陸的異常
@ExceptionHandler(value = WechatLoginException.class)
public String WechatLoginExceptionHandler(HttpServletRequest request, HttpServletResponse response, WechatLoginException e) throws IOException {
    logger.error("微信登陸異常:---Host {} invokes url {} ERROR: {}", request.getRemoteHost(), request.getRequestURL(), e.getMessage());
    response.setStatus(e.getCode());
    return e.getMessage();
}

而後在小程序端測試,發現果真狀態碼能夠變成了自定義的了
clipboard.png
接着,就是在小程序端添加異常處理:url

public static handleHttpException(response: RequestSuccessCallbackResult) {
    let result = '';
    switch (response.statusCode) {
        case 601:
            result = '未找到該學生';
            break;
        case 602:
            result = '該學生的狀態已凍結';
            break;
        case 603:
            result = '該學號已被其餘微信賬號綁定,請聯繫老師或者管理員解除綁定';
            break;
        case 604:
            result = '該微信賬號已綁定學號,請解除綁定後從新登陸';
    }
    // 若是異常信息不爲空,則顯示提示信息,而且拋出異常
    if (result != '') {
        // 顯示異常
        wx.showToast({
            title: result,
            icon: "none",
            duration: Request.duration
        });
        throw response;
    }
 }

最後的效果:spa

clipboard.png

總結

總得來講,此次收穫仍是挺多的,遇到了很多問題,也對一些知識的盲區進行了探索和挖掘。雖然實現了需求,但以爲小程序的異常處理仍是有些生硬,還有改進的餘地。code

相關文章
相關標籤/搜索