ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring WebFlux - Config
    spring 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...
    
    }

    참고: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-webflux-auto-configuration

     

    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는 다음의 모듈이 클래스패스에 존재한다면 자동으로 코덱을 등록해준다.

     

     

    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

    댓글

Designed by Tistory.