Java for Beginner
677 subscribers
546 photos
155 videos
12 files
838 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Обработка ошибок в REST API с использованием Spring Boot

Эффективная обработка ошибок в REST API — важный аспект разработки, обеспечивающий ясность и удобство использования для клиентов. API должен возвращать информативные сообщения об ошибках в стандартизированном формате, указывать причины проблемы и, по возможности, предлагать пути решения.

1. Основные аспекты обработки ошибок


Использование HTTP-кодов:
1xx: Informational (информационные)
2xx: Success (успешно)
3xx: Redirection (перенаправление)
4xx: Client
Error (ошибка клиента, например, неправильный запрос, ресурс не найден).
5xx: Server
Error (ошибка сервера, например, проблемы на уровне базы данных или приложения).

Возврат стандартного формата ошибки: Сообщения об ошибках должны быть понятны и содержать:
- Код состояния HTTP.
- Сообщение об ошибке.
- Вспомогательную информацию (например, время ошибки или идентификатор запроса).


Обработка различных типов ошибок:
- Ошибки валидации.
- Отсутствие ресурсов.
- Некорректный формат запроса.
- Ошибки на уровне сервера.


2. Обработка ошибок с использованием @ControllerAdvice

Аннотация @ControllerAdvice позволяет централизованно обрабатывать исключения, возникающие в контроллерах.

Создайте класс для обработки исключений:
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(RuntimeException.class)
public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
ex.getMessage(),
System.currentTimeMillis()
);
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFoundException(ResourceNotFoundException ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
ex.getMessage(),
System.currentTimeMillis()
);
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}
}


Класс ответа на ошибку:
public class ErrorResponse {

private int status;
private String message;
private long timestamp;

public ErrorResponse(int status, String message, long timestamp) {
this.status = status;
this.message = message;
this.timestamp = timestamp;
}

// Геттеры и сеттеры...
}


Пользовательское исключение для отсутствия ресурса:
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}


#Java #Training #Spring #API_Errors
3. Обработка ошибок валидации

Spring Boot поддерживает валидацию запросов с помощью аннотаций javax.validation. Ошибки можно обрабатывать централизованно.

Добавьте валидацию в сущность:
import jakarta.validation.constraints.*;

@Entity
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotBlank(message = "Name cannot be blank")
private String name;

@Email(message = "Invalid email address")
private String email;

@Min(value = 18, message = "Age must be at least 18")
private Integer age;

// Геттеры и сеттеры...
}


Обработайте ошибки валидации:

import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
for (FieldError error : ex.getBindingResult().getFieldErrors()) {
errors.put(error.getField(), error.getDefaultMessage());
}
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}
}


Пример ответа при ошибке валидации:
{
"name": "Name cannot be blank",
"email": "Invalid email address"
}


4. Обработка ошибок на уровне контроллера

Если требуется специфичная обработка для одного контроллера, можно использовать аннотацию @ExceptionHandler внутри самого контроллера.
@RestController
@RequestMapping("/api/users")
public class UserController {

@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id));
}

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
ex.getMessage(),
System.currentTimeMillis()
);
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}
}


5. Настройка формата ответа

Вы можете настроить формат ответа об ошибке на уровне всего приложения с помощью аннотации @RestControllerAdvice (аналог @ControllerAdvice, но возвращает JSON по умолчанию).

@RestControllerAdvice
public class GlobalRestExceptionHandler {

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGlobalException(Exception ex) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
"An unexpected error occurred",
System.currentTimeMillis()
);
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}


#Java #Training #Spring #API_Errors
6. Настройка ошибок Spring Boot

Spring Boot возвращает стандартные страницы ошибок, такие как Whitelabel Error Page. Для кастомизации ошибок используйте ErrorController.

Отключите Whitelabel Error Page:
server.error.whitelabel.enabled=false
Создайте собственный контроллер ошибок:
java
Копировать код
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.context.request.WebRequest;

import java.util.Map;

@Controller
public class CustomErrorController implements ErrorController {

private final ErrorAttributes errorAttributes;

public CustomErrorController(ErrorAttributes errorAttributes) {
this.errorAttributes = errorAttributes;
}

@RequestMapping("/error")
public ResponseEntity<Map<String, Object>> handleError(WebRequest webRequest) {
Map<String, Object> errors = errorAttributes.getErrorAttributes(webRequest, ErrorAttributeOptions.defaults());
HttpStatus status = HttpStatus.valueOf((int) errors.get("status"));
return new ResponseEntity<>(errors, status);
}
}


7. Пример API с обработкой ошибок

Пример запроса:
GET /api/users/999


Пример ответа:

{
"status": 404,
"message": "User not found with id: 999",
"timestamp": 1702745190123
}


8. Советы по обработке ошибок

Возвращайте только необходимую информацию:
Не отправляйте stack trace клиенту.
Показывайте сообщение об ошибке, понятное конечному пользователю.


Используйте стандартные HTTP-коды:
400 (Bad Request) — ошибка клиента.
401 (Unauthorized) — пользователь не авторизован.
404 (Not Found) — ресурс не найден.
500 (Internal Server
Error) — ошибка сервера.

Добавьте логирование: Все ошибки должны логироваться для анализа.


#Java #Training #Spring #API_Errors