SpringBoot 框架異常處理有五種處理方式,從范圍來說包括有全局異常捕獲處理方式和局部異常捕獲處理方式,接下來通過使用下面的后端代碼一一對這五種捕獲方式講解。
package com.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Description 拋出異常 Controller,測試異常
* @author 歐陽
* @since 2019年4月12日 下午12:48:31
* @version V1.0
*/
@Controller
public class ExceptionController {
private static final Logger log = LoggerFactory.getLogger(ExceptionController.class);
@RequestMapping("/exceptionMethod")
public String exceptionMethod(Model model) throws Exception {
model.addAttribute("msg", "沒有拋出異常");
int num = 1/0; //a處
log.info(String.valueOf(num));
return "home";
}
}
上述代碼將會在 a處拋出 ArithmeticException 異常。
一、自定義異常錯誤頁面
相信大家有過這樣的經歷,在遇到異常時,SpringBoot 會自動跳到一個統一的異常頁面,沒錯,SpringBoot 默認的已經提供了一套處理異常的機制,我們只需要自定義該錯誤頁面就可以,所以這種方式就是自定義這個異常的錯誤頁面。
SpringBoot 默認的異常處理機制:一旦程序中出現了異常 SpringBoot 就會請求 /error 的 url 。在 SpringBoot 中提供了一個叫 BasicExceptionController 來處理 /error 請求,然后跳轉到默認顯示異常的頁面來展示異常信息。接下來就是自定義異常錯誤頁面了,方法很簡單,就是在目錄 src/main/resources/templates/ 下定義一個叫 error 的文件,可以是 jsp 也可以是 html 。

上圖為在指定目錄 src/main/resources/templates/ 添加 error.html 頁面前效果。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>自定義 springboot 異常處理頁面</title>
</head>
<body>
Springboot BasicExceptionController 錯誤頁面
<br>
<span th:text="${msg}"></span>
</body>
</html>
在指定目錄添加 error.html 頁面后效果圖:

注意:必須是在目錄 src/main/resources/templates/ 下定義 error 的文件。
二、使用 @ExceptionHandler 注解處理局部異常
使用這個注解就容易了,但是只能處理使用 @ExceptionHandler 注解的方法的 Controller 的異常,對於其他 Controller 的異常就無能為力了,只能再使用同樣的方法將使用 @ExceptionHandler 注解的方法寫入要捕獲異常的 Controller 中,所以不推薦使用。
使用方式:在最上面的 ExceptionController 中加入使用 @ExceptionHandler 注解的方法代碼,整個 ExceptionController 代碼如下:
package com.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Description 拋出異常 Controller,測試異常
* @author 歐陽
* @since 2019年4月12日 下午12:48:31
* @version V1.0
*/
@Controller
public class ExceptionController {
private static final Logger log = LoggerFactory.getLogger(ExceptionController.class);
@RequestMapping("/exceptionMethod")
public String exceptionMethod(Model model) throws Exception {
model.addAttribute("msg", "沒有拋出異常");
int num = 1/0;
log.info(String.valueOf(num));
return "home";
}
/**
* 描述:捕獲 ExceptionController 中的 ArithmeticException 異常
* @param model 將Model對象注入到方法中
* @param e 將產生異常對象注入到方法中
* @return 指定錯誤頁面
*/
@ExceptionHandler(value = {ArithmeticException.class})
public String arithmeticExceptionHandle(Model model, Exception e) {
model.addAttribute("msg", "@ExceptionHandler" + e.getMessage());
log.info(e.getMessage());
return "error";
}
}
代碼說明:注解 @ExceptionHandler 中 value 的值為數組,表示指定捕獲的異常類型,這里表示捕獲 ArithmeticException 異常,因為 a 處 拋出的是 ArithmeticException 異常,跳轉的頁面為統一的 error.html 頁面,但描述信息不同,以用來區分是 SpringBoot 處理的異常還是我們自己的方法處理的異常,下面也是使用這個方式來區分。
當訪問 http://localhost:8080/exceptionMethod 時,跳轉到下面頁面,顯示 @ExceptionHandler/ by zero ,表示我們使用 @ExceptionHandler 注解處理異常成功。

三、使用 @ControllerAdvice + @ExceptionHandler 注解處理全局異常
使用 @ControllerAdvice + @ExceptionHandler 注解能夠處理全局異常,這種方式推薦使用,可以根據不同的異常對不同的異常進行處理。
使用方式:定義一個類,使用 @ControllerAdvice 注解該類,使用 @ExceptionHandler 注解方法,這里我定義了一個 GlobalException 類表示來處理全局異常,代碼如下:
package com.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
/**
* @Description 全局異常處理類
* @author 歐陽
* @since 2019年4月12日 下午3:52:04
* @version V1.0
*/
@ControllerAdvice
public class GlobalException {
private static final Logger log = LoggerFactory.getLogger(GlobalException.class);
/**
* 描述:捕獲 ArithmeticException 異常
* @param model 將Model對象注入到方法中
* @param e 將產生異常對象注入到方法中
* @return 指定錯誤頁面
*/
@ExceptionHandler(value = {ArithmeticException.class})
public String arithmeticExceptionHandle(Model model, Exception e) {
model.addAttribute("msg", "@ControllerAdvice + @ExceptionHandler :" + e.getMessage());
log.info(e.getMessage());
return "error";
}
}
如果需要處理其他異常,例如 NullPointerException 異常,則只需要在 GlobalException 類中定義一個方法使用 @ExceptionHandler(value = {NullPointerException.class}) 注解該方法,在該方法內部處理異常就可以了。
當訪問 http://localhost:8080/exceptionMethod 時,跳轉到下面頁面,顯示 @ControllerAdvice + @ExceptionHandler :/ by zero ,表示我們使用 @ControllerAdvice + @ExceptionHandler 注解處理異常成功。

四、配置 SimpleMappingExceptionResolver 類處理異常
通過配置 SimpleMappingExceptionResolver 類處理異常也是全局范圍的,通過將 SimpleMappingExceptionResolver 類注入到 Spring 容器。
package com.config;
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
/**
* @Description 配置 SimpleMappingExceptionResolver 類處理異常
* @author 歐陽
* @since 2019年4月12日 下午5:01:08
* @version V1.0
*/
@Configuration
public class GlobalException {
@Bean
public SimpleMappingExceptionResolver
getSimpleMappingExceptionResolver(){
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
/*
* 參數一:異常的類型,注意必須是異常類型的全名
* 參數二:視圖名稱
*/
mappings.put("java.lang.ArithmeticException", "errors");
//設置異常與視圖映射信息的
resolver.setExceptionMappings(mappings);
return resolver;
}
}
注意:在類上加上 @Configuration 注解,在方法上加上 @Bean 注解,方法返回值必須是 SimpleMappingExceptionResolver 。
編寫 errors.html 頁面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>自定義 springboot 異常處理頁面</title>
</head>
<body>
配置 SimpleMappingExceptionResolver 類處理異常
</body>
</html>
訪問 http://localhost:8080/exceptionMethod 鏈接后拋出 ArithmeticException 異常,跳轉到 errors.html 頁面,效果圖如下所示:

五、實現 HandlerExceptionResolver 接口處理異常
通過實現 HandlerExceptionResolver 接口處理異常,第一步是編寫類實現 HandlerExceptionResolver 接口。
package com.config;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
/**
* @Description 實現 HandlerExceptionResolver 接口處理異常
* @author 歐陽
* @since 2019年4月12日 下午5:13:58
* @version V1.0
*/
@Configuration
public class HandlerExceptionResolverImpl implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", "實現 HandlerExceptionResolver 接口處理異常");
//判斷不同異常類型,做不同視圖跳轉
if(ex instanceof ArithmeticException){
modelAndView.setViewName("error");
}
return modelAndView;
}
}
注意:在類上加上 @Configuration 注解。
配置完后訪問 http://localhost:8080/exceptionMethod 后效果:

