SpringBoot全局異常處理知多少?詳細介紹處理方法,附相關(guān)源代碼
Spring Boot提供了一種簡單且靈活的方式來處理應(yīng)用程序中的異常,即全局異常處理。全局異常處理允許我們定義一個統(tǒng)一的異常處理器,以捕獲應(yīng)用程序中發(fā)生的所有異常,并提供自定義的錯誤響應(yīng)。
在本文中,我將詳細介紹Spring Boot全局異常處理的方法,并提供源代碼和相關(guān)說明。
一、創(chuàng)建全局異常處理器
首先,我們需要創(chuàng)建一個全局異常處理器。我們可以通過實現(xiàn)ErrorController接口或使用@ControllerAdvice注解來創(chuàng)建全局異常處理器。
1、實現(xiàn)ErrorController接口
我們可以創(chuàng)建一個類,實現(xiàn)ErrorController接口,并重寫getErrorPath()和errorHandle()方法來處理異常。
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GlobalErrorController implements ErrorController {
private static final String PATH = "/error";
@RequestMapping(value = PATH)
public String errorHandle() {
// 處理異常邏輯
return "Error handling logic goes here";
}
@Override
public String getErrorPath() {
return PATH;
}
}
在上面的代碼中,我們創(chuàng)建了一個名為GlobalErrorController的類,它實現(xiàn)了ErrorController接口。我們使用@RestController注解將該類標記為一個控制器,并使用@RequestMapping注解來映射處理異常的路徑為/error。在errorHandle()方法中,我們可以編寫自定義的異常處理邏輯。
2、使用@ControllerAdvice注解
另一種創(chuàng)建全局異常處理器的方法是使用@ControllerAdvice注解。我們可以創(chuàng)建一個帶有@ControllerAdvice注解的類,并在其中定義一個或多個帶有@ExceptionHandler注解的方法來處理異常。
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public String handleException(Exception e) {
// 處理異常邏輯
return "Error handling logic goes here";
}
}
在上面的代碼中,我們創(chuàng)建了一個名為GlobalExceptionHandler的類,并使用@ControllerAdvice注解將其標記為全局異常處理器。我們使用@ExceptionHandler注解來指定要處理的異常類型,并在方法中編寫自定義的異常處理邏輯。
二、配置全局異常處理器
接下來,我們需要將全局異常處理器配置到Spring Boot應(yīng)用程序中。我們可以通過創(chuàng)建一個配置類,并使用@EnableWebMvc注解或?qū)崿F(xiàn)WebMvcConfigurer接口來配置全局異常處理器。
1、使用@EnableWebMvc注解
我們可以創(chuàng)建一個配置類,并使用@EnableWebMvc注解來啟用全局異常處理器。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@EnableWebMvc
public class WebConfig {
}
在上面的代碼中,我們創(chuàng)建了一個名為WebConfig的配置類,并使用@EnableWebMvc注解來啟用全局異常處理器。
2、實現(xiàn)WebMvcConfigurer接口
另一種配置全局異常處理器的方法是創(chuàng)建一個配置類,并實現(xiàn)WebMvcConfigurer接口。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
resolvers.add(new GlobalExceptionHandler());
}
}
在上面的代碼中,我們創(chuàng)建了一個名為WebConfig的配置類,并實現(xiàn)了WebMvcConfigurer接口。我們重寫了configureHandlerExceptionResolvers()方法,并將全局異常處理器添加到異常解析器列表中。
三、自定義異常處理邏輯
在全局異常處理器中,我們可以編寫自定義的異常處理邏輯。以下是一些常見的處理邏輯示例:
1、返回自定義錯誤信息
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
String errorMessage = "An error occurred: " + e.getMessage();
return new ResponseEntity<>(errorMessage, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
在上面的代碼中,我們使用@RestControllerAdvice注解將GlobalExceptionHandler類標記為全局異常處理器。在handleException()方法中,我們可以捕獲所有的Exception異常,并返回一個包含自定義錯誤信息的ResponseEntity對象。
2、返回自定義錯誤對象
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception e) {
ErrorResponse errorResponse = new ErrorResponse("An error occurred", e.getMessage());
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
在上面的代碼中,我們創(chuàng)建了一個名為ErrorResponse的自定義錯誤對象,并在handleException()方法中返回該對象。該對象包含了自定義的錯誤信息和異常消息。
3、返回統(tǒng)一的錯誤格式
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception e) {
ErrorResponse errorResponse = new ErrorResponse("An error occurred", e.getMessage());
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleUserNotFoundException(UserNotFoundException e) {
ErrorResponse errorResponse = new ErrorResponse("User not found", e.getMessage());
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}
}
在上面的代碼中,我們創(chuàng)建了一個名為ErrorResponse的自定義錯誤對象,并在handleException()方法中返回該對象。在handleUserNotFoundException()方法中,我們捕獲了UserNotFoundException異常,并返回一個包含自定義錯誤信息的ResponseEntity對象。
四、異常處理器的優(yōu)先級
在Spring Boot應(yīng)用程序中,可以存在多個全局異常處理器。當發(fā)生異常時,Spring Boot會根據(jù)異常處理器的優(yōu)先級來選擇合適的處理器。
默認情況下,Spring Boot使用@ControllerAdvice注解的處理器的優(yōu)先級更高。如果多個處理器都能處理同一類型的異常,Spring Boot將選擇具有最高優(yōu)先級的處理器。
我們可以使用@Order注解來指定處理器的優(yōu)先級。優(yōu)先級值越小,優(yōu)先級越高。
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
@Order(1)
public class GlobalExceptionHandler1 {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
String errorMessage = "An error occurred: " + e.getMessage();
return new ResponseEntity<>(errorMessage, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@RestControllerAdvice
@Order(2)
public class GlobalExceptionHandler2 {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
String errorMessage = "An error occurred: " + e.getMessage();
return new ResponseEntity<>(errorMessage, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
在上面的代碼中,GlobalExceptionHandler1的優(yōu)先級為1,GlobalExceptionHandler2的優(yōu)先級為2。當發(fā)生異常時,GlobalExceptionHandler1將被選擇為處理器。
五、測試全局異常處理器
最后,我們可以編寫一些測試用例來測試全局異常處理器。
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
@SpringBootTest
@AutoConfigureMockMvc
public class GlobalExceptionHandlerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testHandleException() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/error"))
.andExpect(MockMvcResultMatchers.status().isInternalServerError())
.andExpect(MockMvcResultMatchers.content().string("An error occurred: Internal Server Error"));
}
@Test
public void testHandleUserNotFoundException() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/user/123"))
.andExpect(MockMvcResultMatchers.status().isNotFound())
.andExpect(MockMvcResultMatchers.content().string("User not found: 123"));
}
}
在上面的代碼中,我們使用MockMvc來模擬HTTP請求,并使用MockMvcRequestBuilders構(gòu)建請求。在testHandleException()方法中,我們發(fā)送一個GET請求到/error路徑,并斷言返回的狀態(tài)碼為500,內(nèi)容為"An error occurred: Internal Server Error"。在testHandleUserNotFoundException()方法中,我們發(fā)送一個GET請求到/user/123路徑,并斷言返回的狀態(tài)碼為404,內(nèi)容為"User not found: 123"。
這些測試用例可以確保全局異常處理器按預(yù)期工作,并返回正確的錯誤信息。