springBoot中全局異常處理,針對ajax響應(包括Rest接口請求)和頁面請求響應

完善的異常處理可以讓客戶端有一個良好的體驗,並且有利於定位出錯原因,幫助更好的解決問題。
SpringBoot 內置了一個 /error 處理,當拋出異常之後,會被轉到這個映射進行處理, 就是常見的 Whitelable Error Page
在這裏插入圖片描述
另外一種就是使用ajax請求,SpringBoot會返回如下的Json格式字符串信息‘’
在這裏插入圖片描述
原理很簡單,SpringBoot默認提供了程序出錯的結果映射路徑/error。這個/error請求是會在BasicErrorController中進行處理,其內部是通過判斷請求頭中的Accept的內容是否是text/html來區分是客戶端瀏覽器(瀏覽器通常默認自動發送請求頭內容Accept:text/html)還是客戶端接口的調用,以此來決定返回視圖還是JSON消息的內容,如下圖是BasicErrorController的底層源碼(在idea中三次按shift鍵將進入底層源碼)
在這裏插入圖片描述
在這裏插入圖片描述

定義一個簡單的error.html頁面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" >
<head>
    <meta charset="UTF-8"/>
    <title>error</title>
</head>
<body>
server error
<p th:text="${errorMessage}"/>
</body>
</html>

定義一個全局的GlobalRestExceptionHandler類來進行處理ajax響應和頁面請求響應

/**
 * @Description: 全局異常處理,針對ajax響應和頁面請求響應
 */
@RestControllerAdvice
public class GlobalRestExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @ExceptionHandler(Exception.class)
    public Object exception(HttpServletRequest reqest, HttpServletResponse response,HandlerMethod handlerMethod, Exception exception) {

        Method m = handlerMethod.getMethod();
        Class<?> clazz = handlerMethod.getBeanType();
        //判斷訪問的url是否爲rest接口請求
        boolean isRestReq = (m.getAnnotation(ResponseBody.class)!=null
                ||clazz.getAnnotation(ResponseBody.class)!=null
                ||clazz.getAnnotation(RestController.class)!=null);
        //判斷訪問的url是否爲ajax請求
        boolean isAjax = isAjax(reqest);
        if (isAjax||isRestReq) {
            logger.error("global exception", exception);
            if (exception instanceof VeException) {
                return ResultInfo.fail(VeErrorCode.UNKNOWN_EXCEPTION, exception.getMessage());
            }
            return ResultInfo.fail(VeErrorCode.UNKNOWN_EXCEPTION);
        } else {
            logger.error("界面請求異常", exception);
            ModelAndView mv = new ModelAndView();
            if (exception instanceof VeException) {
                mv.addObject("errorMessage", exception.getMessage());
                mv.setViewName("error");
                return mv;
            }
            mv.addObject("errorMessage", "");
            mv.setViewName("error");
            return mv;
        }
    }

    /**
     * 判斷網絡請求是否爲ajax
     *
     * @param req
     * @return
     */
    private boolean isAjax(HttpServletRequest req) {
        String contentTypeHeader = req.getHeader("Content-Type");
        String acceptHeader = req.getHeader("Accept");
        String xRequestedWith = req.getHeader("X-Requested-With");
        return (contentTypeHeader != null && contentTypeHeader.contains("application/json"))
                || (acceptHeader != null && acceptHeader.contains("application/json"))
                || "XMLHttpRequest".equalsIgnoreCase(xRequestedWith);
    }
}

VeException 中的內容

**
 * 全局異常
 */
public class VeException extends RuntimeException {
    private String code;
    private String message;

    public VeException(VeErrorCode errorCode) {
        super(errorCode.getCode());
        this.code = errorCode.getCode();
        this.message = errorCode.getMessage();
    }

    public String getCode() {
        return code;
    }

    @Override
    public String getMessage() {
        return message;
    }
}

VeErrorCode中的內容

public enum VeErrorCode {
 UNKNOWN_EXCEPTION("unknown_exception","系統內部錯誤");
   private String code;
    private String message;


    private VeErrorCode(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public String getCode() {
        return code;
    }

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

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

測試:將會出現兩種

ajax請求響應在這裏插入圖片描述

在這裏插入圖片描述

頁面請求響應

在這裏插入圖片描述
在這裏插入圖片描述
測試成功
版權聲明:轉載請標明博客地址,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章