오해가 없도록 어떤 text를 인용했는지 원문을 첨부합니다.🤗
handler함수는 사용자의 요청을 처리해주는 함수이다. 이런 Handler함수들을 routing function builder에서 before
,after
, filter
메서드를 이용해서 필터시킬 수 있다. Annotation기반 프로그래밍에서 @ControllerAdvice, ServletFilter 등으로 했던 것을 동일하게 할 수 있다. 이 필터들은 자신에게 오는 모든 request들을 필터하기 때문에, nested routes안에서 필터를 걸면 그 바깥의 route들은 영향을 받지 않는다.
RouterFunction<ServerResponse> route = route()
.path("/person", b1 -> b1
.nest(accept(APPLICATION_JSON), b2 -> b2
.GET("/{id}", handler::getPerson)
.GET(handler::listPeople)
.before(request -> ServerRequest.from(request)
.header("X-RequestHeader", "Value")
.build()))
.POST("/person", handler::createPerson))
.after((request, response) -> logResponse(response))
.build();
중간에 before이 나오는데, /person경로에 대한 nested route이다. 이 before은 이 nested안에 있는 route들에만 적용되기 때문에
.GET("/{id}", handler::getPerson)
.GET(handler::listPeople)
이 두개에만 적용이 된다. 헤더를 더해주는 역할을 하고 있다. 아래 있는 after는 눈치를 챘겠지만
.after((request, response) -> logResponse(response))
모든 route (nested안에 있는 GET 들도)에 대해서 log를 남기는 필터이다.
filter
메서드는 HandlerFilterFunction
을 인자로 받는다. HandlerFilterFunction
은 ServerRequest와 HandlerFunction을 인자로 받아서 ServerResponse를 return해준다. 만약 여러개의 필터가 있다면 HandlerFunction은 다음 필터를 가리키고, 아니라면 route되는 handler를 가리키게 된다. 이를테면 보안 필터같은 것을 걸어놓을 수 있다. 아래는 특정 path가 allow되는지 체크하는 필터이다.
SecurityManager securityManager = ...
RouterFunction<ServerResponse> route = route()
.path("/person", b1 -> b1
.nest(accept(APPLICATION_JSON), b2 -> b2
.GET("/{id}", handler::getPerson)
.GET(handler::listPeople))
.POST("/person", handler::createPerson))
.filter((request, next) -> {
if (securityManager.allowAccessTo(request.path())) {
return next.handle(request);
}
else {
return ServerResponse.status(UNAUTHORIZED).build();
}
})
.build();
next.handle()을 부르는 것이 optional하다. 즉 필터의 조건에 맞지 않으면 다음 필터나 handler로 안 넘어가게 한다. builder를 사용하지 않아도 router function이 존재하면 RouterFunction.filter(HandlerFilterFunction)
을 해서 필터를 적용할 수 있다.
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
}
일단 EnableWebFlux를 사용해서 Spring WebFlux infrastructure beans를 사용할 수 있다.
또, WebFluxConfigurer
interface를 사용해서 여러가지 설정을 추가할 수 있다.
가장 익숙한 설정은 ViewResolver가 있을 것이다
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
// ...
}
}
@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;
}
}
아래와 같이 ViewResolverRegistry
는 여러 view에 대한 shortcut을 가지고 있어서 손쉽게 설정을 만들 수 있다.