원본 글: https://www.baeldung.com/spring-webflux-filters
Spring Webflux Filters | Baeldung
Learn how to modify requests and responses using Spring Webflux Filters
www.baeldung.com
엔드포인트를 수정하지 않고 request나 response를 수정하기 위해 filter는 웹 애플리케이션에서 많이 사용되고 있습니다.
이 가이드에서는 웹 플럭스를 이용해서 이를 구현하는 방법을 설명합니다.
1. Maven Dependency
먼저, WebFlux에대한 의존성을 추가합니다.
//gradle
implementation 'org.springframework.boot:spring-boot-starter-webflux'
//maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
2. Endpoints
어노테이션기반, 함수기반으로 만들어진 연습용 엔드포인트를 만듭니다.
어노테이션 기반 컨트롤러입니다.
@RestController
public class ExampleController {
@GetMapping("/users/{name}")
public Mono<String> getUser(@PathVariable String name) {
return Mono.just(name);
}
}
다음은 함수기반 엔드포인트를 위한 핸들러를 만듭니다.
@Component
public class ExampleHandler {
public Mono<ServerResponse> getName(ServerRequest request) {
Mono<String> name = Mono.just(request.pathVariable("name"));
return ServerResponse.ok().body(name, String.class);
}
}
라우터를 통해 두 정보를 연결시켜줍니다.
public class ExampleRouter {
@Bean
public RouterFunction<ServerResponse> route(ExampleHandler exampleHandler) {
return RouterFunctions
.route(GET("/players/{name}"), exampleHandler::getName)
.filter(new ExampleHandlerFilterFunction());
}
}
여기서 ExampleHandlerFilterFunction은 뒤에서 살펴보도록 합니다.
3. Types of WebFlux Filters
웹 플럭스 프레임워크는 WebFilter와 HandlerFilterFunctions라는 2가지 종류의 필터를 제공합니다.
WebFilter는 모든 엔드포인트에 대해 동작하고, HandlerFilterFunction은 Router기반(RouterFunction)에서만 동작합니다.
3.1 WebFilter
WebFilter를 통해서 response에 새로운 헤더를 추가하는 예제를 작성합니다. 모든 엔드포인트에 대해서 동작합니다.
@Component
public class ExampleWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
exchange.getResponse().getHeaders().add("web-filter", "web-filter-test");
return chain.filter(exchange);
}
}
3.2 HandlerFilterFunction
이 필터에서는 요청 파라미터(name)값이 "test"라면 FORBIDDEN Http 상태를 반환하는 로직을 추가합니다.
//제네릭 첫번째: HandlerFunction 반환타입, 두번째: filter함수가 반환하는 타입
public class ExampleHandlerFilterFunction implements HandlerFilterFunction<ServerResponse, ServerResponse> {
@Override
public Mono<ServerResponse> filter(ServerRequest request, HandlerFunction<ServerResponse> next) {
if(request.pathVariable("name").equalsIgnoreCase("test")) {
return ServerResponse.status(HttpStatus.FORBIDDEN).build();
}
return next.handle(request);
}
}
4. Testing
WebTestClient를 통해서 필터기능을 테스트할 수 있습니다. 먼저 어노테이션 기반 엔드포인트 테스트를 진행하겠습니다.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
public class ExampleWebFilterTest {
@Autowired
private WebTestClient webTestClient;
@Test
public void whenUserNameIsMinseok_thenWebFilterIsApplied() {
EntityExchangeResult<String> response = webTestClient.get()
.uri("/users/minseok")
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.returnResult();
Assertions.assertEquals("minseok", response.getResponseBody());
Assertions.assertEquals("web-filter-test", response.getResponseHeaders().getFirst("web-filter"));
}
@Test
public void whenUserNameIsTest_thenHandlerFilterFunctionIsNotApplied() {
webTestClient.get().uri("/users/test")
.exchange()
.expectStatus().isOk();
}
}
다음은 라우트기반 엔드포인트 테스트입니다.
@Test
public void whenPlayerNameIsMinseok_thenWebFilterIsApplied() {
EntityExchangeResult<String> result = webTestClient.get()
.uri("/players/minseok")
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.returnResult();
Assertions.assertEquals("minseok", result.getResponseBody());
Assertions.assertEquals("web-filter-test",
result.getResponseHeaders().getFirst("web-filter"));
}
@Test
public void whenPlayerNameIsTest_thenHandlerFilterFunctionIsApplied() {
webTestClient.get().uri("/players/test")
.exchange()
.expectStatus().isForbidden();
}
실행해보면 의도한대로 잘 동작함을 알 수 있습니다.
5. 결론
몇가지 코드를 확인해보며 WebFlux에서 필터가 어떤 종류가 있는지, 어떻게 동작하는지 확인해보았습니다.
baeldung-test/Spring-reactive/Spring-Webflux-Filter/src/test/java/com/my/springwebfluxfilter/ExampleWebFilterTest.java at main
baeldung-test. Contribute to kkminseok/baeldung-test development by creating an account on GitHub.
github.com
내 생각
가이드 자체가 친절한 편은 아니라(static import가 많아서) 몇개의 코드를 추가하였습니다.
이 글을 통해서 라우트 방식, Controller를 이용한 일반적인 방식을 학습하였습니다.
특정 요청에 대한 필터는 라우트방식을 이용해서 하는편이 나을 것 같습니다.
'Baeldung번역&공부 > Spring-Reactive' 카테고리의 다른 글
SpringMVC Async와 SpringWebFlux차이(Spring MVC Async vs Spring WebFlux) (0) | 2025.02.26 |
---|---|
WbFlux에서 404Status를 반환하는방법(How to Return 404 with Spring WebFlux) (0) | 2025.02.25 |
Webflux에서 Error를 다루는방법(Handling Errors in Spring WebFlux) (0) | 2025.02.24 |
Spring WebFlux - 정적 컨텐츠들 (0) | 2025.02.18 |
Spring WebFlux 가이드(Guide to Spring WebFlux) (0) | 2025.02.17 |