问题
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