1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/GiteeOS-springboot-guide

Клонировать/Скачать
springboot-handle-exception.md 11 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 04.06.2025 10:20 f496caa

1. Обработка глобальных исключений с помощью @ControllerAdvice и @ExceptionHandler

Это очень распространенный подход, который я рекомендую. В тестовых кодах используется JUnit 5, поэтому при проверке кода в новом проекте убедитесь, что добавлены соответствующие зависимости.

1. Создание класса для представления информации об ошибке

Это необязательный класс, который используется для упаковки информации об ошибке.

src/main/java/com/twuc/webApp/exception/ErrorResponse.java

/**
 * @author shuang.kou
 */
public class ErrorResponse {

    private String message;
    private String errorTypeName;

    public ErrorResponse(Exception e) {
        this(e.getClass().getName(), e.getMessage());
    }

    public ErrorResponse(String errorTypeName, String message) {
        this.errorTypeName = errorTypeName;
        this.message = message;
    }
    ......пропущены getter и setter методы
}

2. Создание пользовательского типа исключения

src/main/java/com/twuc/webApp/exception/ResourceNotFoundException.java

Обычно мы обрабатываем исключения типа RuntimeException, поэтому если вам нужно создать пользовательский тип исключения, вы можете наследоваться от этого класса.

/**
 * @author shuang.kou
 * Пользовательский тип исключения
 */
public class ResourceNotFoundException extends RuntimeException {
    private String message;

    public ResourceNotFoundException() {
        super();
    }

    public ResourceNotFoundException(String message) {
        super(message);
        this.message = message;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
```**3. Создание класса для обработки исключений**

Добавив аннотацию `@ControllerAdvice` к классу, вы делаете его глобальным обработчиком исключений. Вы также можете использовать `assignableTypes` для указания конкретного типа контроллера, чтобы обработчик исключений обрабатывал исключения только для определенного контроллера.

`src/main/java/com/twuc/webApp/exception/GlobalExceptionHandler.java`

```java
/**
 * @author shuang.kou
 */
@ControllerAdvice(assignableTypes = {ExceptionController.class})
@ResponseBody
public class GlobalExceptionHandler {

    ErrorResponse illegalArgumentResponse = new ErrorResponse(new IllegalArgumentException("Параметр неверен!"));
    ErrorResponse resourseNotFoundResponse = new ErrorResponse(new ResourceNotFoundException("Извините, ресурс не найден!"));
}

2. Обработка исключений на уровне контроллера с помощью @ExceptionHandler

@ExceptionHandler(value = Exception.class) // Перехват всех исключений. Это сделано для демонстрации; обычно один метод обрабатывает только одно исключение.
public ResponseEntity<ErrorResponse> exceptionHandler(Exception e) {

    if (e instanceof IllegalArgumentException) {
        return ResponseEntity.status(400).body(illegalArgumentResponse);
    } else if (e instanceof ResourceNotFoundException) {
        return ResponseEntity.status(404).body(resourseNotFoundResponse);
    }
    return null;
}

4. Моделирование выброса исключений в контроллере

src/main/java/com/twuc/webApp/web/ExceptionController.java

/**
 * @author shuang.kou
 */
@RestController
@RequestMapping("/api")
public class ExceptionController {

    @GetMapping("/illegalArgumentException")
    public void throwException() {
        throw new IllegalArgumentException();
    }

    @GetMapping("/resourceNotFoundException")
    public void throwException2() {
        throw new ResourceNotFoundException();
    }
}
```Используйте GET-запрос [localhost:8080/api/resourceNotFoundException](localhost:8333/api/resourceNotFoundException) (curl -i -s -X GET url), чтобы получить следующие JSON-данные с сервера:

```json
{
    "message": "Sorry, the resourse not found!",
    "errorTypeName": "com.twuc.webApp.exception.ResourceNotFoundException"
}

5. Написание тестового класса

MockMvc предоставляется пакетом org.springframework.boot.test и реализует имитацию HTTP-запросов, обычно используется для тестирования уровня контроллера.

/**
 * @author shuang.kou
 */
@AutoConfigureMockMvc
@SpringBootTest
public class ExceptionTest {
    @Autowired
    MockMvc mockMvc;

    @Test
    void should_return_400_if_param_not_valid() throws Exception {
        mockMvc.perform(get("/api/illegalArgumentException"))
                .andExpect(status().is(400))
                .andExpect(jsonPath("$.message").value("Параметр неверен!"));
    }

    @Test
    void should_return_404_if_resourse_not_found() throws Exception {
        mockMvc.perform(get("/api/resourceNotFoundException"))
                .andExpect(status().is(404))
                .andExpect(jsonPath("$.message").value("Извините, ресурс не найден!"));
    }
}

```Недавно мы упомянули, что использование аннотации @ControllerAdvice и метода `assignableTypes` позволяет указать конкретные классы для обработки исключений. Поэтому такой подход к обработке исключений сейчас используется реже.

Мы можем переместить следующий фрагмент кода в файл src/main/java/com/twuc/webApp/exception/GlobalExceptionHandler.java.

    @ExceptionHandler(value = Exception.class) // перехват всех исключений
    public ResponseEntity<ErrorResponse> exceptionHandler(Exception e) {

        if (e instanceof IllegalArgumentException) {
            return ResponseEntity.status(400).body(illegalArgumentResponse);
        } else if (e instanceof ResourceNotFoundException) {
            return ResponseEntity.status(404).body(resourseNotFoundResponse);
        }
        return null;
    }
```### 3. ResponseStatusException

Для изучения `ResponseStatusException` рассмотрим простой метод обработки исключений с использованием аннотации `@ResponseStatus` (отображение исключений в коды состояния).

`src/main/java/com/twuc/webApp/exception/ResourceNotFoundException.java`

```java
@ResponseStatus(code = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {

    public ResourceNotFoundException() {
    }

    public ResourceNotFoundException(String message) {
        super(message);
    }
}

src/main/java/com/twuc/webApp/web/ResponseStatusExceptionController.java

@RestController
@RequestMapping("/api")
public class ResponseStatusExceptionController {
    @GetMapping("/resourceNotFoundException2")
    public void throwException3() {
        throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Извините, ресурс не найден!", new ResourceNotFoundException());
    }
}

Используя GET-запрос к [localhost:8080/api/resourceNotFoundException2](localhost:8333/api/resourceNotFoundException2), сервер вернет следующие данные в формате JSON:

{
    "timestamp": "2019-08-21T07:11:43.744+0000",
    Yöntem: 404,
    "error": "Not Found",
    "message": "Извините, ресурс не найден!",
    "path": "/api/resourceNotFoundException2"
}

Простой метод обработки исключений с использованием аннотации @ResponseStatus имеет преимущество простоты, но обычно мы не используем такой подход. Вместо этого мы используем ResponseStatusException, что позволяет избежать необходимости создания дополнительных классов исключений.java @GetMapping("/resourceNotFoundException2") public void throwException3() { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Извините, ресурс не найден!", new ResourceNotFoundException()); } Используйте GET-запрос localhost:8080/api/resourceNotFoundException2, и сервер вернет JSON-данные в следующем формате, аналогичные результату, полученному с помощью ResponseStatus. ```json { "timestamp": "2019-08-21T07:28:12.017+0000", "status": 404, "error": "Не найдено", "message": "Извините, ресурс не найден!", "path": "/api/resourceNotFoundException3" }


`ResponseStatusException` имеет три конструктора:

```java
   public ResponseStatusException(HttpStatus status) {
   	this(status, null, null);
   }

   public ResponseStatusException(HttpStatus status, @Nullable String reason) {
   	this(status, reason, null);
   }

   public ResponseStatusException(HttpStatus status, @Nullable String reason, @Nullable Throwable cause) {
   	super(null, cause);
   	Assert.notNull(status, "HttpStatus is required");
   	this.status = status;
   	this.reason = reason;
   }

Параметры конструктора имеют следующее значение:

  • status: HTTP статус
  • reason: сообщение ответа
  • cause: выброшенное исключение

Заключение

В данной статье рассмотрены три способа обработки исключений:

  1. Использование @ControllerAdvice и @ExceptionHandler для обработки глобальных исключений
  2. @ExceptionHandler для обработки исключений на уровне контроллера
  3. ResponseStatusException

Код доступен по адресу: https://github.com/Snailclimb/springboot-guide/tree/master/source-code/basis/springboot-handle-exception

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/GiteeOS-springboot-guide.git
git@api.gitlife.ru:oschina-mirror/GiteeOS-springboot-guide.git
oschina-mirror
GiteeOS-springboot-guide
GiteeOS-springboot-guide
master