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
后效果: