Как настроить 404 ответ в контроллере Spring-MVC?
Быстрый ответ
В Spring MVC для генерации ошибки 404 необходимо вызвать исключение ResponseStatusException
с кодом статуса HttpStatus.NOT_FOUND
:
@GetMapping("/somePath")
public void trigger404() {
// Ваш вопрос: какой ваш любимый HTTP-статус? Ответ: Не найден – 404!
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Ваш ресурс везде искали, но так и не нашли");
}
Этот чёткий код показывает, что запрашиваемый ресурс не найден, что приводит к возникновению ошибки 404.
Рассмотрим также применение схожего подхода в контексте исключения ResourceNotFoundException
.
@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
@GetMapping("/resource/{id}")
public ResponseEntity<?> getResource(@PathVariable("id") String id) {
// Вот вопрос: где этот ресурс?
return yourResourceService.findById(id)
.map(resource -> new ResponseEntity<>(resource, HttpStatus.OK))
.orElseThrow(() -> new ResourceNotFoundException("Ответа нет. Это не игра в 'Найди Вальдо'."));
}
В приведённом примере при отсутствии ресурса генерируется ResourceNotFoundException
, и благодаря аннотации @ResponseStatus
сразу становится очевидным, что следует ожидать ошибку 404.
Детальное рассмотрение механизмов генерации ошибки 404
Подход с использованием ResponseEntity
Применяйте ResponseEntity
для управления ответами с точностью джедая:
@GetMapping("/items/{id}")
public ResponseEntity<Object> getItem(@PathVariable Long id) {
Item item = findItemById(id);
// Отсутствует, как моя мотивация в понедельник
if (item == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(item, HttpStatus.OK);
}
Этот подход предоставляет широкие возможности для тонкой настройки ответа, основываясь на вашей бизнес-логике.
Метод с использованием ModelAndView
Если вас привлекает идея отображения страниц (ведь мы все любим красивые вещи), ModelAndView
станет вашим надёжным помощником:
@GetMapping("/viewItem/{id}")
public ModelAndView viewItem(@PathVariable Long id) {
ModelAndView mav = new ModelAndView();
Item item = findItemById(id);
// Игра в прятки зашла слишком далеко
if (item == null) {
mav.setViewName("error/404");
return mav;
}
mav.addObject("item", item);
mav.setViewName("itemView");
return mav;
}
Метод ModelAndView
позволяет изящно управлять путём, по которому пользователи будут направлены на страницы ошибок.
Обработка исключений для REST-контроллеров
В RESTful API обработчики исключений — это как дежурные, поддерживающие порядок и чистоту вашего кода:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<String> handleResourceNotFoundException(ResourceNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
}
}
Сочетание @RestControllerAdvice
и @ExceptionHandler
обеспечивает централизованное управление исключениями, поддерживая порядок и чистоту в структуре кода.
Инициализация ошибки 404 по условию и добавление гибкости
Гибкость функции isFound()
Иногда необходимо решить, следует ли обозначить ошибку 404, опираясь на конкретные условия:
@GetMapping("/profile")
public ResponseEntity<?> viewProfile(@RequestParam String username) {
return userService.findUserByUsername(username)
.map(user -> new ResponseEntity<>(user, HttpStatus.OK))
.orElseGet(() -> {
// Пользователь просто исчез!
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
});
}
С помощью API Optional в Java 8 можно принимать решения, основываясь на методах isPresent
или isFound
, что делает код более лаконичным и надёжным.
Традиционный подход
В более ранних версиях Spring до 3.0.2 требуется более традиционный подход, напоминающий об использовании классического HttpServletResponse
:
@GetMapping("/oldApproach/items/{id}")
public void getItem(@PathVariable Long id, HttpServletResponse response) {
Item item = findItemById(id);
// Если товар не найден, генерируем ошибку 404 – как город, покинутый жителями
if (item == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
// Иначе продолжаем обработку запроса о товаре
}
Несмотря на свою визуальную громоздкость, этот код предоставляет возможность ручного управления HTTP-статусами, напоминая о старых и простых методах решения задачи.
Проверка с использованием HttpServletRequest
В некоторых случаях полезно провести проверку с помощью HttpServletRequest
, прежде чем сгенерировать ошибку 404:
@GetMapping("/checkRequest/items")
public ResponseEntity<Object> checkItem(HttpServletRequest request) {
// Выполняем проверку, существует ли товар
if (/* условие, основанное на запросе */) {
// Товар пошёл в отпуск и не вернулся!
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
// ...
}
Проверка с использованием HttpServletRequest
позволит вам анализировать различные шаблоны URL и реагировать в зависимости от результата.
Визуализация
Представьте, что ваш контроллер в Spring-MVC — это парк аттракционов:
Добро пожаловать в 🎢 Парк Аттракционов (Ваш Контроллер)
|
🚶♂️Посетитель хочет покататься на аттракционе "🔎 ПоискАттракциона" (Точка Входа)
|
🎟️Проверка билета (Ваша Логика)
|
🚫 Нет такого аттракциона! Что делать?
|
👷♀️Сотрудник парка (Ваш Метод) берёт в руки дело...
|
🛑 **Генерирует исключение NoRideFoundException** – звонок на **404 Not Found**
Ваш сотрудник парка (исключение) всегда на защите, уверяя посетителей в том, что аттракцион недоступен, если он действительно таков.
@Controller
public class ThemeParkController {
@RequestMapping("/findRide")
public String findRide(@RequestParam("rideName") String rideName) {
// Исчезнувший аттракцион, словно мои планы держать диету во время праздников
if (!rideExists(rideName)) {
throw new NoRideFoundException("Извините, аттракцион, который вы ищете, заявлен как закрытый на сегодня");
}
// Аттракцион найден! Добро пожаловать!
return "rideView";
}
}
Наш сотрудник парка всегда решительно действует, чтобы направить посетителей туда, куда нужно.
Полезные материалы
- Annotation Type ResponseStatus – Spring Framework — Узнайте, как отправлять определённые HTTP-статусы с помощью @ResponseStatus.
- Полное руководство по обработке исключений в Spring Boot — Практикуйте обработку исключений в приложениях Spring.
- Обработка исключения 404 Not Found в Spring MVC — Подчерпните полезные советы по работе с ошибками 404 в Spring MVC.
- Руководство по обработке ошибок Spring Boot для REST API — Освойте лучшие практики для эффективной обработки ошибок в RESTful-сервисах на Spring Boot.
- Документация Spring по обработке исключений — Погрузитесь в подробности работы
@ExceptionHandler
в официальной документации Spring.