Work around unwanted static resource warnings from WebFlux and MVC

See gh-28223
This commit is contained in:
Andy Wilkinson 2021-10-14 15:08:42 +01:00
parent bad37f9e37
commit b32a38a814
4 changed files with 42 additions and 17 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,6 +17,8 @@
package org.springframework.boot.autoconfigure.web.reactive; package org.springframework.boot.autoconfigure.web.reactive;
import java.time.Duration; import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -49,6 +51,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.io.ResourceLoader;
import org.springframework.format.FormatterRegistry; import org.springframework.format.FormatterRegistry;
import org.springframework.format.support.FormattingConversionService; import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.http.codec.ServerCodecConfigurer;
@ -151,12 +154,14 @@ public class WebFluxAutoConfiguration {
private final ObjectProvider<ViewResolver> viewResolvers; private final ObjectProvider<ViewResolver> viewResolvers;
private final ResourceLoader resourceLoader;
public WebFluxConfig(org.springframework.boot.autoconfigure.web.ResourceProperties resourceProperties, public WebFluxConfig(org.springframework.boot.autoconfigure.web.ResourceProperties resourceProperties,
WebProperties webProperties, WebFluxProperties webFluxProperties, ListableBeanFactory beanFactory, WebProperties webProperties, WebFluxProperties webFluxProperties, ListableBeanFactory beanFactory,
ObjectProvider<HandlerMethodArgumentResolver> resolvers, ObjectProvider<HandlerMethodArgumentResolver> resolvers,
ObjectProvider<CodecCustomizer> codecCustomizers, ObjectProvider<CodecCustomizer> codecCustomizers,
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizer, ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizer,
ObjectProvider<ViewResolver> viewResolvers) { ObjectProvider<ViewResolver> viewResolvers, ResourceLoader resourceLoader) {
this.resourceProperties = resourceProperties.hasBeenCustomized() ? resourceProperties this.resourceProperties = resourceProperties.hasBeenCustomized() ? resourceProperties
: webProperties.getResources(); : webProperties.getResources();
this.webFluxProperties = webFluxProperties; this.webFluxProperties = webFluxProperties;
@ -165,6 +170,7 @@ public class WebFluxAutoConfiguration {
this.codecCustomizers = codecCustomizers; this.codecCustomizers = codecCustomizers;
this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizer.getIfAvailable(); this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizer.getIfAvailable();
this.viewResolvers = viewResolvers; this.viewResolvers = viewResolvers;
this.resourceLoader = resourceLoader;
} }
@Override @Override
@ -184,17 +190,28 @@ public class WebFluxAutoConfiguration {
return; return;
} }
if (!registry.hasMappingForPattern("/webjars/**")) { if (!registry.hasMappingForPattern("/webjars/**")) {
ResourceHandlerRegistration registration = registry.addResourceHandler("/webjars/**") String webjarsLocation = "classpath:/META-INF/resources/webjars/";
.addResourceLocations("classpath:/META-INF/resources/webjars/"); if (this.resourceLoader.getResource(webjarsLocation).exists()) {
configureResourceCaching(registration); ResourceHandlerRegistration registration = registry.addResourceHandler("/webjars/**")
customizeResourceHandlerRegistration(registration); .addResourceLocations(webjarsLocation);
configureResourceCaching(registration);
customizeResourceHandlerRegistration(registration);
}
} }
String staticPathPattern = this.webFluxProperties.getStaticPathPattern(); String staticPathPattern = this.webFluxProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) { if (!registry.hasMappingForPattern(staticPathPattern)) {
ResourceHandlerRegistration registration = registry.addResourceHandler(staticPathPattern) List<String> foundLocations = new ArrayList<>();
.addResourceLocations(this.resourceProperties.getStaticLocations()); for (String staticLocation : this.resourceProperties.getStaticLocations()) {
configureResourceCaching(registration); if (this.resourceLoader.getResource(staticLocation).exists()) {
customizeResourceHandlerRegistration(registration); foundLocations.add(staticLocation);
}
}
if (!foundLocations.isEmpty()) {
ResourceHandlerRegistration registration = registry.addResourceHandler(staticPathPattern)
.addResourceLocations(foundLocations.toArray(new String[0]));
configureResourceCaching(registration);
customizeResourceHandlerRegistration(registration);
}
} }
} }

View File

@ -201,6 +201,8 @@ public class WebMvcAutoConfiguration {
private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer; private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
private final ResourceLoader resourceLoader;
private ServletContext servletContext; private ServletContext servletContext;
public WebMvcAutoConfigurationAdapter( public WebMvcAutoConfigurationAdapter(
@ -209,7 +211,7 @@ public class WebMvcAutoConfiguration {
ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<HttpMessageConverters> messageConvertersProvider,
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,
ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<DispatcherServletPath> dispatcherServletPath,
ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) { ObjectProvider<ServletRegistrationBean<?>> servletRegistrations, ResourceLoader resourceLoader) {
this.resourceProperties = resourceProperties.hasBeenCustomized() ? resourceProperties this.resourceProperties = resourceProperties.hasBeenCustomized() ? resourceProperties
: webProperties.getResources(); : webProperties.getResources();
this.mvcProperties = mvcProperties; this.mvcProperties = mvcProperties;
@ -218,6 +220,7 @@ public class WebMvcAutoConfiguration {
this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable(); this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
this.dispatcherServletPath = dispatcherServletPath; this.dispatcherServletPath = dispatcherServletPath;
this.servletRegistrations = servletRegistrations; this.servletRegistrations = servletRegistrations;
this.resourceLoader = resourceLoader;
this.mvcProperties.checkConfiguration(); this.mvcProperties.checkConfiguration();
} }
@ -334,7 +337,11 @@ public class WebMvcAutoConfiguration {
logger.debug("Default resource handling disabled"); logger.debug("Default resource handling disabled");
return; return;
} }
addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/"); Resource webjarsLocationResource = this.resourceLoader
.getResource("classpath:/META-INF/resources/webjars/");
if (webjarsLocationResource.exists()) {
addResourceHandler(registry, "/webjars/**", webjarsLocationResource);
}
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> { addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations()); registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) { if (this.servletContext != null) {
@ -344,7 +351,7 @@ public class WebMvcAutoConfiguration {
}); });
} }
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, String... locations) { private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, Resource... locations) {
addResourceHandler(registry, pattern, (registration) -> registration.addResourceLocations(locations)); addResourceHandler(registry, pattern, (registration) -> registration.addResourceLocations(locations));
} }

View File

@ -150,9 +150,10 @@ class WebFluxAutoConfigurationTests {
SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class); SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class);
assertThat(hm.getUrlMap().get("/**")).isInstanceOf(ResourceWebHandler.class); assertThat(hm.getUrlMap().get("/**")).isInstanceOf(ResourceWebHandler.class);
ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap().get("/**"); ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap().get("/**");
assertThat(staticHandler).extracting("locationValues").asList().hasSize(4); assertThat(staticHandler).extracting("locationValues").asList().hasSize(2);
assertThat(staticHandler.getLocations()).hasSize(1); assertThat(staticHandler.getLocations()).hasSize(2);
assertThat(staticHandler.getLocations().get(0)).hasToString("class path resource [public/]"); assertThat(staticHandler.getLocations().get(0)).hasToString("class path resource [META-INF/resources/]");
assertThat(staticHandler.getLocations().get(1)).hasToString("class path resource [public/]");
assertThat(hm.getUrlMap().get("/webjars/**")).isInstanceOf(ResourceWebHandler.class); assertThat(hm.getUrlMap().get("/webjars/**")).isInstanceOf(ResourceWebHandler.class);
ResourceWebHandler webjarsHandler = (ResourceWebHandler) hm.getUrlMap().get("/webjars/**"); ResourceWebHandler webjarsHandler = (ResourceWebHandler) hm.getUrlMap().get("/webjars/**");
assertThat(webjarsHandler).extracting("locationValues").asList() assertThat(webjarsHandler).extracting("locationValues").asList()
@ -166,7 +167,7 @@ class WebFluxAutoConfigurationTests {
SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class); SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class);
assertThat(hm.getUrlMap().get("/static/**")).isInstanceOf(ResourceWebHandler.class); assertThat(hm.getUrlMap().get("/static/**")).isInstanceOf(ResourceWebHandler.class);
ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap().get("/static/**"); ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap().get("/static/**");
assertThat(staticHandler).extracting("locationValues").asList().hasSize(4); assertThat(staticHandler).extracting("locationValues").asList().hasSize(2);
}); });
} }