diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java index be7e3e3dda4e..96218e0fe3d9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.web.reactive; import java.time.Duration; +import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -163,14 +164,14 @@ public static class WebFluxConfig implements WebFluxConfigurer { private final ObjectProvider codecCustomizers; - private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer; + private final ObjectProvider resourceHandlerRegistrationCustomizers; private final ObjectProvider viewResolvers; public WebFluxConfig(Environment environment, WebProperties webProperties, WebFluxProperties webFluxProperties, ListableBeanFactory beanFactory, ObjectProvider resolvers, ObjectProvider codecCustomizers, - ObjectProvider resourceHandlerRegistrationCustomizer, + ObjectProvider resourceHandlerRegistrationCustomizers, ObjectProvider viewResolvers) { this.environment = environment; this.resourceProperties = webProperties.getResources(); @@ -178,7 +179,7 @@ public WebFluxConfig(Environment environment, WebProperties webProperties, WebFl this.beanFactory = beanFactory; this.argumentResolvers = resolvers; this.codecCustomizers = codecCustomizers; - this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizer.getIfAvailable(); + this.resourceHandlerRegistrationCustomizers = resourceHandlerRegistrationCustomizers; this.viewResolvers = viewResolvers; } @@ -210,19 +211,22 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) { logger.debug("Default resource handling disabled"); return; } + List resourceHandlerRegistrationCustomizers = this.resourceHandlerRegistrationCustomizers + .orderedStream() + .toList(); String webjarsPathPattern = this.webFluxProperties.getWebjarsPathPattern(); if (!registry.hasMappingForPattern(webjarsPathPattern)) { ResourceHandlerRegistration registration = registry.addResourceHandler(webjarsPathPattern) .addResourceLocations("classpath:/META-INF/resources/webjars/"); configureResourceCaching(registration); - customizeResourceHandlerRegistration(registration); + resourceHandlerRegistrationCustomizers.forEach((customizer) -> customizer.customize(registration)); } String staticPathPattern = this.webFluxProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { ResourceHandlerRegistration registration = registry.addResourceHandler(staticPathPattern) .addResourceLocations(this.resourceProperties.getStaticLocations()); configureResourceCaching(registration); - customizeResourceHandlerRegistration(registration); + resourceHandlerRegistrationCustomizers.forEach((customizer) -> customizer.customize(registration)); } } @@ -247,12 +251,6 @@ public void addFormatters(FormatterRegistry registry) { ApplicationConversionService.addBeans(registry, this.beanFactory); } - private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) { - if (this.resourceHandlerRegistrationCustomizer != null) { - this.resourceHandlerRegistrationCustomizer.customize(registration); - } - } - } /** diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java index 27ae96ee440e..d6127133dcc7 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java @@ -90,6 +90,7 @@ import org.springframework.web.reactive.accept.RequestedContentTypeResolver; import org.springframework.web.reactive.config.BlockingExecutionConfigurer; import org.springframework.web.reactive.config.DelegatingWebFluxConfiguration; +import org.springframework.web.reactive.config.ResourceHandlerRegistration; import org.springframework.web.reactive.config.WebFluxConfigurationSupport; import org.springframework.web.reactive.config.WebFluxConfigurer; import org.springframework.web.reactive.function.server.support.RouterFunctionMapping; @@ -122,6 +123,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; /** * Tests for {@link WebFluxAutoConfiguration}. @@ -182,6 +184,18 @@ void shouldCustomizeCodecs() { }); } + @Test + void shouldCustomizeResources() { + this.contextRunner.withUserConfiguration(ResourceHandlerRegistrationCustomizers.class).run((context) -> { + ResourceHandlerRegistrationCustomizer customizer1 = context + .getBean("firstResourceHandlerRegistrationCustomizer", ResourceHandlerRegistrationCustomizer.class); + ResourceHandlerRegistrationCustomizer customizer2 = context + .getBean("secondResourceHandlerRegistrationCustomizer", ResourceHandlerRegistrationCustomizer.class); + then(customizer1).should(times(2)).customize(any(ResourceHandlerRegistration.class)); + then(customizer2).should(times(2)).customize(any(ResourceHandlerRegistration.class)); + }); + } + @Test void shouldRegisterResourceHandlerMapping() { this.contextRunner.run((context) -> { @@ -843,6 +857,21 @@ CodecCustomizer firstCodecCustomizer() { } + @Configuration(proxyBeanMethods = false) + static class ResourceHandlerRegistrationCustomizers { + + @Bean + ResourceHandlerRegistrationCustomizer firstResourceHandlerRegistrationCustomizer() { + return mock(ResourceHandlerRegistrationCustomizer.class); + } + + @Bean + ResourceHandlerRegistrationCustomizer secondResourceHandlerRegistrationCustomizer() { + return mock(ResourceHandlerRegistrationCustomizer.class); + } + + } + @Configuration(proxyBeanMethods = false) static class ViewResolvers {