Ответ
В Spring MVC для глобальной обработки исключений и выполнения перенаправления (redirect) используются аннотации @ControllerAdvice и @ExceptionHandler.
1. Создание пользовательского исключения
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
// Можно добавить дополнительные поля, например, userId
}
2. Создание класса-обработчика исключений (@ControllerAdvice)
Класс, помеченный @ControllerAdvice, перехватывает исключения, выброшенные в любом контроллере.
@ControllerAdvice // Объявляет глобальный обработчик исключений
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class) // Указывает тип обрабатываемого исключения
public String handleUserNotFoundException(UserNotFoundException ex,
HttpServletRequest request,
RedirectAttributes redirectAttributes) {
// 1. Логирование исключения (обязательно для отладки)
logger.error("User not found for request: " + request.getRequestURI(), ex);
// 2. Добавление flash-атрибута для передачи сообщения на страницу регистрации
// Flash-атрибуты живут ровно один redirect, что идеально подходит для этой задачи.
redirectAttributes.addFlashAttribute("errorMessage",
"Пользователь не найден. Пожалуйста, зарегистрируйтесь.");
// 3. Выполнение redirect на URL страницы регистрации
return "redirect:/register"; // Предполагается, что есть маппинг на "/register"
}
}
3. Контроллер, который бросает исключение
@Controller
public class UserController {
@GetMapping("/user/{id}")
public String getUserProfile(@PathVariable Long id, Model model) {
User user = userService.findById(id)
.orElseThrow(() -> new UserNotFoundException("User with id " + id + " not found"));
model.addAttribute("user", user);
return "profile";
}
}
4. Контроллер и страница регистрации
@Controller
public class RegistrationController {
@GetMapping("/register")
public String showRegistrationForm(Model model) {
// Атрибут "errorMessage" будет автоматически подставлен из flash-атрибута
// если он был установлен в обработчике исключений.
if (!model.containsAttribute("userDto")) {
model.addAttribute("userDto", new UserDto());
}
return "registration-page"; // Имя Thymeleaf/HTML шаблона
}
}
В шаблоне registration-page.html (например, Thymeleaf) можно отобразить сообщение:
<div th:if="${errorMessage}" class="alert alert-danger">
<span th:text="${errorMessage}"></span>
</div>
<!-- Остальная форма регистрации -->
Ключевые моменты:
@ControllerAdvice+@ExceptionHandler— стандартный и мощный механизм для централизованной обработки исключений.RedirectAttributesиспользуется для безопасной передачи данных между запросами при redirect.- Flash-атрибуты (
addFlashAttribute) идеальны для передачи сообщений об ошибках, так как они не попадают в URL и существуют один запрос. - Всегда логируйте исключения для последующего анализа.
- Этот подход отделяет логику обработки ошибок от бизнес-логики контроллеров, делая код чище и поддерживаемее.