From 0785256b2f805a292b4b6c81c7b574d9ba57300c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Wed, 22 Nov 2023 16:00:39 +0100 Subject: [PATCH] Match HandlerMapping lookup to bean signature This commit makes sure to initialize any HandlerMapping defined in the context when searching for resource handlers. Previously, the detection algorithm was looking up for `SimpleUrlHandlerMapping` while the declared target type in WebMvcConfigurationSupport is HandlerMapping. If the application uses lazy initialization, the lookup algorithm would not force that bean to be initialized. Closes gh-25488 --- .../resource/ResourceUrlProvider.java | 23 +++++++--------- .../servlet/resource/ResourceUrlProvider.java | 26 ++++++++----------- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java index 765e021fc6..ae2a9909dc 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java @@ -16,7 +16,6 @@ package org.springframework.web.reactive.resource; -import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; @@ -31,11 +30,11 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.http.server.PathContainer; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.lang.Nullable; -import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping; +import org.springframework.web.reactive.HandlerMapping; +import org.springframework.web.reactive.handler.AbstractUrlHandlerMapping; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.pattern.PathPattern; import org.springframework.web.util.pattern.PathPatternParser; @@ -100,16 +99,14 @@ public class ResourceUrlProvider implements ApplicationListener beans = context.getBeansOfType(SimpleUrlHandlerMapping.class); - List mappings = new ArrayList<>(beans.values()); - AnnotationAwareOrderComparator.sort(mappings); - - mappings.forEach(mapping -> - mapping.getHandlerMap().forEach((pattern, handler) -> { - if (handler instanceof ResourceWebHandler resourceHandler) { - this.handlerMap.put(pattern, resourceHandler); - } - })); + context.getBeanProvider(HandlerMapping.class).orderedStream() + .filter(AbstractUrlHandlerMapping.class::isInstance) + .map(AbstractUrlHandlerMapping.class::cast) + .forEach(mapping -> mapping.getHandlerMap().forEach((pattern, handler) -> { + if (handler instanceof ResourceWebHandler resourceHandler) { + this.handlerMap.put(pattern, resourceHandler); + } + })); if (this.handlerMap.isEmpty()) { logger.trace("No resource handling mappings found"); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java index afd47b83b3..62b7fd43a6 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,12 +31,12 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.lang.Nullable; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import org.springframework.util.StringUtils; -import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; +import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping; import org.springframework.web.util.UrlPathHelper; /** @@ -147,18 +147,14 @@ public class ResourceUrlProvider implements ApplicationListener beans = appContext.getBeansOfType(SimpleUrlHandlerMapping.class); - List mappings = new ArrayList<>(beans.values()); - AnnotationAwareOrderComparator.sort(mappings); - - for (SimpleUrlHandlerMapping mapping : mappings) { - for (String pattern : mapping.getHandlerMap().keySet()) { - Object handler = mapping.getHandlerMap().get(pattern); - if (handler instanceof ResourceHttpRequestHandler resourceHandler) { - this.handlerMap.put(pattern, resourceHandler); - } - } - } + appContext.getBeanProvider(HandlerMapping.class).orderedStream() + .filter(AbstractUrlHandlerMapping.class::isInstance) + .map(AbstractUrlHandlerMapping.class::cast) + .forEach(mapping -> mapping.getHandlerMap().forEach((pattern, handler) -> { + if (handler instanceof ResourceHttpRequestHandler resourceHandler) { + this.handlerMap.put(pattern, resourceHandler); + } + })); if (this.handlerMap.isEmpty()) { logger.trace("No resource handling mappings found");