← Назад к вопросам
Что такое @ControllerAdvice?
2.0 Middle🔥 201 комментариев
#REST API и микросервисы#Spring Framework
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое @ControllerAdvice
@ControllerAdvice — это аннотация Spring Framework, которая позволяет определить глобальный обработчик исключений и другие кросс-функциональные компоненты для всех контроллеров приложения. Она предоставляет централизованный способ обработки ошибок и исключений в REST API.
Основное назначение
@ControllerAdvice используется для:
- Глобальной обработки исключений — перехват исключений из всех контроллеров
- Подготовки моделей данных — инициализация данных для всех представлений
- Преобразования данных — конвертация между форматами
- Валидации данных — применение кастомной валидации
Архитектура и использование
// Простой пример глобального обработчика
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ResponseEntity<ErrorResponse> handleResourceNotFound(
ResourceNotFoundException ex) {
ErrorResponse error = new ErrorResponse(
"NOT_FOUND",
ex.getMessage(),
System.currentTimeMillis()
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<ErrorResponse> handleIllegalArgument(
IllegalArgumentException ex) {
ErrorResponse error = new ErrorResponse(
"BAD_REQUEST",
ex.getMessage(),
System.currentTimeMillis()
);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ResponseEntity<ErrorResponse> handleGenericException(Exception ex) {
ErrorResponse error = new ErrorResponse(
"INTERNAL_SERVER_ERROR",
"An unexpected error occurred",
System.currentTimeMillis()
);
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(error);
}
}
Класс для ответа об ошибке
public class ErrorResponse {
private String code;
private String message;
private long timestamp;
private List<FieldError> errors;
public ErrorResponse(String code, String message, long timestamp) {
this.code = code;
this.message = message;
this.timestamp = timestamp;
this.errors = new ArrayList<>();
}
// getters и setters
public String getCode() { return code; }
public String getMessage() { return message; }
public long getTimestamp() { return timestamp; }
public List<FieldError> getErrors() { return errors; }
}
Обработка ошибок валидации
@ControllerAdvice
public class ValidationExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<ErrorResponse> handleValidationExceptions(
MethodArgumentNotValidException ex) {
ErrorResponse error = new ErrorResponse(
"VALIDATION_ERROR",
"Validation failed",
System.currentTimeMillis()
);
// Собираем все ошибки валидации
ex.getBindingResult().getAllErrors().forEach(err -> {
String fieldName = ((FieldError) err).getField();
String errorMessage = err.getDefaultMessage();
error.getErrors().add(new FieldError(fieldName, errorMessage));
});
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
}
Инициализация данных для всех представлений
@ControllerAdvice
public class GlobalControllerAdvice {
@ModelAttribute("currentUser")
public User currentUser(Principal principal) {
if (principal != null) {
return userService.findByUsername(principal.getName());
}
return null;
}
@ModelAttribute("siteName")
public String siteName() {
return "My Application";
}
}
Преобразователь (Converter) для всех контроллеров
@ControllerAdvice
public class GlobalConverters {
@InitBinder
public void initBinder(WebDataBinder binder) {
// Регистрируем кастомный форматер для даты
binder.registerCustomEditor(LocalDate.class,
new PropertyEditorSupport() {
@Override
public void setAsText(String text) {
setValue(LocalDate.parse(text,
DateTimeFormatter.ofPattern("dd/MM/yyyy")));
}
});
}
}
Ограничение области действия
Если нужно применить ControllerAdvice только к определённым контроллерам:
@ControllerAdvice(assignableTypes = {UserController.class, AdminController.class})
public class SpecificExceptionHandler {
// Обработка только для указанных контроллеров
}
// Или по пакетам
@ControllerAdvice(basePackages = {"com.example.api", "com.example.admin"})
public class PackageBasedAdvice {
// Обработка для контроллеров из указанных пакетов
}
Преимущества @ControllerAdvice
- DRY принцип — не нужно писать обработку ошибок в каждом контроллере
- Консистентность — все ошибки обрабатываются одинаково
- Централизация — вся логика обработки в одном месте
- Переиспользуемость — методы могут применяться к разным типам исключений
- Улучшенная безопасность — можно скрывать внутренние детали ошибок от клиентов
Заключение
@ControllerAdvice — это мощный инструмент Spring Framework для создания чистой и поддерживаемой архитектуры обработки ошибок. Вместо разбросанной логики обработки исключений по всему коду, вы получаете централизованное, тестируемое и расширяемое решение, которое упрощает разработку REST API.