0Pricing
Java Academy · Урок

Детали проблемы RFC 7807 и единообразные ответы с ошибками

Возвращайте структурированные данные об ошибках в соответствии с RFC 7807, используя ProblemDetail из Spring 6.

«Детали проблемы RFC 7807 и единообразные ответы с ошибками» — бесплатный урок Java Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Что такое RFC 7807?

RFC 7807 «Подробности проблемы для HTTP API» определяет стандартный формат JSON для ответов с ошибками. Это избавляет API от необходимости использовать собственные форматы ошибок и дает клиентам предсказуемую структуру для разбора.

Поля RFC 7807

Стандартные поля: type (URI, идентифицирующий проблему), title (краткое описание для пользователя), status (код состояния HTTP), detail (конкретное объяснение), instance (URI конкретного случая).

{
  "type": "https://api.example.com/errors/not-found",
  "title": "Resource Not Found",
  "status": 404,
  "detail": "User with id 42 does not exist.",
  "instance": "/api/users/42"
}

ProblemDetail в Spring 6

Spring 6 и Spring Boot 3 поставляются со встроенной поддержкой ProblemDetail. Возвращайте ProblemDetail из обработчиков исключений или используйте ErrorResponseException.

import org.springframework.http.ProblemDetail;

@ExceptionHandler(ResourceNotFoundException.class)
public ProblemDetail handleNotFound(ResourceNotFoundException ex, HttpServletRequest req) {
    ProblemDetail pd = ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage());
    pd.setType(URI.create("https://api.example.com/errors/not-found"));
    pd.setTitle("Resource Not Found");
    pd.setInstance(URI.create(req.getRequestURI()));
    return pd;
}

Добавление пользовательских расширений

ProblemDetail поддерживает свойства расширения через setProperty(key, value) для дополнительных сведений предметной области, таких как коды ошибок или ошибки полей.

ProblemDetail pd = ProblemDetail.forStatus(HttpStatus.BAD_REQUEST);
pd.setTitle("Validation Failed");
pd.setProperty("errors", fieldErrors); // custom extension
pd.setProperty("timestamp", Instant.now());

Включение RFC 7807 для Spring MVC

Включите ProblemDetail для всех встроенных исключений Spring, задав spring.mvc.problemdetails.enabled=true в application.properties. После этого Spring автоматически оборачивает стандартные исключения (404, 405 и т. д.) в формат RFC 7807.

# application.properties:
spring.mvc.problemdetails.enabled=true

ErrorResponseException

Выбрасывайте ErrorResponseException из кода сервиса, чтобы получить ответ RFC 7807 без метода-обработчика — Spring MVC перехватывает это исключение и форматирует ответ.

throw new ErrorResponseException(HttpStatus.CONFLICT,
    ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT,
        "Email already exists: " + email), null);

Пользовательский подкласс ProblemDetail

Создайте подкласс ProblemDetail, предназначенный для конкретной предметной области, чтобы добавить типизированные поля расширения и сохранить код обработчиков чистым.

public class ValidationProblemDetail extends ProblemDetail {
    private final Map<String, String> fieldErrors;
    public ValidationProblemDetail(Map<String, String> errors) {
        super(HttpStatus.BAD_REQUEST.value());
        this.fieldErrors = errors;
        setTitle("Validation Failed");
        setProperty("fieldErrors", errors);
    }
}

Тип содержимого: application/problem+json

Ответы RFC 7807 должны использовать тип содержимого application/problem+json, чтобы клиенты могли отличать ответы с описанием проблем от обычных полезных данных JSON.

return ResponseEntity.status(HttpStatus.NOT_FOUND)
    .contentType(MediaType.APPLICATION_PROBLEM_JSON)
    .body(pd);

Контрольный список единообразной структуры ошибок

Хороший API ошибок содержит: (1) URI типа, пригодный для машинной обработки, (2) понятный человеку заголовок, (3) точный код состояния HTTP, (4) конкретное сообщение с подробностями, (5) URI экземпляра запроса, (6) необязательные поля расширения (временная метка, traceId, ошибки полей).

Идентификаторы трассировки для наблюдаемости

Добавьте идентификатор трассировки запроса (из Micrometer Tracing или MDC) как свойство расширения, чтобы разработчики могли сопоставить записи об ошибках с конкретным неудачным запросом.

pd.setProperty("traceId", MDC.get("traceId"));
pd.setProperty("timestamp", Instant.now());

Тестирование сведений о проблемах

В тестах @WebMvcTest проверьте, что тип содержимого ответа — application/problem+json, а такие поля JSON, как status, title и detail, соответствуют ожидаемым значениям.

mockMvc.perform(get("/api/users/999"))
    .andExpect(status().isNotFound())
    .andExpect(content().contentType("application/problem+json"))
    .andExpect(jsonPath("$.status").value(404))
    .andExpect(jsonPath("$.title").value("Resource Not Found"));

Быстрая проверка

Какое свойство Spring Boot включает RFC 7807 для встроенных исключений Spring MVC?

Итоги

RFC 7807 стандартизирует ответы JSON с ошибками, используя поля type, title, status, detail и instance. Spring 6 предоставляет ProblemDetail и ErrorResponseException. Включите поддержку с помощью spring.mvc.problemdetails.enabled=true. Добавьте traceId и временную метку в качестве расширений для наблюдаемости.

Часто задаваемые вопросы

Урок «Детали проблемы RFC 7807 и единообразные ответы с ошибками» бесплатный?

Да — полный текст урока «Детали проблемы RFC 7807 и единообразные ответы с ошибками» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Детали проблемы RFC 7807 и единообразные ответы с ошибками»?

Возвращайте структурированные данные об ошибках в соответствии с RFC 7807, используя ProblemDetail из Spring 6. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Детали проблемы RFC 7807 и единообразные ответы с ошибками»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Проверка компонентов: @NotNull, @Size, @Pattern
  2. Пользовательские аннотации ограничений
  3. Глобальная обработка исключений с @ControllerAdvice
  4. Детали проблемы RFC 7807 и единообразные ответы с ошибками
← Назад к Java Academy