REST 서비스에 대한 일반적인 요구 사항은 오류 응답 본문에 세부 정보를 포함하는 것입니다. Spring Framework는 "HTTP API에 대한 문제 세부 정보" 사양인 RFC 7807을 지원합니다.
다음은 이 지원에 대한 주요 추상화입니다.
ProblemDetail
- RFC 7807 문제 세부정보에 대한 표현입니다. 사양에 정의된 표준 필드와 비표준 필드에 대한 간단한 컨테이너입니다.
ErrorResponse
- HTTP 상태, 응답 헤더 및 본문을 포함한 HTTP 오류 응답 세부 정보를 RFC 7807 형식으로 노출하는 계약입니다. 이를 통해 예외가 HTTP 응답에 매핑되는 방법에 대한 세부 정보를 캡슐화하고 노출할 수 있습니다. 모든 Spring MVC 예외는 이를 구현합니다.
ErrorResponseException
- 다른 사람들이 편리한 기본 클래스로 사용할 수 있는 기본 ErrorResponse
구현입니다.
ResponseEntityExceptionHandler
- 모든 Spring MVC 예외 및 ErrorResponseException
을 처리하고 본문으로 오류 응답을 렌더링하는 @ControllerAdvice에 대한 편리한 기본 클래스입니다.
@ExceptionHandler
또는 @RequestMapping
메서드에서 ProblemDetail
또는 ErrorResponse
를 반환하여 RFC 7807 응답을 렌더링할 수 있습니다. 이는 다음과 같이 처리됩니다.
ProblemDetail
의 status
속성은 HTTP 상태를 결정합니다.
ProblemDetail
의 instance
속성은 아직 설정되지 않은 경우 현재 URL 경로에서 설정됩니다.
콘텐츠 협상의 경우 Jackson HttpMessageConverter
는 ProblemDetail
을 렌더링할 때 "application/json"보다 "application/problem+json"을 선호하고 호환되는 미디어 유형이 없으면 이를 대체합니다.
Spring WebFlux 예외 및 ErrorResponseException
에 대해 RFC 7807 응답을 활성화하려면 ResponseEntityExceptionHandler
를 확장하고 Spring 구성에서 @ControllerAdvice로 선언합니다. 핸들러에는 모든 내장 웹 예외를 포함하는 ErrorResponse
예외를 처리하는 @ExceptionHandler
메소드가 있습니다. 더 많은 예외 처리 메서드를 추가하고 보호된 메서드를 사용하여 모든 예외를 ProblemDetail
에 매핑할 수 있습니다.
두 가지 방법 중 하나로 비표준 필드를 사용하여 RFC 7807 응답을 확장할 수 있습니다.
첫째, ProblemDetail
의 "속성(properties)" Map
에 삽입합니다. Jackson 라이브러리를 사용할 때 Spring Framework는 이 "속성" Map
이 래핑 해제되어 응답에서 최상위 JSON 속성으로 렌더링되도록 보장하는 ProblemDetailJacksonMixin
을 등록하며 마찬가지로 역직렬화 중 알 수 없는 속성이 이 Map
에 삽입됩니다.
ProblemDetail
을 확장하여 전용 비표준 속성을 추가할 수도 있습니다. ProblemDetail
의 복사 생성자를 사용하면 기존 ProblemDetail
에서 하위 클래스를 쉽게 만들 수 있습니다. 이는 중앙에서 수행될 수 있습니다. 추가 비표준 필드가 있는 하위 클래스로 예외의 ProblemDetail
을 다시 생성하는 ResponseEntityExceptionHandler
와 같은 @ControllerAdvice
에서.
오류 응답 세부 사항을 사용자 정의하고 국제화하는 것은 일반적인 요구 사항입니다. 구현 세부사항이 공개되는 것을 피하기 위해 Spring MVC 예외에 대한 문제 세부사항을 사용자 정의하는 것도 좋은 습관입니다. 이 섹션에서는 이에 대한 지원을 설명합니다.
ErrorResponse
는 "type", "title" 및 "detail"에 대한 메시지 코드와 "detail" 필드에 대한 메시지 코드 인수를 노출합니다. ResponseEntityExceptionHandler
는 MessageSource를 통해 이를 해결하고 그에 따라 해당 ProblemDetail
필드를 업데이트합니다.
메시지 코드의 기본 전략은 다음 패턴을 따릅니다.
"type": problemDetail.type.[fully qualified exception class name]
"title": problemDetail.title.[fully qualified exception class name]
"detail": problemDetail.[fully qualified exception class name][suffix]
ErrorResponse
는 둘 이상의 메시지 코드를 노출할 수 있으며 일반적으로 기본 메시지 코드에 접미사를 추가합니다. 아래 표에는 Spring MVC 예외에 대한 메시지 코드와 인수가 나열되어 있습니다.
예외 | 메시지 코드 | 메시지 코드 인수 |
---|---|---|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) + ".parseError" |
|
|
(기본값) |
|
|
(기본값) + ".parseError" |
|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
매트릭스 변수 이름 |
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
|
|
(기본값) |
|
클라이언트 애플리케이션은 WebClient
를 사용할 때 WebClientResponseException
을 포착하거나 RestTemplate
을 사용할 때 RestClientResponseException
을 포착할 수 있으며 getResponseBodyAs
메소드를 사용하여 오류 응답 본문을 ProblemDetail
또는 ProblemDetail
의 하위 클래스와 같은 대상 유형으로 디코딩할 수 있습니다.