-
Spring WebFlux - Configspring 2019. 8. 29. 12:56
개요
Spring Webflux Java Configuration은 어노테이션 기반의 컨트롤러 방식이나 functional endpoints 방식에서 요청을 처리하기 위한 bean들을 정의하고 웹 관련 설정을 커스터마이징할 수 있는 api를 제공한다. @EnableWebflux 라는 어노테이션으로 웹플럭스 설정을 활성화할 수 있다.
@Configuration @EnableWebFlux public class WebConfig { }
WebFlux config API를 오버라이딩하기 위해서는 아래와 같이 WebFluxConfigurer을 구현한다.
@Configuration @EnableWebFlux public class WebConfig implements WebFluxConfigurer { // Implement configuration methods... }
Spring boot에서의 @EnableWebFlux 사용
스프링 부트에서는 @EnableWebFlux 어노테이션을 사용하지 않는 것이 기본이다. 스프링 부트의 웹플럭스 모듈은 부트의 특성답게 자동 설정을 하는 것이 기본인데, @EnableWebFlux 어노테이션을 사용하면 부트의 webflux 설정을 사용하지 않고, 웹플럭스에 대한 완전한 컨트롤을 가져오겠다는 의미이다. 부트의 웹플럭스를 사용하고 싶지 않을 때에만 @EnableWebFlux 어노테이션을 사용해야 한다.
@Configuration public class WebConfig { }
@Configuration public class WebConfig implements WebFluxConfigurer { // Implement configuration methods... }
Conversion, formatting
Number 타입과 Date 타입의 formatter가 기본적으로 내장되어 있다(ex. @NumberFormat, @DateTimeFormat). Joda-Time 라이브러리가 클래스패스에 존재한다면 Joda-Time에 대한 포맷팅도 기본으로 제공한다. 커스텀 formatter와 converter를 추가하고 싶으면 아래처럼 addFormatters()를 오버라이딩하면 된다.
@Configuration @EnableWebFlux public class WebConfig implements WebFluxConfigurer { @Override public void addFormatters(FormatterRegistry registry) { // ... } }
Validation
디폴트로, Hibernate Validator와 같은 validator 모듈이 클래스패스에 존재한다면 LocalValidatorFactoryBean이 글로벌 validator로 등록된다.
glboal Validator 인스턴스를 커스터마이징하고 싶으면 다음과 같이 getValidator() 메소드를 오버라이딩한다.
@Configuration @EnableWebFlux public class WebConfig implements WebFluxConfigurer { @Override public Validator getValidator(); { // ... } }
로컬 Validator를 등록하고 싶으면 다음과 같이 컨트롤러에서 등록한다.
@Controller public class MyController { @InitBinder protected void initBinder(WebDataBinder binder) { binder.addValidators(new FooValidator()); } }
Content Type Resolvers
디폴트로, 웹플럭스에서 요청에 대한 미디어 타입을 결정하는 방식은 request의 Accept 헤더를 체크하는 것이다. 그러나 다음과 같이 query parameter-based 방식을 사용할 수도 있다.
@Configuration @EnableWebFlux public class WebConfig implements WebFluxConfigurer { @Override public void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) { builder.parameterResolver().mediaType("json", MediaType.APPLICATION_JSON); } }
query parameter-based
'format=json' 형태의 request param을 보내서 미디어 타입을 결정하는 방식이다.
ex. GET /projects/spring-boot?format=json
MVC와의 차이
스프링 MVC는 디폴트로 suffix pattern matching 방식을 사용하여 미디어 타입을 결정한다.
ex. "GET /projects/spring-boot.json"
그러나, suffix patthern matching은 파일 확장자의 '.'과 path 내 '.'을 구분하기가 어렵고 모호해서 스프링 webflux에서는 suffix pattern matching을 아예 지원하지 않는다.
참고: https://github.com/spring-projects/spring-framework/issues/20198
스프링 부트 mvc에서는 웹플럭스와 마찬가지로 디폴트로 Accept 헤더를 보는 방식인데, suffix pattern maching을 사용하도록 설정하는 것이 가능하다.
spring.mvc.contentnegotiation.favor-path-extension=true spring.mvc.pathmatch.use-suffix-pattern=true
스프링 부트 mvc에서 query parameter-based 방식을 사용하려면 다음과 같이 설정한다.
spring.mvc.contentnegotiation.favor-parameter=true
HTTP message codecs
HTTP 메세지 코덱도 다음과 같이 커스터마이징할 수 있다.
@Configuration @EnableWebFlux public class WebConfig implements WebFluxConfigurer { @Override public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { configurer.defaultCodecs().jackson2JsonEncoder(encoder); configurer.defaultCodecs().jackson2JsonDecoder(decoder); } }
ServerCodecConfigurer는 다음의 모듈이 클래스패스에 존재한다면 자동으로 코덱을 등록해준다.
- jackson-datatype-jdk7: Support for Java 7 types like java.nio.file.Path.
-
jackson-datatype-joda: Support for Joda-Time types.
-
jackson-datatype-jsr310: Support for Java 8 Date and Time API types.
-
jackson-datatype-jdk8: Support for other Java 8 types, such as Optional.
View Resolvers
view resolver도 설정할 수 있다. 다음은 FreeMarker를 사용하는 예제이다.
@Configuration @EnableWebFlux public class WebConfig implements WebFluxConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.freeMarker(); } // Configure Freemarker... @Bean public FreeMarkerConfigurer freeMarkerConfigurer() { FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); configurer.setTemplateLoaderPath("classpath:/templates"); return configurer; } }
Static Resources
static resource들을 편하게 uri mapping을 해주기 위한 설정도 가능하다. 다음 예제는 '/resources'로 시작하는 request uri를 '/public'과 'classpath:/static/' 의 상대 경로로 리소스를 맵핑해준다.
@Configuration @EnableWebFlux public class WebConfig implements WebFluxConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**") .addResourceLocations("/public", "classpath:/static/") .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS)); } }
Path Matching
다음과 같이 uri path matching에 대한 설정도 커스터마이징할 수 있다.
@Configuration @EnableWebFlux public class WebConfig implements WebFluxConfigurer { @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer .setUseCaseSensitiveMatch(true) .setUseTrailingSlashMatch(false) .addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController.class)); } }
Advanced Configuration mode
@EnableWebFlux 어노테이션은 DelegatingWebFluxConfiguration을 import한다.
DelegatingWebFluxConfiguration
- 스프링 웹플럭스 기본 설정을 잡아준다.
- WebFluxConfigurer를 구현하고 있는 설정을 찾아서 잡아준다.
웹플럭스 설정을 advanced하게 하려면 @EnableWebFlux 어노테이션을 떼고 직접 DelegatingWebFluxConfiguration을 상속받아도 된다.
@Configuration public class WebConfig extends DelegatingWebFluxConfiguration { // ... }
이렇게 하면 WebFluxConfigurer을 구현할 때 할 수 있는 기능과 더불어 base bean 선언에도 관여할 수 있다.
'spring' 카테고리의 다른 글
Spring Webflux Cache (1) 2019.10.28 Reactor - Reactive Streams 생명 주기 (0) 2019.10.21 Spring Webflux - CORS (0) 2019.07.31 Spring Webflux - Functional Endpoints (0) 2019.07.25 Spring Webflux - DispatcherHandler (0) 2019.07.18