HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Во время работы приложения могут возникать ошибки, которые должны транслироваться в правильные коды ответа. Всего в Spring можно выделить две большие группы ошибок:</p>
1 <p>Во время работы приложения могут возникать ошибки, которые должны транслироваться в правильные коды ответа. Всего в Spring можно выделить две большие группы ошибок:</p>
2 <ul><li>Ошибки внутри Spring Boot - это исключения, которые фреймворк генерирует в ответ на разные ситуации</li>
2 <ul><li>Ошибки внутри Spring Boot - это исключения, которые фреймворк генерирует в ответ на разные ситуации</li>
3 <li>Ошибки в коде приложения - это исключения, которые возникают в нашем коде или коде библиотек внутри нашего кода</li>
3 <li>Ошибки в коде приложения - это исключения, которые возникают в нашем коде или коде библиотек внутри нашего кода</li>
4 </ul><p>Рассмотрим каждую группу отдельно.</p>
4 </ul><p>Рассмотрим каждую группу отдельно.</p>
5 <p>Взаимодействие с внешней средой непредсказуемо. Всегда есть вероятность получить несоответствие между ожиданиями Spring Boot и реальностью. Обычно это проявляется в неправильно сформированных HTTP-запросах. Представим, что у нас есть такой обработчик:</p>
5 <p>Взаимодействие с внешней средой непредсказуемо. Всегда есть вероятность получить несоответствие между ожиданиями Spring Boot и реальностью. Обычно это проявляется в неправильно сформированных HTTP-запросах. Представим, что у нас есть такой обработчик:</p>
6 <p>Что будет, если мы выполним запрос с параметром limit, передав туда строку? В ответ мы получим ошибку 400, которая указывает на "плохой запрос":</p>
6 <p>Что будет, если мы выполним запрос с параметром limit, передав туда строку? В ответ мы получим ошибку 400, которая указывает на "плохой запрос":</p>
7 <p>Эту ситуацию Spring Boot обрабатывает внутри себя. Точно так же он обрабатывает и множество других ситуаций, среди которых:</p>
7 <p>Эту ситуацию Spring Boot обрабатывает внутри себя. Точно так же он обрабатывает и множество других ситуаций, среди которых:</p>
8 <ul><li>Используется неподдерживаемый HTTP-метод</li>
8 <ul><li>Используется неподдерживаемый HTTP-метод</li>
9 <li>Используется неподдерживаемый media type</li>
9 <li>Используется неподдерживаемый media type</li>
10 <li>Параметры обработчика не проходят валидацию</li>
10 <li>Параметры обработчика не проходят валидацию</li>
11 </ul><p>Всего есть около 15 ошибок-исключений. Каждое исключение обрабатывается автоматически. После обработки мы получаем соответствующий HTTP-код и тело с описанием ошибки:</p>
11 </ul><p>Всего есть около 15 ошибок-исключений. Каждое исключение обрабатывается автоматически. После обработки мы получаем соответствующий HTTP-код и тело с описанием ошибки:</p>
12 <p>Обработкой этих ошибок в Spring Boot занимается класс<a>ResponseEntityExceptionHandler</a>. Он вызывается автоматически для обработки любых ошибок, возникающих во время обработки маршрута (диспетчеризации). Причем это работает не только для кода самого Spring Boot, но и для кода внутри обработчика.</p>
12 <p>Обработкой этих ошибок в Spring Boot занимается класс<a>ResponseEntityExceptionHandler</a>. Он вызывается автоматически для обработки любых ошибок, возникающих во время обработки маршрута (диспетчеризации). Причем это работает не только для кода самого Spring Boot, но и для кода внутри обработчика.</p>
13 <p>Чтобы лучше понять обработку ошибок, советуем открыть исходники класса ResponseEntityExceptionHandler и изучить их.</p>
13 <p>Чтобы лучше понять обработку ошибок, советуем открыть исходники класса ResponseEntityExceptionHandler и изучить их.</p>
14 <h2>Ошибки в коде приложения</h2>
14 <h2>Ошибки в коде приложения</h2>
15 <p>Если ничего специально не делать, то любые ошибки внутри кода приложения будут автоматически приводиться к HTTP-коду 500. Для большинства ошибок это желаемое поведение, но иногда нужна и особая обработка. Например, важно выдать ошибку 404, когда запись в базе данных не найдена.</p>
15 <p>Если ничего специально не делать, то любые ошибки внутри кода приложения будут автоматически приводиться к HTTP-коду 500. Для большинства ошибок это желаемое поведение, но иногда нужна и особая обработка. Например, важно выдать ошибку 404, когда запись в базе данных не найдена.</p>
16 <p>Посмотрим, что произойдет в коде ниже, если данных в базе нет:</p>
16 <p>Посмотрим, что произойдет в коде ниже, если данных в базе нет:</p>
17 <p>В этом случае вернется ошибка с кодом 500. С точки зрения HTTP, это неверное поведение. В этом случае правильный код возврата - 404. Технически мы можем вернуть код 404 с помощью ResponseEntity. Нам понадобится метод ResponseEntity.of(). Он принимает на вход Optional и возвращает коды 200 или 404 в зависимости от того, есть результат или нет:</p>
17 <p>В этом случае вернется ошибка с кодом 500. С точки зрения HTTP, это неверное поведение. В этом случае правильный код возврата - 404. Технически мы можем вернуть код 404 с помощью ResponseEntity. Нам понадобится метод ResponseEntity.of(). Он принимает на вход Optional и возвращает коды 200 или 404 в зависимости от того, есть результат или нет:</p>
18 <p>Но бывают и более сложные ситуации, в которых одним таким методом не обойтись. Например, мы не всегда имеем дело с Optional, иногда требуется дополнительная логика для формирования ответа. В таких ситуациях, удобнее определить свой обработчик ошибки на базе ResponseEntityExceptionHandler.</p>
18 <p>Но бывают и более сложные ситуации, в которых одним таким методом не обойтись. Например, мы не всегда имеем дело с Optional, иногда требуется дополнительная логика для формирования ответа. В таких ситуациях, удобнее определить свой обработчик ошибки на базе ResponseEntityExceptionHandler.</p>
19 <p>Для централизованной обработки ошибки 404 нужно выполнить три шага.</p>
19 <p>Для централизованной обработки ошибки 404 нужно выполнить три шага.</p>
20 <p><strong>Шаг 1.</strong>Создать исключение:</p>
20 <p><strong>Шаг 1.</strong>Создать исключение:</p>
21 <p><strong>Шаг 2.</strong>Реализовать глобальный обработчик этого исключения:</p>
21 <p><strong>Шаг 2.</strong>Реализовать глобальный обработчик этого исключения:</p>
22 <p>Чтобы Spring Boot начал использовать наш обработчик ошибок для всех контроллеров сразу, нужно использовать несколько аннотаций:</p>
22 <p>Чтобы Spring Boot начал использовать наш обработчик ошибок для всех контроллеров сразу, нужно использовать несколько аннотаций:</p>
23 <ul><li>@ControllerAdvice указывает, что этот класс отвечает за централизованную обработку исключений</li>
23 <ul><li>@ControllerAdvice указывает, что этот класс отвечает за централизованную обработку исключений</li>
24 <li>@ExceptionHandler указывает, какое исключение должно обрабатываться проаннотированным методом</li>
24 <li>@ExceptionHandler указывает, какое исключение должно обрабатываться проаннотированным методом</li>
25 </ul><p>Сам метод похож на обычный обработчик маршрута. Разница только в том, что ему на вход подается возникшее исключение. Далее мы сами описываем логику и возвращаем ResponseEntity с правильным кодом и телом ответа.</p>
25 </ul><p>Сам метод похож на обычный обработчик маршрута. Разница только в том, что ему на вход подается возникшее исключение. Далее мы сами описываем логику и возвращаем ResponseEntity с правильным кодом и телом ответа.</p>
26 <p><strong>Шаг 3.</strong>Внедрить использование исключения в обработчики маршрутов:</p>
26 <p><strong>Шаг 3.</strong>Внедрить использование исключения в обработчики маршрутов:</p>
27  
27