1. 程式人生 > >Springboot(10)輕鬆搞定統一異常處理

Springboot(10)輕鬆搞定統一異常處理

原始碼地址

異常的捕獲方式

方式一 HandlerExceptionResolver介面

實現該介面,註冊到spring容器中,當controller中產生異常的時候會呼叫該介面來處理,注意,當返回值指定檢視時會自動跳轉至指定的檢視中去,如果返回null,會繼續呼叫下一個異常處理器去執行。  springboot中可以通過以下方式去註冊進容器。

@Component
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyException implements HandlerExceptionResolver
{ @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { log.error("錯誤資訊:",e); return null; }
}

這裡可以直接返回ModelAndView物件,跳轉到頁面。如果返回null,則跳轉到/error

方式二 @ControllerAdvice以及@ExceptionHandler

spring 中還可以通過@ControllerAdvice以及@ExceptionHandler(ApplicationException.class)註解對指定的異常做全域性處理

@ControllerAdvice
@Slf4j
public class GlobalExceptionController {
    @ExceptionHandler(Exception.
class) public String handlerException(Exception e) { log.error("控制器增強處理異常"); return "error2";//返回templates/error2.html } }

執行完之後會返回一個ModelAndView物件,所以不會再執行我們自己註冊的異常解析器了,要想生效,我們只需在註冊時調整註冊順序即可

全域性的異常處理

以上2種方式只能處理Controller層之內的異常,對於渲染層及其他的異常是無能為力的,如果我們要做全域性的異常處理就需要結合容器來做處理了。

例如:404錯誤

以tomcat為例,容器在處理請求時,遇到異常情況,首先會去找錯誤頁面,如果沒有配置錯誤頁面,會HttpStatus預設轉發到/error路徑,所以我們可以寫一個controller類來處理/error 請求,而springboot中預設有一個處理/error 請求的controller類

@Controller
@RequestMapping("${server.error.path:/error}")
public class GlobalErrorController implements ErrorController {

    /**
     * 錯誤資訊的構建工具.
     */
    @Autowired
    private ErrorInfoBuilder errorInfoBuilder;

    /**
     * 錯誤資訊頁的路徑
     */
    private final static String DEFAULT_ERROR_VIEW = "error";

    /**
     * 獲取錯誤控制器的對映路徑.
     */
    @Override
    public String getErrorPath() {
        return errorInfoBuilder.getErrorProperties().getPath();
    }

    /**
     * 情況1:若預期返回型別為text/html,s則返回錯誤資訊頁(View).
     */
    @RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
    @ResponseBody
    public ModelAndView errorHtml(HttpServletRequest request) {
        return new ModelAndView(DEFAULT_ERROR_VIEW,
                "errorInfo", errorInfoBuilder.getErrorInfo(request));
    }

    /**
     * 情況2:其它預期型別 則返回詳細的錯誤資訊(JSON).
     */
    @RequestMapping
    @ResponseBody
    public ErrorInfo error(HttpServletRequest request) {
        return errorInfoBuilder.getErrorInfo(request);
    }
}

樣例測試訪問地址:http://127.0.0.1:8080/exception