1. 程式人生 > 實用技巧 >10、SpringBoot之異常處理

10、SpringBoot之異常處理

第一種:自定義錯誤頁面

  • SpringBoot預設的處理異常的機制:SpringBoot預設的已經提供了一套處理異常的機制。
  • 一旦程式中出現了異常SpringBoot會向/error的url傳送請求。
  • SpringBoot中提供了一個名為BasicErrorController來處理/error請求,然後跳轉到預設顯示異常的頁面來展示異常資訊。

由於沒有找到/error對映的檔案,所以將錯誤返回到springboot的頁面將異常資訊進行輸出

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Apr 23 23:29:38 CST 2020
There was an unexpected error (type=Internal Server Error, status=500).
No message available
如果需要將所有異常統一跳轉到自定義的錯誤頁面,需要在**src/main/resources/templates** 目錄下建立**error.html**頁面。注意:頁面必須叫**error**

當有一個命名為error的錯誤頁面時,出現異常則直接跳到該頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    出現錯誤異常
</body>
</html>

缺點:當捕獲到不同的異常想要跳轉至不同頁面是,自定義錯誤頁面沒辦法實現;

第二種:通過@ExceptionHandler註解處理異常

  • 修改Controller
  • 建立頁面

@ExceptionHandler註解可以做到根據不同異常型別,來跳轉到不同的頁面進行異常資訊的顯示

我們需要在能夠產生異常的方法所在的controller當中再新增一個處理異常的方法

@Controller
public class UsersController {
    /**
     * 定義一個會報出空指標異常的方法
     * @return
     */
    @RequestMapping("showInfo")
    public String showInfo(){
        String str = null;
        str.length();
        return "ok";
    }


    /**
     * 該方法會處理當前這個controller出現的空指標異常
     * @param e
     * @return
     */
    @ExceptionHandler(value = {java.lang.NullPointerException.class})
    public ModelAndView nullpointExceptionHandler(Exception e){
//        e物件會接收放錯傳入的異常物件
        ModelAndView mv = new ModelAndView();
        mv.addObject("err", e);
        mv.setViewName("error1");
        return mv;
    }
}

error1頁面

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    出錯了。。。
    <span th:text="${err}"></span>
</body>
</html>

缺點:單用一個@ExceptionHandler註解只能作用他當前的controller進行異常處理,如果其他controller也出現同樣的異常是不會進行處理的,複用性差,這個時候需要@ControllerAdvice結合使用,使異常處理方法可以全域性使用。

第三種:通過@ControllerAdvice與@ExceptionHandler註解處理異常

  • 建立全域性異常處理類

Controller

@Controller
public class UsersController {
    /**
     * 定義一個會報出空指標異常的方法
     * @return
     */
    @RequestMapping("showInfo")
    public String showInfo(){
        String str = null;
        str.length();
        return "ok";
    }
    /**
     * 定義一個會報出算術異常的方法
     * @return
     */
    @RequestMapping("showInfo2")
    public String showInfo2(){
        int i = 10/0;
        return "ok";
    }
}

全域性異常處理類

/**
* 全域性異常處理類
*/
@ControllerAdvice
public class GlobalException {
    /**
     * 處理空指標異常
     * @param e
     * @return
     */
    @ExceptionHandler(value = {java.lang.NullPointerException.class})
    public ModelAndView nullpointExceptionHandler(Exception e){
//        e物件會接收放錯傳入的異常物件
        ModelAndView mv = new ModelAndView();
        mv.addObject("err", e);
        mv.setViewName("error1");
        return mv;
    }
    /**
     * 處理算術異常
     * @param e
     * @return
     */
    @ExceptionHandler(value = {java.lang.ArithmeticException.class})
    public ModelAndView ArithmeticExceptionHandler(Exception e){
//        e物件會接收放錯傳入的異常物件
        ModelAndView mv = new ModelAndView();
        mv.addObject("err", e);
        mv.setViewName("error2");
        return mv;
    }
}

當專案中出現空指標異常都會被該方法攔截並進行處理

全域性異常處理類有個缺點就是會定義特別多的方法來處理異常

第四種,通過SimpleMappingExceptionResolver物件處理異常

SimpleMappingExceptionResolve可以通過一個方法來處理多個不同的異常,並且跳轉到不同的頁面

/**
* 全域性異常
* SimpleMappingExceptionResolver
*/
@Configuration
public class GloballException2 {
    /**
     * 此方法返回值必須是SimpleMappingExceptionResolver,方法名可以隨意
     * @return
     */
    @Bean
    public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){
        //簡單對映異常解析,也是可以根據異常型別和需要跳轉檢視做一個對映處理
        SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
        Properties properties = new Properties();
        /**
         * 引數1:異常型別(全名)
         * 引數2:跳轉頁面(檢視)
         */
        //這裡只是做,檢視與異常型別的對映,並沒有傳遞異常物件,所以跳轉到對應的檢視後並沒有傳遞異常物件過去
        properties.put("java.lang.NullPointerException","error3");
        properties.put("java.lang.ArithmeticException","error4");
        resolver.setExceptionMappings(properties);
        return resolver;
    }
}

error3.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    出錯了。。。空指標異常
</body>
</html>

error4.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
    <meta charset="UTF-8">
    <title>error2</title>
</head>
<body>
    出錯了。。。算術異常
</body>
</html>

缺點:只能做異常和檢視的對映,不能獲取到異常資訊

第五種,通過自定義HandlerExceptionResolver物件處理異常

  • 建立全域性異常處理類

全域性異常處理類 GloballException3

/**
* 自定義HandlerExceptionResolve物件處理異常
* 必須要實現HandlerExceptionResolver
*/
@Configuration
public class GloballException3 implements HandlerExceptionResolver{
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception e) {
        ModelAndView mv = new ModelAndView();
        //判斷不同異常型別,做不同檢視的跳轉
        if(e instanceof NullPointerException){
           mv.setViewName("error5");
        }
        if(e instanceof ArithmeticException){
            mv.setViewName("error6");
        }
        //不管跳到哪個檢視,攜帶的異常資訊不變所以不用帶入if判斷裡面
        mv.addObject("error", e.toString());
        return mv;
    }
}

error5.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
    <meta charset="UTF-8">
    <title>error5</title>
</head>
<body>
    出錯了。。。空指標異常
    <span th:text="${error}"></span>
</body>
</html>

error6.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}" />
<head>
    <meta charset="UTF-8">
    <title>error6</title>
</head>
<body>
    出錯了。。。算術異常
    <span th:text="${error}"></span>
</body>
</html>