Это очень распространенный подход, который я рекомендую. В тестовых кодах используется 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("Извините, ресурс не найден!"));
}
@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;
}
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"
}
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;
}
Параметры конструктора имеют следующее значение:
В данной статье рассмотрены три способа обработки исключений:
@ControllerAdvice
и @ExceptionHandler
для обработки глобальных исключений@ExceptionHandler
для обработки исключений на уровне контроллераResponseStatusException
Код доступен по адресу: https://github.com/Snailclimb/springboot-guide/tree/master/source-code/basis/springboot-handle-exception
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )