From 2a309a031a2282cf740fa7704640f9333a5a4e65 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 17 Nov 2017 12:55:11 -0500 Subject: [PATCH] Revise charset by location support for static resources --- .../web/servlet/config/MvcNamespaceUtils.java | 43 --------- .../config/ResourcesBeanDefinitionParser.java | 32 +------ .../ResourceHandlerRegistration.java | 23 ++--- .../annotation/ResourceHandlerRegistry.java | 3 +- .../resource/ResourceHttpRequestHandler.java | 89 ++++++++++++++----- .../web/servlet/config/MvcNamespaceTests.java | 25 +++--- .../ResourceHandlerRegistryTests.java | 26 ++++-- .../config/mvc-config-resources-chain.xml | 8 +- 8 files changed, 108 insertions(+), 141 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java index 52fe3071fa4..ed3ea8531bf 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java @@ -16,9 +16,7 @@ package org.springframework.web.servlet.config; -import java.nio.charset.Charset; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import org.springframework.beans.factory.config.BeanDefinition; @@ -26,9 +24,6 @@ import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; -import org.springframework.core.io.UrlResource; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import org.springframework.web.cors.CorsConfiguration; @@ -64,8 +59,6 @@ public abstract class MvcNamespaceUtils { private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector"; - private static final String URL_RESOURCE_CHARSET_PREFIX = "[charset="; - public static void registerDefaultComponents(ParserContext parserContext, Object source) { registerBeanNameUrlHandlerMapping(parserContext, source); @@ -228,40 +221,4 @@ public abstract class MvcNamespaceUtils { return null; } - /** - * Load the {@link Resource}'s for the given locations with the given - * {@link ResourceLoader} and add them to the output list. Also for - * {@link org.springframework.core.io.UrlResource URL-based resources} (e.g. files, - * HTTP URLs, etc) this method supports a special prefix to indicate the charset - * associated with the URL so that relative paths appended to it can be encoded - * correctly, e.g. {@code [charset=Windows-31J]http://example.org/path}. - * The charsets, if any, are added to the output map. - * @since 4.3.13 - */ - public static void loadResourceLocations(String[] locations, ResourceLoader resourceLoader, - List outputLocations, Map outputLocationCharsets) { - - for (String location : locations) { - Charset charset = null; - location = location.trim(); - if (location.startsWith(URL_RESOURCE_CHARSET_PREFIX)) { - int endIndex = location.indexOf("]", URL_RESOURCE_CHARSET_PREFIX.length()); - if (endIndex == -1) { - throw new IllegalArgumentException("Invalid charset syntax in location: " + location); - } - String value = location.substring(URL_RESOURCE_CHARSET_PREFIX.length(), endIndex); - charset = Charset.forName(value); - location = location.substring(endIndex + 1); - } - Resource resource = resourceLoader.getResource(location); - outputLocations.add(resource); - if (charset != null) { - if (!(resource instanceof UrlResource)) { - throw new IllegalArgumentException("Unexpected charset for non-UrlResource: " + resource); - } - outputLocationCharsets.put(resource, charset); - } - } - } - } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java index aa34ef6d5ed..8a7f2a9bd0c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java @@ -16,11 +16,6 @@ package org.springframework.web.servlet.config; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -28,7 +23,6 @@ import org.w3c.dom.Element; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; @@ -39,8 +33,6 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.cache.concurrent.ConcurrentMapCache; import org.springframework.core.Ordered; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; import org.springframework.http.CacheControl; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; @@ -170,35 +162,13 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser { return null; } - String[] locationValues = StringUtils.commaDelimitedListToStringArray(locationAttr); - if (context.getRegistry() instanceof ConfigurableBeanFactory) { - ConfigurableBeanFactory cbf = ((ConfigurableBeanFactory) context.getRegistry()); - for (int i = 0; i < locationValues.length; i++) { - locationValues[i] = cbf.resolveEmbeddedValue(locationValues[i]); - } - } - - ManagedList locations = new ManagedList(); - Map locationCharsets = new HashMap(); - ResourceLoader resourceLoader = context.getReaderContext().getResourceLoader(); - - if (resourceLoader != null) { - List resources = new ArrayList(); - MvcNamespaceUtils.loadResourceLocations(locationValues, resourceLoader, resources, locationCharsets); - locations.addAll(resources); - } - else { - locations.addAll(Arrays.asList(locationValues)); - } - RootBeanDefinition resourceHandlerDef = new RootBeanDefinition(ResourceHttpRequestHandler.class); resourceHandlerDef.setSource(source); resourceHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); MutablePropertyValues values = resourceHandlerDef.getPropertyValues(); values.add("urlPathHelper", pathHelperRef); - values.add("locations", locations); - values.add("locationCharsets", locationCharsets); + values.add("locationValues", StringUtils.commaDelimitedListToStringArray(locationAttr)); String cacheSeconds = element.getAttribute("cache-period"); if (StringUtils.hasText(cacheSeconds)) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistration.java index bfa76c05a6b..82bb3432d8c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistration.java @@ -16,18 +16,13 @@ package org.springframework.web.servlet.config.annotation; -import java.nio.charset.Charset; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Arrays; import java.util.List; -import java.util.Map; import org.springframework.cache.Cache; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; import org.springframework.http.CacheControl; import org.springframework.util.Assert; -import org.springframework.web.servlet.config.MvcNamespaceUtils; import org.springframework.web.servlet.resource.PathResourceResolver; import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; @@ -41,13 +36,9 @@ import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; */ public class ResourceHandlerRegistration { - private final ResourceLoader resourceLoader; - private final String[] pathPatterns; - private final List locations = new ArrayList(); - - private final Map locationCharsets = new HashMap(); + private final List locationValues = new ArrayList(4); private Integer cachePeriod; @@ -58,12 +49,10 @@ public class ResourceHandlerRegistration { /** * Create a {@link ResourceHandlerRegistration} instance. - * @param resourceLoader a resource loader for turning a String location into a {@link Resource} * @param pathPatterns one or more resource URL path patterns */ - public ResourceHandlerRegistration(ResourceLoader resourceLoader, String... pathPatterns) { + public ResourceHandlerRegistration(String... pathPatterns) { Assert.notEmpty(pathPatterns, "At least one path pattern is required for resource handling."); - this.resourceLoader = resourceLoader; this.pathPatterns = pathPatterns; } @@ -86,8 +75,7 @@ public class ResourceHandlerRegistration { * chained method invocation */ public ResourceHandlerRegistration addResourceLocations(String... resourceLocations) { - MvcNamespaceUtils.loadResourceLocations( - resourceLocations, this.resourceLoader, this.locations, this.locationCharsets); + this.locationValues.addAll(Arrays.asList(resourceLocations)); return this; } @@ -177,8 +165,7 @@ public class ResourceHandlerRegistration { handler.setResourceResolvers(this.resourceChainRegistration.getResourceResolvers()); handler.setResourceTransformers(this.resourceChainRegistration.getResourceTransformers()); } - handler.setLocations(this.locations); - handler.setLocationCharsets(this.locationCharsets); + handler.setLocationValues(this.locationValues); if (this.cacheControl != null) { handler.setCacheControl(this.cacheControl); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistry.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistry.java index 402341f8299..8b276218452 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistry.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistry.java @@ -114,8 +114,7 @@ public class ResourceHandlerRegistry { * registered resource handler */ public ResourceHandlerRegistration addResourceHandler(String... pathPatterns) { - ResourceHandlerRegistration registration = - new ResourceHandlerRegistration(this.applicationContext, pathPatterns); + ResourceHandlerRegistration registration = new ResourceHandlerRegistration(pathPatterns); this.registrations.add(registration); return registration; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java index 9c465326786..86706af19f2 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java @@ -20,7 +20,6 @@ import java.io.IOException; import java.net.URLDecoder; import java.nio.charset.Charset; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -33,7 +32,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; import org.springframework.core.io.support.ResourceRegion; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -101,11 +103,15 @@ public class ResourceHttpRequestHandler extends WebContentGenerator private static final Log logger = LogFactory.getLog(ResourceHttpRequestHandler.class); + private static final String URL_RESOURCE_CHARSET_PREFIX = "[charset="; + private final List locations = new ArrayList(4); private final Map locationCharsets = new HashMap(4); + private final List locationValues = new ArrayList(4); + private final List resourceResolvers = new ArrayList(4); private final List resourceTransformers = new ArrayList(4); @@ -129,8 +135,9 @@ public class ResourceHttpRequestHandler extends WebContentGenerator /** - * Set the {@code List} of {@code Resource} paths to use as sources + * Set the {@code List} of {@code Resource} locations to use as sources * for serving static resources. + * @see #setLocationValues(List) */ public void setLocations(List locations) { Assert.notNull(locations, "Locations list must not be null"); @@ -139,35 +146,27 @@ public class ResourceHttpRequestHandler extends WebContentGenerator } /** - * Return the {@code List} of {@code Resource} paths to use as sources - * for serving static resources. + * Return the configured {@code List} of {@code Resource} locations. + * Note that if {@link #setLocationValues(List) locationValues} are provided, + * instead of loaded Resource-based locations, this method will return + * empty until after initialization via {@link #afterPropertiesSet()}. */ public List getLocations() { return this.locations; } /** - * Specify charsets associated with the configured {@link #setLocations(List) - * locations}. This is supported for - * {@link org.springframework.core.io.UrlResource URL resources} such as a - * file or an HTTP URL location and is used in {@link PathResourceResolver} - * to correctly encode paths relative to the location. - *

Note: The charset is used only if the - * {@link #setUrlPathHelper urlPathHelper} property is also configured and - * its {@code urlDecode} property is set to {@code true}. - * @since 4.3.13 - */ - public void setLocationCharsets(Map locationCharsets) { - this.locationCharsets.clear(); - this.locationCharsets.putAll(locationCharsets); - } - - /** - * Return charsets associated with static resource locations. + * An alternative to {@link #setLocations(List)} that accepts a list of + * String-based location values, with support for {@link UrlResource}'s + * (e.g. files or HTTP URLs) with a special prefix to indicate the charset + * to use when appending relative paths. For example + * {@code "[charset=Windows-31J]http://example.org/path"}. * @since 4.3.13 */ - public Map getLocationCharsets() { - return Collections.unmodifiableMap(this.locationCharsets); + public void setLocationValues(List locationValues) { + Assert.notNull(locationValues, "Location values list must not be null"); + this.locationValues.clear(); + this.locationValues.addAll(locationValues); } /** @@ -297,6 +296,9 @@ public class ResourceHttpRequestHandler extends WebContentGenerator @Override public void afterPropertiesSet() throws Exception { + + loadResourceLocations(); + if (logger.isWarnEnabled() && CollectionUtils.isEmpty(this.locations)) { logger.warn("Locations list is empty. No resources will be served unless a " + "custom ResourceResolver is configured as an alternative to PathResourceResolver."); @@ -305,6 +307,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator if (this.resourceResolvers.isEmpty()) { this.resourceResolvers.add(new PathResourceResolver()); } + initAllowedLocations(); if (this.resourceHttpMessageConverter == null) { @@ -317,6 +320,46 @@ public class ResourceHttpRequestHandler extends WebContentGenerator this.contentNegotiationStrategy = initContentNegotiationStrategy(); } + private void loadResourceLocations() { + if (!CollectionUtils.isEmpty(this.locations) && !CollectionUtils.isEmpty(this.locationValues)) { + throw new IllegalArgumentException("Please set either Resource-based \"locations\" or " + + "String-based \"locationValues\", but not both."); + } + if (CollectionUtils.isEmpty(this.locationValues)) { + return; + } + ApplicationContext appContext = getApplicationContext(); + ConfigurableBeanFactory beanFactory = null; + if (appContext.getAutowireCapableBeanFactory() instanceof ConfigurableBeanFactory) { + beanFactory = ((ConfigurableBeanFactory) appContext.getAutowireCapableBeanFactory()); + } + for (String location : this.locationValues) { + if (beanFactory != null) { + location = beanFactory.resolveEmbeddedValue(location); + Assert.notNull(location, "Null location"); + } + Charset charset = null; + location = location.trim(); + if (location.startsWith(URL_RESOURCE_CHARSET_PREFIX)) { + int endIndex = location.indexOf("]", URL_RESOURCE_CHARSET_PREFIX.length()); + if (endIndex == -1) { + throw new IllegalArgumentException("Invalid charset syntax in location: " + location); + } + String value = location.substring(URL_RESOURCE_CHARSET_PREFIX.length(), endIndex); + charset = Charset.forName(value); + location = location.substring(endIndex + 1); + } + Resource resource = appContext.getResource(location); + this.locations.add(resource); + if (charset != null) { + if (!(resource instanceof UrlResource)) { + throw new IllegalArgumentException("Unexpected charset for non-UrlResource: " + resource); + } + this.locationCharsets.put(resource, charset); + } + } + } + /** * Look for a {@code PathResourceResolver} among the configured resource * resolvers and set its {@code allowedLocations} property (if empty) to diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java index 88af9254412..ced438b1411 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java @@ -21,8 +21,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -47,14 +47,13 @@ import org.junit.Test; import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.TypeMismatchException; -import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.concurrent.ConcurrentMapCache; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.core.Ordered; import org.springframework.core.convert.ConversionService; -import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat.ISO; import org.springframework.format.annotation.NumberFormat; @@ -86,7 +85,7 @@ import org.springframework.web.context.request.async.CallableProcessingIntercept import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter; import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor; import org.springframework.web.context.request.async.DeferredResultProcessingInterceptorAdapter; -import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.context.support.XmlWebApplicationContext; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.support.CompositeUriComponentsContributor; @@ -174,7 +173,7 @@ public class MvcNamespaceTests { "org.springframework.web.servlet.config.viewControllerHandlerMapping"; - private GenericWebApplicationContext appContext; + private XmlWebApplicationContext appContext; private TestController handler; @@ -184,7 +183,7 @@ public class MvcNamespaceTests { @Before public void setUp() throws Exception { TestMockServletContext servletContext = new TestMockServletContext(); - appContext = new GenericWebApplicationContext(); + appContext = new XmlWebApplicationContext(); appContext.setServletContext(servletContext); LocaleContextHolder.setLocale(Locale.US); @@ -435,8 +434,6 @@ public class MvcNamespaceTests { assertNotNull(handler); assertNotNull(handler.getUrlPathHelper()); - assertEquals(1, handler.getLocationCharsets().size()); - assertEquals(StandardCharsets.ISO_8859_1, handler.getLocationCharsets().values().iterator().next()); List resolvers = handler.getResourceResolvers(); assertThat(resolvers, Matchers.hasSize(4)); @@ -456,8 +453,9 @@ public class MvcNamespaceTests { Matchers.instanceOf(ContentVersionStrategy.class)); PathResourceResolver pathResolver = (PathResourceResolver) resolvers.get(3); - assertEquals(1, pathResolver.getLocationCharsets().size()); - assertEquals(StandardCharsets.ISO_8859_1, handler.getLocationCharsets().values().iterator().next()); + Map locationCharsets = pathResolver.getLocationCharsets(); + assertEquals(1, locationCharsets.size()); + assertEquals(StandardCharsets.ISO_8859_1, locationCharsets.values().iterator().next()); List transformers = handler.getResourceTransformers(); assertThat(transformers, Matchers.hasSize(3)); @@ -967,11 +965,8 @@ public class MvcNamespaceTests { private void loadBeanDefinitions(String fileName) { - XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(appContext); - ClassPathResource resource = new ClassPathResource(fileName, AnnotationDrivenBeanDefinitionParserTests.class); - reader.loadBeanDefinitions(resource); - String names = Arrays.toString(this.appContext.getBeanDefinitionNames()); - appContext.refresh(); + this.appContext.setConfigLocation("classpath:org/springframework/web/servlet/config/" + fileName); + this.appContext.refresh(); } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistryTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistryTests.java index 946e4e59bdf..1608e647e95 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistryTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistryTests.java @@ -16,8 +16,10 @@ package org.springframework.web.servlet.config.annotation; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Map; import org.hamcrest.Matchers; import org.junit.Before; @@ -25,11 +27,12 @@ import org.junit.Test; import org.mockito.Mockito; import org.springframework.cache.concurrent.ConcurrentMapCache; +import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; +import org.springframework.http.CacheControl; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.mock.web.test.MockServletContext; -import org.springframework.http.CacheControl; import org.springframework.web.accept.ContentNegotiationManager; import org.springframework.web.context.support.GenericWebApplicationContext; import org.springframework.web.servlet.HandlerMapping; @@ -46,7 +49,12 @@ import org.springframework.web.servlet.resource.VersionResourceResolver; import org.springframework.web.servlet.resource.WebJarsResourceResolver; import org.springframework.web.util.UrlPathHelper; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; /** * Unit tests for {@link ResourceHandlerRegistry}. @@ -64,8 +72,11 @@ public class ResourceHandlerRegistryTests { @Before public void setUp() { - this.registry = new ResourceHandlerRegistry(new GenericWebApplicationContext(), - new MockServletContext(), new ContentNegotiationManager(), new UrlPathHelper()); + GenericWebApplicationContext appContext = new GenericWebApplicationContext(); + appContext.refresh(); + + this.registry = new ResourceHandlerRegistry(appContext, new MockServletContext(), + new ContentNegotiationManager(), new UrlPathHelper()); this.registration = this.registry.addResourceHandler("/resources/**"); this.registration.addResourceLocations("classpath:org/springframework/web/servlet/config/annotation/"); @@ -226,13 +237,12 @@ public class ResourceHandlerRegistryTests { UrlResource resource = (UrlResource) handler.getLocations().get(1); assertEquals("file:/tmp", resource.getURL().toString()); assertNotNull(handler.getUrlPathHelper()); - assertEquals(1, handler.getLocationCharsets().size()); - assertEquals(StandardCharsets.ISO_8859_1, handler.getLocationCharsets().get(resource)); List resolvers = handler.getResourceResolvers(); PathResourceResolver resolver = (PathResourceResolver) resolvers.get(resolvers.size()-1); - assertEquals(1, resolver.getLocationCharsets().size()); - assertEquals(StandardCharsets.ISO_8859_1, handler.getLocationCharsets().values().iterator().next()); + Map locationCharsets = resolver.getLocationCharsets(); + assertEquals(1, locationCharsets.size()); + assertEquals(StandardCharsets.ISO_8859_1, locationCharsets.values().iterator().next()); } private ResourceHttpRequestHandler getHandler(String pathPattern) { diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-resources-chain.xml b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-resources-chain.xml index 32d0c2a32ab..89560d1bec1 100644 --- a/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-resources-chain.xml +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-resources-chain.xml @@ -21,7 +21,13 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> - + + + location=file:///tmp + + + +