In some scenarios, we need to get HandlerMethod ahead of org.springframework.web.reactive.DispatcherHandler, such as an implement of authentication by WebFilter
public class AuthFilter implements WebFilter, Ordered {
@Autowired
private RequestMappingHandlerMapping handlerMapping;
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return handlerMapping.getHandler(exchange).switchIfEmpty(chain.filter(exchange))
.flatMap(handler -> {
if (handler instanceof HandlerMethod) {
HandlerMethod methodHandle = (HandlerMethod) handler;
CheckPermission permission = methodHandle.getMethodAnnotation(CheckPermission.class);
if (Objects.isNull(permission)) {
permission = AnnotationUtils.findAnnotation(methodHandle.getBeanType(), CheckPermission.class);
}
if (Objects.nonNull(permission)) {
// TODO do something..
}
}
return chain.filter(exchange);
}
);
}
}
HandlerMethod is necessary but there is no alternative way to get it withon WebFilter, which limited the capabilities of WebFilter. so, we need call getHandler, however this may lead to repeated call of lookupHandlerMethod as issue:
https://github.com/spring-projects/spring-framework/blob/00da70e26b9cb5ece2a9499e7c1b449e856b4aea/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java#L293
To avoid duplicate search for HandlerMethod in mapping.getHandler , I suggest implementing a improved getHandlerInternal, in which HandlerMethod would be searched in attributes at first.
Object handlerMethod = exchange.getAttributes().get(BEST_MATCHING_HANDLER_ATTRIBUTE);
if (handlerMethod instanceof HandlerMethod) {
return Mono.just((HandlerMethod) handlerMethod);
}
related issue:https://github.com/spring-projects/spring-framework/issues/29591
Comment From: rstoyanchev
WebFilters are called first and are not meant to know what the DispatcherHandler will do or what controller method it will choose. You can of course call a HandlerMapping from a WebFilter, but that is not something that we recommend or support.