Spring Framework
Spring Webflux - Exception Handle
흥부가귀막혀
2022. 3. 14. 13:09
Exception Handle
Functional Level
- Handler 에서 함수 수행시 onErrorReturn, onErrorResume 을 정의하여 에러 핸들링 처리를 할 수 있다.
onErrorReturn
public Mono<ServerResponse> handleRequest(ServerRequest request) {
return sayHello(request)
.onErrorReturn("Request Fail! But Return Success Status!")
.flatMap(s -> ServerResponse.ok()
.contentType(MediaType.TEXT_PLAIN)
.bodyValue(s));
}
onErrorResume
public Mono<ServerResponse> handleRequest(ServerRequest request) {
return sayHello(request)
.flatMap(s -> ServerResponse.ok()
.contentType(MediaType.TEXT_PLAIN)
.bodyValue(s))
.onErrorResume(e -> sayHelloFallback()
.flatMap(s -> ServerResponse.ok()
.contentType(MediaType.TEXT_PLAIN)
.bodyValue(s)
)
);
}
Controller Level
- MVC 와 동일하게 @ExceptionHandler 어노테이션을 통해 error handling 이 가능하다.
@Controller public class SimpleController {
// ...
@ExceptionHandler
public ResponseEntity<String> handle(IOException ex) {
// ...
}
}
⚠️ Spring WebFlux 에서 @ExceptionHandler 를 사용할 경우 request body나 @ModelAttribute에 관련된 매개변수와 반환 값은 사용 불가능하다.
Global Level
- WebExceptionHandler 를 정의하여 Bean 으로 등록하면 모든 요청에 대한 Exception Handling 이 가능하다.
- Spring WebFlux 에서는 아래의 WebExceptionHandler 구현체를 제공한다.
- ResponseStatusExceptionHandler : ResponseStatusException 유형에 대한 예외 처리
- WebFluxResponseStatusExceptionHandler : @ResponseStatus 가 선언된 경우에 대한 예외처리. ResponseStatusExceptionHandler의 확장
- DefaultErrorWebExceptionHandler : Exception Handle 에 대한 기본적인 기능 제공
- 직접 WebExceptionHandler 를 구현하고 싶다면 AbstractErrorWebExceptionHandler 나 DefaultErrorWebExceptionHandler 를 상속받아 커스터마이징 하여 Bean 으로 등록한다.
@Component
@Order(-2)
public class GlobalErrorWebExceptionHandler extends
AbstractErrorWebExceptionHandler {
// constructors
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(
ErrorAttributes errorAttributes) {
return RouterFunctions.route(
RequestPredicates.all(), this::renderErrorResponse);
}
private Mono<ServerResponse> renderErrorResponse(
ServerRequest request) {
Map<String, Object> errorPropertiesMap = getErrorAttributes(request,
ErrorAttributeOptions.defaults());
return ServerResponse.status(HttpStatus.BAD_REQUEST)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(errorPropertiesMap));
}
}
⚠️ Spring WebFlux 에서는 DefaultErrorWebExceptionHandler 가 @Order(-1) 로 등록이 되기 때문에 DefaultErrorWebExceptionHandler 보다 먼저 error handling 을 하려면 @Order(-2) 를 정의해야한다.
- 에러 응답에 대한 정의만 필요하다면, ErrorAttributes 혹은 DefaultErrorAttributes 를 상속받은 구현체를 Bean 으로 정의하는 방법도 있다.
@Component
public class GlobalErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(ServerRequest request,
ErrorAttributeOptions options) {
Map<String, Object> map = super.getErrorAttributes(
request, options);
map.put("status", HttpStatus.BAD_REQUEST);
map.put("message", "username is required");
return map;
}
}