From b32a38a8147ccc84cfdfe9edba3eface01fa1a04 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 14 Oct 2021 15:08:42 +0100 Subject: [PATCH] Work around unwanted static resource warnings from WebFlux and MVC See gh-28223 --- .../reactive/WebFluxAutoConfiguration.java | 37 ++++++++++++++----- .../web/servlet/WebMvcAutoConfiguration.java | 13 +++++-- .../WebFluxAutoConfigurationTests.java | 9 +++-- .../META-INF/resources/webjars/webjar | 0 4 files changed, 42 insertions(+), 17 deletions(-) create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/resources/META-INF/resources/webjars/webjar 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 41349b5848..7f9aa1a5e4 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 @@ -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"); * you may not use this file except in compliance with the License. @@ -17,6 +17,8 @@ package org.springframework.boot.autoconfigure.web.reactive; import java.time.Duration; +import java.util.ArrayList; +import java.util.List; import org.apache.commons.logging.Log; 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.Import; import org.springframework.core.Ordered; +import org.springframework.core.io.ResourceLoader; import org.springframework.format.FormatterRegistry; import org.springframework.format.support.FormattingConversionService; import org.springframework.http.codec.ServerCodecConfigurer; @@ -151,12 +154,14 @@ public class WebFluxAutoConfiguration { private final ObjectProvider viewResolvers; + private final ResourceLoader resourceLoader; + public WebFluxConfig(org.springframework.boot.autoconfigure.web.ResourceProperties resourceProperties, WebProperties webProperties, WebFluxProperties webFluxProperties, ListableBeanFactory beanFactory, ObjectProvider resolvers, ObjectProvider codecCustomizers, ObjectProvider resourceHandlerRegistrationCustomizer, - ObjectProvider viewResolvers) { + ObjectProvider viewResolvers, ResourceLoader resourceLoader) { this.resourceProperties = resourceProperties.hasBeenCustomized() ? resourceProperties : webProperties.getResources(); this.webFluxProperties = webFluxProperties; @@ -165,6 +170,7 @@ public class WebFluxAutoConfiguration { this.codecCustomizers = codecCustomizers; this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizer.getIfAvailable(); this.viewResolvers = viewResolvers; + this.resourceLoader = resourceLoader; } @Override @@ -184,17 +190,28 @@ public class WebFluxAutoConfiguration { return; } if (!registry.hasMappingForPattern("/webjars/**")) { - ResourceHandlerRegistration registration = registry.addResourceHandler("/webjars/**") - .addResourceLocations("classpath:/META-INF/resources/webjars/"); - configureResourceCaching(registration); - customizeResourceHandlerRegistration(registration); + String webjarsLocation = "classpath:/META-INF/resources/webjars/"; + if (this.resourceLoader.getResource(webjarsLocation).exists()) { + ResourceHandlerRegistration registration = registry.addResourceHandler("/webjars/**") + .addResourceLocations(webjarsLocation); + configureResourceCaching(registration); + customizeResourceHandlerRegistration(registration); + } } String staticPathPattern = this.webFluxProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { - ResourceHandlerRegistration registration = registry.addResourceHandler(staticPathPattern) - .addResourceLocations(this.resourceProperties.getStaticLocations()); - configureResourceCaching(registration); - customizeResourceHandlerRegistration(registration); + List foundLocations = new ArrayList<>(); + for (String staticLocation : this.resourceProperties.getStaticLocations()) { + if (this.resourceLoader.getResource(staticLocation).exists()) { + foundLocations.add(staticLocation); + } + } + if (!foundLocations.isEmpty()) { + ResourceHandlerRegistration registration = registry.addResourceHandler(staticPathPattern) + .addResourceLocations(foundLocations.toArray(new String[0])); + configureResourceCaching(registration); + customizeResourceHandlerRegistration(registration); + } } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java index 2e8de24cac..6c7ea8dc3c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java @@ -201,6 +201,8 @@ public class WebMvcAutoConfiguration { private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer; + private final ResourceLoader resourceLoader; + private ServletContext servletContext; public WebMvcAutoConfigurationAdapter( @@ -209,7 +211,7 @@ public class WebMvcAutoConfiguration { ObjectProvider messageConvertersProvider, ObjectProvider resourceHandlerRegistrationCustomizerProvider, ObjectProvider dispatcherServletPath, - ObjectProvider> servletRegistrations) { + ObjectProvider> servletRegistrations, ResourceLoader resourceLoader) { this.resourceProperties = resourceProperties.hasBeenCustomized() ? resourceProperties : webProperties.getResources(); this.mvcProperties = mvcProperties; @@ -218,6 +220,7 @@ public class WebMvcAutoConfiguration { this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable(); this.dispatcherServletPath = dispatcherServletPath; this.servletRegistrations = servletRegistrations; + this.resourceLoader = resourceLoader; this.mvcProperties.checkConfiguration(); } @@ -334,7 +337,11 @@ public class WebMvcAutoConfiguration { logger.debug("Default resource handling disabled"); 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) -> { registration.addResourceLocations(this.resourceProperties.getStaticLocations()); 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)); } 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 20a5b410f4..36381b03b9 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 @@ -150,9 +150,10 @@ class WebFluxAutoConfigurationTests { SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class); assertThat(hm.getUrlMap().get("/**")).isInstanceOf(ResourceWebHandler.class); ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap().get("/**"); - assertThat(staticHandler).extracting("locationValues").asList().hasSize(4); - assertThat(staticHandler.getLocations()).hasSize(1); - assertThat(staticHandler.getLocations().get(0)).hasToString("class path resource [public/]"); + assertThat(staticHandler).extracting("locationValues").asList().hasSize(2); + assertThat(staticHandler.getLocations()).hasSize(2); + 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); ResourceWebHandler webjarsHandler = (ResourceWebHandler) hm.getUrlMap().get("/webjars/**"); assertThat(webjarsHandler).extracting("locationValues").asList() @@ -166,7 +167,7 @@ class WebFluxAutoConfigurationTests { SimpleUrlHandlerMapping hm = context.getBean("resourceHandlerMapping", SimpleUrlHandlerMapping.class); assertThat(hm.getUrlMap().get("/static/**")).isInstanceOf(ResourceWebHandler.class); ResourceWebHandler staticHandler = (ResourceWebHandler) hm.getUrlMap().get("/static/**"); - assertThat(staticHandler).extracting("locationValues").asList().hasSize(4); + assertThat(staticHandler).extracting("locationValues").asList().hasSize(2); }); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/META-INF/resources/webjars/webjar b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/META-INF/resources/webjars/webjar new file mode 100644 index 0000000000..e69de29bb2