Глобальная обработка исключений — очень важная функция в приложениях Spring Boot. Это может помочь нам перехватывать необработанные исключения, единообразно обрабатывать их и возвращать клиенту понятное сообщение об ошибке. В этой статье будет показано, как использовать Spring Boot для корректной обработки глобальных исключений, а также приведены некоторые практические примеры кода.
@ControllerAdvice
Аннотация создает глобальный обработчик исключенийВесной MVCсередина,мы можем использовать@ControllerAdvice
Аннотация создает глобальный обработчик исключений.。Этот класс будет содержать методы для обработки различных исключений.,Эти методы можно использовать@ExceptionHandler
Аннотировать с аннотациями。Вот простой пример:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Внутренняя ошибка сервера");
}
}
В этом примере,Мы создали файл под названиемGlobalExceptionHandler
Класс глобального обработчика исключений,и использовать@ControllerAdvice
Аннотировать с аннотациями。существоватьэтот класссередина,Мы определяем метод для обработки исключенийhandleException()
,и использовать@ExceptionHandler(Exception.class)
В аннотации указано, что метод используется для обработкиException
тип исключения。
Помимо обработки всех типов исключений,Мы также можем создавать специализированные методы для обработки некоторых типичных исключений. Например,Мы можем создать метод для обработкиNullPointerException
аномальный:
@ExceptionHandler(NullPointerException.class)
public ResponseEntity<String> handleNullPointerException(NullPointerException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Параметры запроса не могут быть пустыми");
}
Для лучшей обработки исключений мы можем создавать собственные классы исключений и вызывать эти исключения там, где это необходимо. Вот простой пример пользовательского класса исключений:
public class CustomException extends RuntimeException {
private static final long serialVersionUID = 1L;
public CustomException(String message) {
super(message);
}
}
В контроллере мы можем по мере необходимости генерировать собственные исключения. Например:
@RestController
public class UserController {
@GetMapping("/users/{id}")
public User getUserById(@PathVariable Long id) {
if (id == null || id <= 0) {
throw new CustomException("Идентификатор пользователя должен быть положительным числом");
}
// ...другой логический код
}
}
Чтобы обрабатывать пользовательские исключения, нам нужно добавить соответствующие методы в глобальный класс обработчика исключений. Например:
@ExceptionHandler(CustomException.class)
public ResponseEntity<String> handleCustomException(CustomException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
}
Чтобы клиент мог получать более понятную информацию об ошибках, мы можем создать собственный класс ответа на ошибку и использовать этот класс в глобальном обработчике исключений для возврата информации об ошибках. Например:
public class ErrorResponse {
private int status;
private String message;
public ErrorResponse(int status, String message) {
this.status = status;
this.message = message;
}
// ... методы получения и установки
}
Затем,существоватьобщая ситуацияаномальныйпроцессорсерединаиспользоватьErrorResponse
Класс возвращает сообщение об ошибке:
@ExceptionHandler(CustomException.class)
public ResponseEntity<ErrorResponse> handleCustomException(CustomException e) {
ErrorResponse errorResponse = new ErrorResponse(HttpStatus.BAD_REQUEST.value(), e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponse);
}
Если вы хотите ограничить глобальную обработку определенных типов исключений, вы можете сделать это двумя следующими способами:
@ExceptionHandler
аннотациясерединаиспользоватьexclude
свойствоВесной после версии 3.2,@ExceptionHandler
Аннотация добавленаexclude
свойство,позволяет исключить определенныетип исключения Без обработки。ты можешьсуществовать@ExceptionHandler
аннотациясередина Укажите, что исключитьаномальныйтип,Как показано ниже:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
if (e instanceof SomeSpecificException) {
// Не обрабатывать исключения типа SomeSpecificException.
return null;
}
// Обработка других типов исключений
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Внутренняя ошибка сервера");
}
// Другие методы обработки...
}
Однако,Этот подход не очень элегантен,потому что это требует от тебясуществоватьиметь дело сметод内部进行тип检查ивозвращатьсяnull
。Лучший способ - использоватьexclude
свойствопрямойсуществоватьаннотациясередина排除不需要иметь дело с的аномальныйтип。но,Следует отметить, что,@ExceptionHandler
Сама аннотация не даетexclude
свойство。Чтобы реализовать эту функцию,вам нужно использовать@ControllerAdvice
вариант——@RestControllerAdvice
,Это позволяет вам определять исключенные типы исключений на уровне класса.
@RestControllerAdvice(exclude = SomeSpecificException.class)
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
// Этот метод не будет обрабатывать исключения типа SomeSpecificException.
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Внутренняя ошибка сервера");
}
// Другие методы обработки...
}
Другой подход — создать несколько обработчиков исключений, каждый из которых обрабатывает свой набор исключений. Таким образом, вы можете косвенно исключить определенные типы исключений, не включая их. Например:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler({Exception.class, AnotherException.class})
public ResponseEntity<String> handleMultipleExceptions(Exception e) {
// Обработка исключений типа Exception и AnotherException
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Внутренняя ошибка сервера");
}
// Этот метод не будет обрабатывать исключения типа SomeSpecificException.
}
При глобальной обработке исключений форматированный вывод журналов может помочь нам лучше понять контекстную информацию при возникновении исключений, что упрощает отладку и обнаружение проблем. Вот как реализовать вывод в формате журнала при глобальной обработке исключений:
первый,Убедитесь, что вы включили зависимость платформы ведения журнала в свой проект. Возьмите Logback в качестве примера,вам нужносуществоватьpom.xml
документсередина Добавьте следующие зависимости:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
В вашем глобальном классе обработчика исключений,Создайте объект журнала. в целом,мы используемSLF4J
В качестве бревенчатого фасада,Затем Выберите конкретную реализацию журнала(нравитьсяLogback)。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
// ...другой код
}
В методе глобального обработчика исключений,Использование объекта журналаerror()
метод Записыватьаномальныйинформация。Чтобы добиться форматированного вывода,мы можем использовать{}
заполнитель,и Воляаномальный Объект передается в качестве аргументаerror()
метод。
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
logger.error("Внутренняя ошибка сервера: {}", e.getMessage(), e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Внутренняя ошибка сервера");
}
В этом примере,мы используемlogger.error()
метод Записывать了一个格式化的错误日志。{}
заполнитель Воля被e.getMessage()
Замените значение,в то же времяаномальныйобъектe
также будет передано в журналметодсередина,для включения в журнал информации о трассировке стека исключения.
Чтобы лучше контролировать формат вывода журнала,мы можемсуществоватьsrc/main/resources
Создайте каталог с именемlogback-spring.xml
файлы,Используется для настройки структуры ведения журнала Logback. в этом файле,Мы можем определить формат вывода и уровень журнала.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
В этом файле конфигурации,Мы определяем файл с именемSTDOUT
консольный вывод,И установите формат вывода журнала。%d{yyyy-MM-dd HH:mm:ss.SSS}
представляет дату и время,%thread
Указывает имя потока,%-5level
Указывает уровень журнала(выравнивание по левому краю),%logger{36}
Представляет имя экспортера журналов.(перед перехватом36персонажи),%msg
представляет собой сообщение журнала,%n
Представляет символ новой строки。
В этой статье объясняется, как использовать Spring Boot优雅地иметь дело собщая ситуацияаномальный。通过创建общая ситуацияаномальныйпроцессор类и использовать@ControllerAdvice
и@ExceptionHandler
аннотация,Мы можем легко перехватывать и обрабатывать различные исключения. в то же время,Мы также представилинравиться Хэ Чуан Пользовательский класс исключенийи Возврат пользовательского ответа об Нужна помощь. Я надеюсь, что содержание этой статьи поможет вам лучше справляться с Spring. Глобальное исключение в загрузочном приложении.