← Назад к вопросам

Как обработать UserNotFoundException и сделать redirect на страницу регистрации

2.0 Middle🔥 161 комментариев
#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Обработка UserNotFoundException с редиректом на регистрацию

В Spring приложении обработка исключений и редирект — это стандартная задача. Существует несколько подходов в зависимости от архитектуры (MVC, REST API, гибридный подход).

Подход 1: @ExceptionHandler в @ControllerAdvice (рекомендуется)

Это глобальный обработчик исключений для всего приложения:

@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(UserNotFoundException.class)
    public String handleUserNotFound(UserNotFoundException ex, Model model) {
        model.addAttribute("error", ex.getMessage());
        return "redirect:/auth/register";
    }
}

Если нужно передать параметры в URL:

@ExceptionHandler(UserNotFoundException.class)
public RedirectView handleUserNotFound(UserNotFoundException ex) {
    RedirectView redirect = new RedirectView();
    redirect.setUrl("/auth/register?error=" + URLEncoder.encode(ex.getMessage(), StandardCharsets.UTF_8));
    return redirect;
}

Подход 2: Обработка в контроллере

Если нужна локальная обработка только в одном контроллере:

@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
        // или
        return userService.findById(id)
            .orElseThrow(() -> new UserNotFoundException("User not found"));
    }
    
    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<?> handleUserNotFound(UserNotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
            .body(new ErrorResponse("user_not_found", ex.getMessage()));
    }
}

Подход 3: Custom Exception с перехватом на уровне Filter

Для web-приложений (не REST) можно использовать фильтр:

@Component
public class ExceptionHandlerFilter extends OncePerRequestFilter {
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                   HttpServletResponse response, 
                                   FilterChain filterChain) 
            throws ServletException, IOException {
        try {
            filterChain.doFilter(request, response);
        } catch (UserNotFoundException ex) {
            response.sendRedirect("/auth/register?error=user_not_found");
        }
    }
}

Подход 4: Использование HttpSession для передачи сообщения об ошибке

@ExceptionHandler(UserNotFoundException.class)
public String handleUserNotFound(UserNotFoundException ex, 
                                 HttpSession session) {
    session.setAttribute("error", ex.getMessage());
    return "redirect:/auth/register";
}

// На странице регистрации
// <c:if test="${not empty sessionScope.error}">
//     <div class="alert alert-danger">${sessionScope.error}</div>
// </c:if>

Определение собственного исключения

public class UserNotFoundException extends RuntimeException {
    private String userId;
    
    public UserNotFoundException(String message) {
        super(message);
    }
    
    public UserNotFoundException(String message, String userId) {
        super(message);
        this.userId = userId;
    }
    
    public String getUserId() {
        return userId;
    }
}

REST API: Что вернуть вместо редиректа?

Для REST API редирект 302/301 некорректен. Вместо этого возвращают JSON:

@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException ex) {
    ErrorResponse error = new ErrorResponse(
        "USER_NOT_FOUND",
        "User does not exist. Please register first.",
        "/auth/register"
    );
    return ResponseEntity
        .status(HttpStatus.NOT_FOUND)
        .body(error);
}

Клиент (JavaScript) обрабатывает статус 404 и сам перенаправляет:

fetch("/api/users/123")
    .then(res => {
        if (res.status === 404) {
            window.location.href = "/auth/register";
        }
        return res.json();
    })
    .catch(err => console.error(err));

Лучшие практики

  1. Используй @ControllerAdvice для централизованной обработки
  2. Логируй исключения перед редиректом
  3. Передавай информацию об ошибке через параметры URL или session
  4. Проверяй безопасность — не раскрывай чувствительную информацию
  5. Используй правильные HTTP статусы: 302/303 для редиректа, 404 для REST API
  6. Тестируй обработку исключений через unit и integration тесты