首頁>技術>

上篇文章中的處理方法確實只能保證進入我們的Controller之後的異常都進行捕獲,並返回統一的格式。

但是在沒進入Controller前的一些異常是無法捕獲的。比如404,400、還有一些500。

關於這些錯誤的處理方法大概有下面這些:

方式一、前端統一處理

其實對於這些錯誤,不建議後端全部攔截,使用SpringBoot框架的應用應該都進行了前後端分離。可以在前端統一進行網路請求的攔截處理,如果返回的http status 不是200,前端對於不同的status進行相應的處理即可。

方式二、對於404的處理

我們可以在Springboot的配置中設定404時丟擲異常。這樣我們就可以在GlobalExceptionInterceptor類中進行捕獲了。

配置:

# 出現404錯誤時, 直接丟擲異常 spring.mvc.throw-exception-if-no-handler-found=true # 不要對資原始檔建立對映 spring.resources.add-mappings=false

然後我們直接在 類中捕獲該型別的異常即可:

package com.xtoad.study.common.web.interceptor;import com.xtoad.study.common.web.ResultDTO;import com.xtoad.study.common.web.exception.BusinessException;import com.xtoad.study.common.web.exception.ResultCodeEnum;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.bind.MethodArgumentNotValidException;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.RestControllerAdvice;/** * 全域性異常捕捉處理 * * @author xtoad * @date 2021/02/18 */@RestControllerAdvicepublic class GlobalExceptionInterceptor {    private final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionInterceptor.class);    /**     * 全域性業務異常捕捉處理     *     * @param ex 業務異常     * @return 結果     */    @ExceptionHandler(value = BusinessException.class)    public ResultDTO businessExceptionHandler(BusinessException ex) {        LOGGER.info(ex.getMsg(), ex);        return ResultDTO.failed(ex.getCode(), ex.getMsg());    }    /**     * 全域性異常捕捉處理     *     * @param ex Exception     * @return 結果     */    @ExceptionHandler(value = Exception.class)    public ResultDTO exceptionHandler(Exception ex) {        LOGGER.error(ex.getMessage(), ex);        if (ex instanceof MethodArgumentNotValidException) {            return ResultDTO.failed(ResultCodeEnum.INVALID_PARAMETER);        } else if (ex instanceof org.springframework.web.servlet.NoHandlerFoundException) {            // 這裡判斷異常是404時            return ResultDTO.failed("404", "請求的url不存在");        } else {            return ResultDTO.failed(ResultCodeEnum.UNKNOW_ERROR);        }    }}

方式三、重寫ErrorController,任何時候都返回統一格式

上面方式二是能處理404了,但是也不能對映靜態資源了,而且開篇我們說了,除了404,還有他的一些異常,如何捕獲呢?

所以我們重寫ErrorController:

@RestControllerpublic class GlobalExceptionController extends AbstractErrorController {    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionController.class);    private static final String ERROR_PATH = "/error";     public GlobalExceptionController(ErrorAttributes errorAttributes) {        super(errorAttributes);    }     @Override    public String getErrorPath() {        return ERROR_PATH;    }     @RequestMapping(value = ERROR_PATH)    public ResultDTO error(HttpServletRequest request) {        WebRequest webRequest = new ServletWebRequest(request);        Throwable e = getError(webRequest);        if (e == null) {            Map<String, Object> attributes = getErrorAttributes(request, false);            Object timestamp = attributes.get("timestamp");            Object status = attributes.get("status");            String error = attributes.get("error").toString();            Object path = attributes.get("path");            LOGGER.error("status {} error {} path{} timestamp {}", status, error, path, timestamp);            return ResultDTO.failed(Integer.parseInt(status.toString()), error);        }        if (e instanceof TokenExpiredException) {            TokenExpiredException tokenExpiredException = (TokenExpiredException) e;            return ResultDTO.failed(tokenExpiredException.getHttpStatus().value(), tokenExpiredException.getHttpStatus().getReasonPhrase());        } else if (e instanceof CodeException) {            CodeException codeException = (CodeException) e;            String message = e.getMessage();            if (StringUtils.isEmpty(message)) {                message = String.format("[%s][%s]", codeException.getErrCode(), codeException.getErrMsg());            }            return ResultDTO.failed(codeException.getErrCode(), message);        } else {            return ResultDTO.failed("500", "系統繁忙,請稍後再試");        }    }     private Throwable getError(WebRequest webRequest) {        return (Throwable) this.getAttribute(webRequest, "javax.servlet.error.exception");    }     private Object getAttribute(RequestAttributes requestAttributes, String name) {        return requestAttributes.getAttribute(name, 0);    }}

該方式,比較簡單粗暴,除非你確定你的應用無論什麼場合都返回統一的JSON,不否不建議使用。

更推薦方式一,前端統一攔截,對http status 進行判斷處理。

15
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Spring Boot 整合CXF新增日誌攔截器