1. 程式人生 > >SpringBoot Web/API的通用異常處理[嗡湯圓的小筆記]

SpringBoot Web/API的通用異常處理[嗡湯圓的小筆記]

view的異常處理

SpringBoot Web專案中對於view的預設錯誤資訊頁如下:
這裡寫圖片描述

並不十分友好,因此需要對異常進行自定義處理,步驟如下:

  1. 建立@ControllerAdvice Bean。並分別為各異常類制定處理方式。為簡單起見,本處僅對Exception(500錯誤)和NoHandlerFoundException(即404錯誤)進行處理
  2. 設定ServletDispatcher,允許404異常丟擲(若不做此設定,NoHandlerFoundException不會被捕獲)

程式碼如下:

/*STEP 1 : 宣告@ControllerAdvice Bean*/
@ControllerAdvice
public class ErrorView { @ExceptionHandler(value=Exception.class) public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) throws Exception { ModelAndView view = new ModelAndView(); view.addObject("ERRORCODE", 500); view.addObject("ERRORMSG"
, e.getMessage()); view.addObject("URL", request.getRequestURL()); view.setViewName("error"); return view; } @ExceptionHandler(value=NoHandlerFoundException.class) public ModelAndView pageNoFoundHandler(HttpServletRequest request, Exception e) throws Exception { ModelAndView view = new
ModelAndView(); view.addObject("ERRORCODE", 404); view.addObject("ERRORMSG", "頁面未找到"); view.addObject("URL", request.getRequestURL()); view.setViewName("error"); return view; } } /*STEP - 2 : 設定DispatcherServlet的404異常丟擲*/ @EnableScheduling @SpringBootApplication public class WebProxy { public static void main(String[] args) { ApplicationContext ctx = SpringApplication.run(WebProxy.class, args); // 自定義處理404異常 DispatcherServlet servlet = (DispatcherServlet) ctx.getBean("dispatcherServlet"); servlet.setThrowExceptionIfNoHandlerFound(true); } }

在此基礎上,製作一個異常頁面error.html即可。程式碼如下(此處藉助thymeleaf模板引擎):

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org"
    xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>ERROR</title>
<!-- 基本樣式和庫 -->
<div th:include="layout/common :: header"></div>
<div th:include="layout/common :: lib"></div>
<!-- 基本樣式和庫 -->
</head>

<body>
    <header class="header">
        <h1>
            <a href="#" class="sel-station">錯誤頁面</a>
        </h1>
    </header>
    <div class="content" id="app">
        <div class="media"><img th:src="@{/static/images/ico18.png}" width="100%" /></div>
        <div class="lobby-place">
            <section class="item">
                <p th:text="'code:'+${ERRORCODE}">ERRORCODE</p>
                <p th:text="'url:'+${URL}">
                    URL
                </p>
                <P th:text="'msg:'+${ERRORMSG}">
                    ERRORMSG
                </P>
                <a class="btn btn-block btn-primary" th:href="@{/view/index}">回首頁</a>
            </section>
        </div>
    </div>
</body>

</html>

顯示效果如下:
這裡寫圖片描述

增加API的異常處理

在增加通用處理前,首先先定義所有API的規範化資料結構。基本資訊應包括:狀態碼statusCode, 狀態資訊statusMsg,資料data。程式碼如下:

public class ResultBean {

    private int statusCode;
    private String statusMsg;
    private Object data;

    /*getter  setter 省略*/
}

定義statusCode == 0 為成功,則從data中獲取資料,否則失敗,從statusMsg中獲取錯誤資訊。
同時,對於請求url地址統一定位於/api/ 之下,這樣既可通過url判斷該請求屬於檢視還是API介面。

將返回的ModelAndView 改為Object,同時加上@ResponseBody 修改後的@ControllerAdvice如下

@ControllerAdvice
public class ErrorView {
    @ResponseBody
    @ExceptionHandler(value=Exception.class)
    public Object defaultErrorHandler(HttpServletRequest request, Exception e) throws Exception {
        if (!returnJson(request)) {
            ModelAndView view = new ModelAndView();
            view.addObject("ERRORCODE", 500);
            view.addObject("ERRORMSG", e.getMessage());
            view.addObject("URL", request.getRequestURL());
            view.setViewName("error");
            return view;
        } else {
            System.out.println("is json");
            ResultBean bean = new ResultBean();
            bean.setReturnCode(-1);
            bean.setReturnMsg("[api異常]" + e.getMessage());
            return bean;        
        }
    }   
    @ResponseBody
    @ExceptionHandler(value=NoHandlerFoundException.class)
    public Object pageNoFoundHandler(HttpServletRequest request, Exception e) throws Exception {
        if (!returnJson(request)) {
            ModelAndView view = new ModelAndView();
            view.addObject("ERRORCODE", 404);
            view.addObject("ERRORMSG", "頁面未找到");
            view.addObject("URL", request.getRequestURL());
            view.setViewName("error");
            return view;
        } else {
            System.out.println("is json");
            ResultBean bean = new ResultBean();
            bean.setReturnCode(-1);
            bean.setReturnMsg("地址未找到");
            return bean;
        }
    }
    private boolean returnJson(HttpServletRequest request){
        System.out.println(request.getRequestURI());
        return request.getRequestURI().contains("/api/");
    }
}

這樣在呼叫Api出現異常時既可返回相應的錯誤資訊。效果入下:
這裡寫圖片描述

這裡寫圖片描述