How to do post-matching filter in webflux?

可紊 提交于 2020-01-24 22:00:08

问题


As we know, in jersey we have pre-matching filter and post-matching filter.

I'm wondering how can I get similar behavior with WebFilter in webflux application.

It seems the WebFilter is sort of like a pre-matching filter which will be executed for sure, no matter a resource in @RestController found or not.

My filter like this (copied from metrics filter in spring actuator):

@Component
@Order(100)
public class AppFilter1 implements WebFilter {

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {

    return chain.filter(exchange).compose((call) -> filter(exchange, call));
}

private Publisher<Void> filter(ServerWebExchange exchange, Mono<Void> call) {

    System.out.println("Start AppFilter1 in thread:" + Thread.currentThread().getId() + "..........");
    ServerHttpResponse response = exchange.getResponse();
    return call.doOnSuccess((done) -> success(exchange)).doOnError((cause) -> {
        if (response.isCommitted()) {
            error(exchange, cause);
        } else {
            response.beforeCommit(() -> {
                error(exchange, cause);
                return Mono.empty();
            });
        }
    });
}

private void success(ServerWebExchange exchange) {

    System.out.println("End AppFilter1 in thread:" + Thread.currentThread().getId() + "..............");

}

private void error(ServerWebExchange exchange, Throwable cause) {
    System.out.println("End AppFilter1 with Error in thread:" + Thread.currentThread().getId() + "...............");
}

}

Add my controller is like:

@RestController
public class ExampleController {

@GetMapping("/example")
public String example() {
    System.out.println("Example in thread:" + Thread.currentThread().getId());
    return "Example";
}
}

What I can see is the filter will be executed for sure no matter I access /example or /notexist

Actually I'd like my filter to do post-matching, only executed for /example.

To be more specific, I'd like to see console output for /example:

Start AppFilter1 in thread:....
Example in thread:.....
End AppFilter1 in thread:....

and for a not matched resource like /notexist, there's no console output at all.

Thanks

Leon


回答1:


The Spring WebFlux WebFilter class does not operate at the same level as the pre/post matching filters in Jersey. It's actually closer to a Servlet filter.

The WebFilter has no clue about what is handling the request - it could be a Controller, a handler serving static resources, or any other custom handler.

Since you're at the HTTP level here, you can just check for the request path and whether the response status is not "404 Not Found".

Since your question does not provide much background about what you're trying to achieve here (business logic? authentication? logging? tracing? any operation that involves I/O?), I can't really say more about the choice of Reactor operator.

If you'd like a filter that only operates on Resources (as in Jersey Resources), then WebFilter is not the right choice as it's operating at a lower level (all HTTP exchanges). I don't think there's infrastructure for that in Spring Framework. Feel free to open an enhancement request in Spring Framework (this time providing enough details about your use case).



来源:https://stackoverflow.com/questions/50559991/how-to-do-post-matching-filter-in-webflux

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!