Spring Web Reactive | 1. Spring WebFlux | 1.3. DispatcherHandler
Spring WebFlux은 Spring MVC와 마찬가지로 프런트 컨트롤러 패턴을 중심으로 설계되어 있으며, 중앙의 WebHandler
인 DispatcherHandler
가 요청 처리의 공유 알고리즘을 제공하고, 실제 작업은 구성 가능한 위임(delegate) 컨포넌트에 의해 실행된다 . 이 모델은 유연하고 다양한 워크 플로우를 지원한다.
DispatcherHandler
는 Spring 설정에서 필요한 위임 컨포넌트를 검색한다. 그러고, Spring Bean 자체되도록 설계되어 실행되는 컨텍스트에 액세스하기 위해 ApplicationContextAware
를 구현한다. DispatcherHandler
이 webHandler
이라는 Bean 이름으로 선언되는 경우 WebHandler
API에 따라 요청 처리 체인을 모와서 WebHttpHandlerBuilder
에 의해 검색된다.
WebFlux 응용 프로그램의 Spring 설정은 일반적으로 다음이 포함된다.
DispatcherHandler
, Bean 이름은webHandler
WebFilter
그리고WebExceptionHandler
BeanDispatcherHandler
특수 Bean- 기타
다음의 예제에서 알 수 있듯이, 처리는 체인을 구축하기 위해 WebHttpHandlerBuilder
에 주어진다.
Java
ApplicationContext context = ...
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context).build();
Kotlin
val context: ApplicationContext = ...
val handler = WebHttpHandlerBuilder.applicationContext(context).build()
결과 HttpHandler
는 서버 어댑터에서 함께 사용할 준비가 되어 있다.
1.3.1. 특별한 Bean 유형(Special Bean Types)
DispatcherHandler
는 요청을 처리하고 적절한 응답을 렌더링하는데 특별한 Bean에 위임한다. “특별한 Bean"이란, WebFlux 프레임워크의 요소를 구현하는 Spring 관리 Object
인스턴스를 의미한다. 기본적으로 내장(built-in)되어 있지만, 속성을 정의하거나 확장하거나 교체 할 수 있다.
다음 표는 DispatcherHandler
의해 검지된 특별한 Bean을 보여준다. 낮은 레벨에서 감지된 그밖에 Bean도 일부 있다는 점에 유의해라(Web 핸들러 API의 특별한 Bean 유형 참조).
Bean 유형 | 설명 |
---|---|
HandlerMapping |
요청을 핸들러에 매핑한다. 매핑은 몇 가지 조건을 기반으로 하며, 그 자세한 내용은 HandlerMapping 구현에 따라 달라진다. 주석이 선언된 컨트롤러, 간단한 URL 패턴 매핑 등. 주요 HandlerMapping 구현은 @RequestMapping 어노테이션이 선언된 메서드의 RequestMappingHandlerMapping , 함수 엔드 포인트 루트의 RouterFunctionMapping 및 URI 경로 패턴과 WebHandler 인스턴스의 명시적인 등록 SimpleUrlHandlerMapping 이다. |
HandlerAdapter |
핸들러가 실제로 호출되는 방법에 관계없이, DispatcherHandler 가 요청에 매핑 된 핸들러를 호출하는데 도움이 된다. 예: 어노테이션이 선언된 컨트롤러를 호출하려면 어노테이션에 대한 리졸버가 있어야 하는데, HandlerAdapter 의 주요 목적은 그러 구체적인 부분까지는 DispatcherHandler 에서 관여할 필요 없이 처리를 분리하는 것이다. |
HandlerResultHandler |
핸들러 호출의 결과를 처리하고 응답을 확인한다. 결과 핸들링를 참조해라. |
1.3.2. WebFlux 구성
응용 프로그램은 요청을 처리하는 데 필요한 인프라 Bean(Web 핸들러 API 및 DispatcherHandler
에 목록화되어 있다)를 선언 할 수 있다. 그러나 대부분의 경우 WebFlux 구성이 최적의 출밤점이다. 필요한 Bean을 선언하고 그것을 정의하기 위한 높은 레벨의 구성 콜백 API를 제공한다.
Spring Boot는 WebFlux 구성에 따라 Spring WebFlux를 구성하고, 더욱 편리한 옵션을 제공한다.
1.3.3. 처리
DispatcherHandler
는 요청을 다음과 같이 처리한다.
- 각
HandlerMapping
일치하는 핸드러를 찾을 수 있도록 도와주고, 처음 메칭된 핸드러가 사용된다. - 핸들러가 찾으면 적절한
HandlerAdapter
를 통해 실행되며, 실행에서 반환 값을HandlerResult
로 전달한다. HandlerResult
는 적절한HandlerResultHandler
에 전달된 응답을 직접 만들거나, 뷰를 사용하여 렌더링 처리를 완료한다.
1.3.4. 결과 처리(Result Handling)
HandlerAdapter
를 통해 핸들러의 호출의 반환 값은 추가 컨텍스트와 함께 HandlerResult로 싸여 그 지원을 요구하는 첫번째 HandlerResultHandler
에 전달된다. 다음 표는 사용 가능한 HandlerResultHandler
구현을 보여준다. 이들은 모두 WebFlux 구성에 선언되어 있다.
결과 핸들러 유형 | 반환 값 | 기본 순서 |
---|---|---|
ResponseEntityResultHandler |
ResponseEntity , 일반적으로 @Controller 인스턴스에서 사용. |
0 |
ServerResponseResultHandler |
ServerResponse 일반적으로 함수 엔드 포인트에서 사용. |
0 |
ResponseBodyResultHandler |
@ResponseBody 메소드 또는 @RestController 클래스에서 반환 값을 처리한다. |
100 |
ViewResolutionResultHandler |
CharSequence , View , Model, Map , Rendering이나 다른 Object 는 모델 속성으로 처리된다. 뷰 리졸버를 참조해라. |
Integer.MAX_VALUE |
1.3.5. 예외(Exceptions)
HandlerAdapter
에서 반환된 HandlerResult
는 핸들러 고유의 메커니즘을 기반으로 에러 핸들링 함수를 제공한다. 이 에러 핸들링 함수는 다음의 경우에 호출된다:
- 핸들러 (예를 들어,
@Controller
) 호출 실패 HandlerResultHandler
를 통한 핸들러 반환 처리실패
에러 함수는 핸들러에서 반환되는 리액티브 유형의 데이터 항목을 생성하기 전에 에러 신호가 발생하면, 응답(예를 들어, 에러 상태:status)를 변경할 수 있다.
그래서 @Controller
클래스의 @ExceptionHandler
메서드가 지원된다. 반면 Spring MVC에서의 동일한 지원은 HandlerExceptionResolver
을 기반으로 한다. 이는 그리 중요하지 않다. 다만, WebFlux는 @ControllerAdvice
을 사용하여 핸들러가 선택되기 전에 발생하는 예외를 처리 할 수 없음에 주의해라.
“어노테이션이 선언된 컨트롤러"섹션의 예외 관리 또는 WebHandler API 섹션의 예외를 참조해라.
1.3.6. 뷰 리솔루션(View Resolution)
뷰 리솔루션(View Resolution)를 사용하면 특정 뷰 기술에 얽매이지 않고, HTML 템플릿과 모델을 사용하여 브라우저에 렌더링 할 수 있다. Spring WebFlux는 ViewResolver
인스턴스를 사용하여 문자열(논리적 뷰 이름을 나타내는)를 View
인스턴스에 매핑하는 전용 HandlerResultHandler
를 통해 뷰 리솔루션이 지원되고 있다. 다음은 View
를 사용하여 응답을 렌더링한다.
핸들링(Handling)
ViewResolutionResultHandler
에 전달되는 HandlerResult
는 핸들러로부터의 반환 값과 요청 처리 중에 추가 된 속성을 포함하는 모델이 포함되어 있다. 반환 값은 다음 중 하나로 처리된다.
String
,CharSequence
: 구성된ViewResolver
구현의 목록을 통해View
에서 만들어지는 논리적 뷰 이름.void
: 요청 경로에 따라 앞뒤에 슬래시를 제외한 디폴트 뷰 이름을 선택하고,View
에서 해결한다. 뷰 이름이 지정되지 않은 경우(모델 속성이 반환된 경우 등) 또는 비동기 반환 값 (예를 들어, 빈어 있는Mono
가 완료된 경우)에서도 동일하게 처리한다.- Rendering : 뷰 리솔루션 시나리오 API. IDE 자동 완성의 옵션을 찾아보자.
Model
,Map
: 요청의 모델에 추가된 추가 모델 속성.- 그 외 : 다른 반환 값(
BeanUtils#isSimpleProperty
에 의해 결정되는 단순한 유형 제외)는 모델에 추가되는 모델 속성으로 처리된다. 핸들러 메소드@ModelAttribute
어노테이션이 존재하지 않는 속성 이름은 Conventions을 사용하여 클래스 이름으로부터 얻어진다.
모델은 비동기 리액티브 타입을 포함 할 수 있다(예를 들어, Reactor 또는 RxJava에서). AbstractView
는 이러한 모델 특성을 렌더링 전에 구체적인 값으로 값으로 리졸빙하고 그 모델을 업데이트한다. 단일 값의 리액티브 타입은 단일 값 또는 값 없음(비어있는 경우)로 확인된 여러 값의 리액티브 유형(예를 들어, Flux<T>
)는 수집 된 List<T>
에 리졸빙된다.
뷰 리졸버 조치를 구성하려면 ViewResolutionResultHandler
Bean을 Spring 설정에 추가 하면 된다. WebFlux 구성은 뷰 리졸버 우퍼 전용 구성 API를 제공한다.
Spring WebFlux와 통합 된 뷰 기술에 대한 자세한 내용은 뷰 기술을 참조해라.
리디렉션(Redirecting)
뷰 이름의 특별한 redirect:
접두사(prefix)를 붙이면 리디렉션 할 수 있다. UrlBasedViewResolver
(및 서브 클래스)는이를 리디렉션이 필요한 명령으로 인식한다. 뷰 이름의 나머지는 리디렉션 URL이다.
최종 효과는 컨트롤러가 RedirectView
또는 Rendering.redirectTo("abc").build()
를 반환한 경우와 동일하지만 컨트롤러 자체가 논리적 뷰 이름의 관점에서 작동 할 수 있게 되어 있다. redirect:/some/resource
와 같은 뷰 이름은 현재 응용 프로그램에 관련이 있지만, redirect:https://example.com/arbitrary/path
와 같이 하면 절대 경로 URL로 리디렉션된다.
콘텐츠 협상(Content Negotiation)
ViewResolutionResultHandler
콘텐츠 협상을 지원하고 있다. 요청 미디어 유형과 선택한 각 View
에서 지원되는 미디어 유형을 비교한다. 요청한 미디어 타입을 지원하는 최초의 View
가 사용된다.
JSON 또는 XML 등의 미디어 타입을 지원하기 위해, Spring WebFlux는 HttpMessageWriterView
을 제공한다. 이는 HttpMessageWriter
을 통해 렌더링하는 특별한 View
이다. 일반적으로 이들은 WebFlux 설정을 통해 기본 뷰로 설정한다. 요청한 미디어 타입에 일치하는 경우 기본 뷰가 항상 선택되어 사용된다.