From 5a2e30c18bee91343ca9547930efc678a08b0cac Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 27 Sep 2013 21:02:17 -0400 Subject: [PATCH] Refactor Resource URL generation and Servlet Filter Renamed ResourceUrlMapper to ResourceUrlGenerator and refactored it to be configured with Resource-serving HandlerMappings as opposed to having them detected in the ApplicationContext through the BeanPostProcessor contact. Renamed and polished ResourceUrlEncodingFilter to ResourceUrlFilter and added tests. --- .../ResourceHandlerRegistration.java | 37 ++++- ...dingFilter.java => ResourceUrlFilter.java} | 40 +++-- .../resource/ResourceUrlGenerator.java | 129 +++++++++++++++ .../servlet/resource/ResourceUrlMapper.java | 106 ------------ .../resource/ResourceUrlFilterTests.java | 154 ++++++++++++++++++ ...ts.java => ResourceUrlGeneratorTests.java} | 34 ++-- 6 files changed, 357 insertions(+), 143 deletions(-) rename spring-webmvc/src/main/java/org/springframework/web/servlet/resource/{ResourceUrlEncodingFilter.java => ResourceUrlFilter.java} (62%) create mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlGenerator.java delete mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlMapper.java create mode 100644 spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlFilterTests.java rename spring-webmvc/src/test/java/org/springframework/web/servlet/resource/{ResourceUrlMapperTests.java => ResourceUrlGeneratorTests.java} (74%) 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 8ce3914180e..0a876df93fd 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 @@ -23,7 +23,10 @@ import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; +import org.springframework.web.servlet.resource.PathResourceResolver; import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; +import org.springframework.web.servlet.resource.ResourceResolver; +import org.springframework.web.servlet.resource.ResourceTransformer; /** * Encapsulates information required to create a resource handlers. @@ -43,6 +46,11 @@ public class ResourceHandlerRegistration { private Integer cachePeriod; + private List resourceResolvers; + + private List resourceTransformers; + + /** * Create a {@link ResourceHandlerRegistration} instance. * @param resourceLoader a resource loader for turning a String location into a {@link Resource} @@ -70,6 +78,23 @@ public class ResourceHandlerRegistration { return this; } + /** + * Configure the list of {@link ResourceResolver}s to use. + *

+ * By default {@link PathResourceResolver} is configured. If using this property, it + * is recommended to add {@link PathResourceResolver} as the last resolver. + */ + public void setResourceResolvers(List resourceResolvers) { + this.resourceResolvers = resourceResolvers; + } + + /** + * Configure the list of {@link ResourceTransformer}s to use. + */ + public void setResourceTransformers(List transformers) { + this.resourceTransformers = transformers; + } + /** * Specify the cache period for the resources served by the resource handler, in seconds. The default is to not * send any cache headers but to rely on last-modified timestamps only. Set to 0 in order to send cache headers @@ -95,9 +120,15 @@ public class ResourceHandlerRegistration { protected ResourceHttpRequestHandler getRequestHandler() { Assert.isTrue(!CollectionUtils.isEmpty(locations), "At least one location is required for resource handling."); ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler(); - requestHandler.setLocations(locations); - if (cachePeriod != null) { - requestHandler.setCacheSeconds(cachePeriod); + if (this.resourceResolvers != null) { + requestHandler.setResourceResolvers(this.resourceResolvers); + } + if (this.resourceTransformers != null) { + requestHandler.setResourceTransformers(this.resourceTransformers); + } + requestHandler.setLocations(this.locations); + if (this.cachePeriod != null) { + requestHandler.setCacheSeconds(this.cachePeriod); } return requestHandler; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlFilter.java similarity index 62% rename from spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilter.java rename to spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlFilter.java index 84008cd029b..0d571c6d434 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlEncodingFilter.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlFilter.java @@ -17,6 +17,9 @@ package org.springframework.web.servlet.resource; import java.io.IOException; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; import javax.servlet.FilterChain; import javax.servlet.ServletException; @@ -31,13 +34,17 @@ import org.springframework.web.util.UrlPathHelper; /** + * A filter that wraps the {@link HttpServletResponse} and overrides its + * {@link HttpServletResponse#encodeURL(String) encodeURL} method in order to generate + * resource URL links via {@link ResourceUrlGenerator}. * * @author Jeremy Grelle + * @author Rossen Stoyanchev * @since 4.0 */ -public class ResourceUrlEncodingFilter extends OncePerRequestFilter { +public class ResourceUrlFilter extends OncePerRequestFilter { - private ResourceUrlMapper mapper; + private Set resourceUrlGenerators; @Override @@ -49,8 +56,10 @@ public class ResourceUrlEncodingFilter extends OncePerRequestFilter { @Override protected void initFilterBean() throws ServletException { - WebApplicationContext appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); - this.mapper = appContext.getBean(ResourceUrlMapper.class); + WebApplicationContext cxt = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); + Map beans = cxt.getBeansOfType(ResourceUrlGenerator.class); + this.resourceUrlGenerators = new LinkedHashSet(); + this.resourceUrlGenerators.addAll(beans.values()); } @@ -60,35 +69,30 @@ public class ResourceUrlEncodingFilter extends OncePerRequestFilter { private String pathPrefix; + private ResourceUrlResponseWrapper(HttpServletRequest request, HttpServletResponse wrapped) { super(wrapped); - - this.pathPrefix = pathHelper.getContextPath(request); - String servletPath = pathHelper.getServletPath(request); - String appPath = pathHelper.getPathWithinApplication(request); - //This accounts for the behavior when servlet is mapped to "/" - if (!servletPath.equals(appPath)) { - this.pathPrefix += pathHelper.getServletPath(request); - } + String requestUri = this.pathHelper.getRequestUri(request); + String lookupPath = this.pathHelper.getLookupPathForRequest(request); + this.pathPrefix = requestUri.replace(lookupPath, ""); } @Override public String encodeURL(String url) { - if(url.startsWith(pathPrefix)) { - String relativeUrl = url.replaceFirst(pathPrefix, ""); + if(url.startsWith(this.pathPrefix)) { + String relativeUrl = url.replaceFirst(this.pathPrefix, ""); if (!relativeUrl.startsWith("/")) { relativeUrl = "/" + relativeUrl; } - if (mapper.isResourceUrl(relativeUrl)) { - String resourceUrl = mapper.getUrlForResource(relativeUrl); + for (ResourceUrlGenerator generator : resourceUrlGenerators) { + String resourceUrl = generator.getResourceUrl(relativeUrl); if (resourceUrl != null) { - return resourceUrl; + return super.encodeURL(this.pathPrefix + resourceUrl); } } } return super.encodeURL(url); } - } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlGenerator.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlGenerator.java new file mode 100644 index 00000000000..f4086b875aa --- /dev/null +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlGenerator.java @@ -0,0 +1,129 @@ +/* + * Copyright 2002-2013 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.servlet.resource; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; + +import org.springframework.core.io.Resource; +import org.springframework.util.PathMatcher; +import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; + + +/** + * A helper class for generating the URL for a resource. Given knowledge of all configured + * resource handler mappings (see {@link #setResourceHandlerMappings(List)}), it can + * determine whether a given path is a path to a resource, as well as what URL should be + * sent to the client to access that resource. This is essentially the reverse of + * resolving an incoming request URL to a resource. + * + * @author Rossen Stoyanchev + * @since 4.0 + */ +public class ResourceUrlGenerator { + + private final List resourceMappings = new ArrayList(); + + + /** + * Configure this instance with the handler mappings used to serve resources. It is + * expected that the handler mapping URL map contains handlers of type + * {@link ResourceHttpRequestHandler}. + * + * @param handlerMappings resource handler mappings + */ + public void setResourceHandlerMappings(List handlerMappings) { + this.resourceMappings.clear(); + if (handlerMappings == null) { + return; + } + for (SimpleUrlHandlerMapping handlerMapping : handlerMappings) { + PathMatcher pathMatcher = handlerMapping.getPathMatcher(); + + for(Entry entry : handlerMapping.getUrlMap().entrySet()) { + Object value = entry.getValue(); + if (value instanceof ResourceHttpRequestHandler) { + ResourceHttpRequestHandler handler = (ResourceHttpRequestHandler) value; + + String pattern = entry.getKey(); + List resolvers = handler.getResourceResolvers(); + List locations = handler.getLocations(); + this.resourceMappings.add(new ResourceMapping(pattern, pathMatcher, resolvers, locations)); + } + } + } + } + + /** + * Resolve the given resource path to a URL path. This is useful when rendering URL + * links to clients to determine the actual URL to use. + * + * @param candidatePath the resource path to resolve + * + * @return the resolved URL path or {@code null} if the given path does not match to + * any resource or otherwise could not be resolved to a resource URL path + */ + public String getResourceUrl(String candidatePath) { + for (ResourceMapping mapping : this.resourceMappings) { + String url = mapping.getUrlForResource(candidatePath); + if (url != null) { + return url; + } + } + return null; + } + + + private static class ResourceMapping { + + private final String pattern; + + private final PathMatcher pathMatcher; + + private final List resolvers; + + private final List locations; + + + public ResourceMapping(String pattern, PathMatcher pathMatcher, + List resolvers, List locations) { + + this.pattern = pattern; + this.pathMatcher = pathMatcher; + this.resolvers = resolvers; + this.locations = locations; + } + + public String getUrlForResource(String candidatePath) { + + if (this.pathMatcher.match(this.pattern, candidatePath)) { + + String pathWithinMapping = this.pathMatcher.extractPathWithinPattern(this.pattern, candidatePath); + String pathMapping = candidatePath.replace(pathWithinMapping, ""); + + DefaultResourceResolverChain chain = new DefaultResourceResolverChain(this.resolvers); + String url = chain.resolveUrlPath(pathWithinMapping, this.locations); + if (url != null) { + return pathMapping + url; + } + } + return null; + } + } + +} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlMapper.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlMapper.java deleted file mode 100644 index 4885d05ebae..00000000000 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceUrlMapper.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2002-2013 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.web.servlet.resource; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.context.ApplicationListener; -import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.core.OrderComparator; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.ClassUtils; -import org.springframework.util.PathMatcher; -import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; - - -/** - * - * @author Jeremy Grelle - * @since 4.0 - */ -public class ResourceUrlMapper implements BeanPostProcessor, ApplicationListener{ - - private final Map handlers = new LinkedHashMap(); - - private final List mappings = new ArrayList(); - - private final PathMatcher matcher = new AntPathMatcher(); - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { - return bean; - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { - if (ClassUtils.isAssignableValue(SimpleUrlHandlerMapping.class, bean)) { - SimpleUrlHandlerMapping mapping = (SimpleUrlHandlerMapping) bean; - for(Entry mappingEntry : mapping.getUrlMap().entrySet()) { - Object val = mappingEntry.getValue(); - if (val instanceof ResourceHttpRequestHandler) { - this.mappings.add(mapping); - } - } - } - return bean; - } - - @Override - public void onApplicationEvent(ContextRefreshedEvent event) { - OrderComparator.sort(this.mappings); - for (SimpleUrlHandlerMapping mapping : mappings) { - for(Entry mappingEntry : mapping.getUrlMap().entrySet()) { - Object val = mappingEntry.getValue(); - this.handlers.put(mappingEntry.getKey(), (ResourceHttpRequestHandler) val); - } - } - } - - public String getUrlForResource(String resourcePath) { - for (Entry mapping : this.handlers.entrySet()) { - if (matcher.match(mapping.getKey(), resourcePath)) { - ResourceHttpRequestHandler handler = mapping.getValue(); - String nestedPath = matcher.extractPathWithinPattern(mapping.getKey(), resourcePath); - String prefix = resourcePath.replace(nestedPath, ""); - List resolvers = handler.getResourceResolvers(); - DefaultResourceResolverChain chain = new DefaultResourceResolverChain(resolvers); - String url = chain.resolveUrlPath(nestedPath, handler.getLocations()); - if (url != null) { - return prefix + url; - } - } - } - return null; - } - - public boolean isResourceUrl(String relativeUrl) { - for (String mapping : this.handlers.keySet()) { - if (matcher.match(mapping, relativeUrl)) { - return true; - } - } - return false; - } -} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlFilterTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlFilterTests.java new file mode 100644 index 00000000000..6fce5731419 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlFilterTests.java @@ -0,0 +1,154 @@ +/* + * Copyright 2002-2013 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.web.servlet.resource; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.Test; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.mock.web.test.MockFilterChain; +import org.springframework.mock.web.test.MockHttpServletRequest; +import org.springframework.mock.web.test.MockHttpServletResponse; +import org.springframework.mock.web.test.MockServletContext; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; +import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; + +import static org.junit.Assert.*; + + +/** + * + * @author Rossen Stoyanchev + */ +public class ResourceUrlFilterTests { + + private MockFilterChain filterChain; + + private TestServlet servlet; + + + @Test + public void rootServletMapping() throws Exception { + + initFilterChain(WebConfig.class); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); + request.setRequestURI("/myapp/index.html"); + request.setContextPath("/myapp"); + request.setServletPath("/index.html"); + this.filterChain.doFilter(request, new MockHttpServletResponse()); + + String actual = this.servlet.response.encodeURL("/myapp/resources/foo.css"); + assertEquals("/myapp/resources/foo-e36d2e05253c6c7085a91522ce43a0b4.css", actual); + } + + @Test + public void prefixServletMapping() throws Exception { + + initFilterChain(WebConfig.class); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); + request.setRequestURI("/myapp/myservlet/index.html"); + request.setContextPath("/myapp"); + request.setServletPath("/myservlet"); + this.filterChain.doFilter(request, new MockHttpServletResponse()); + + String actual = this.servlet.response.encodeURL("/myapp/myservlet/resources/foo.css"); + assertEquals("/myapp/myservlet/resources/foo-e36d2e05253c6c7085a91522ce43a0b4.css", actual); + } + + @Test + public void extensionServletMapping() throws Exception { + + initFilterChain(WebConfig.class); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); + request.setRequestURI("/myapp/index.html"); + request.setContextPath("/myapp"); + request.setServletPath("/index.html"); + this.filterChain.doFilter(request, new MockHttpServletResponse()); + + String actual = this.servlet.response.encodeURL("/myapp/resources/foo.css"); + assertEquals("/myapp/resources/foo-e36d2e05253c6c7085a91522ce43a0b4.css", actual); + } + + private void initFilterChain(Class configClass) throws ServletException { + + MockServletContext servletContext = new MockServletContext(); + + AnnotationConfigWebApplicationContext cxt = new AnnotationConfigWebApplicationContext(); + cxt.setServletContext(servletContext); + cxt.register(configClass); + cxt.refresh(); + + servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, cxt); + + ResourceUrlFilter filter = new ResourceUrlFilter(); + filter.setServletContext(servletContext); + filter.initFilterBean(); + + this.servlet = new TestServlet(); + this.filterChain = new MockFilterChain(servlet, filter); + } + + + @Configuration + static class WebConfig extends WebMvcConfigurationSupport { + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + + List resourceResolvers = new ArrayList<>(); + resourceResolvers.add(new FingerprintResourceResolver()); + resourceResolvers.add(new PathResourceResolver()); + + registry.addResourceHandler("/resources/**") + .addResourceLocations("classpath:org/springframework/web/servlet/resource/test/") + .setResourceResolvers(resourceResolvers); + } + + @Bean + public ResourceUrlGenerator resourceUrlGenerator() { + ResourceUrlGenerator generator = new ResourceUrlGenerator(); + SimpleUrlHandlerMapping handlerMapping = (SimpleUrlHandlerMapping) resourceHandlerMapping(); + generator.setResourceHandlerMappings(Collections.singletonList(handlerMapping)); + return generator; + } + } + + private static class TestServlet extends HttpServlet { + + private HttpServletResponse response; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + this.response = response; + } + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlMapperTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlGeneratorTests.java similarity index 74% rename from spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlMapperTests.java rename to spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlGeneratorTests.java index 2c6ee8f4b08..2c3a2149229 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlMapperTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlGeneratorTests.java @@ -17,6 +17,7 @@ package org.springframework.web.servlet.resource; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -33,41 +34,42 @@ import static org.junit.Assert.*; /** * * @author Jeremy Grelle + * @author Rossen Stoyanchev */ -public class ResourceUrlMapperTests { +public class ResourceUrlGeneratorTests { ResourceHttpRequestHandler handler; SimpleUrlHandlerMapping mapping; - ResourceUrlMapper mapper; + ResourceUrlGenerator generator; + @Before public void setUp() { - List resourcePaths = new ArrayList(); - resourcePaths.add(new ClassPathResource("test/", getClass())); - resourcePaths.add(new ClassPathResource("testalternatepath/", getClass())); + List locations = new ArrayList(); + locations.add(new ClassPathResource("test/", getClass())); + locations.add(new ClassPathResource("testalternatepath/", getClass())); Map urlMap = new HashMap(); handler = new ResourceHttpRequestHandler(); - handler.setLocations(resourcePaths); + handler.setLocations(locations); urlMap.put("/resources/**", handler); mapping = new SimpleUrlHandlerMapping(); mapping.setUrlMap(urlMap); } - private void resetMapper() { - mapper = new ResourceUrlMapper(); - mapper.postProcessAfterInitialization(mapping, "resourceMapping"); - mapper.onApplicationEvent(null); + private void initGenerator() { + generator = new ResourceUrlGenerator(); + generator.setResourceHandlerMappings(Collections.singletonList(this.mapping)); } @Test public void getStaticResourceUrl() { - resetMapper(); + initGenerator(); - String url = mapper.getUrlForResource("/resources/foo.css"); + String url = generator.getResourceUrl("/resources/foo.css"); assertEquals("/resources/foo.css", url); } @@ -77,9 +79,9 @@ public class ResourceUrlMapperTests { resolvers.add(new FingerprintResourceResolver()); resolvers.add(new PathResourceResolver()); handler.setResourceResolvers(resolvers); - resetMapper(); + initGenerator(); - String url = mapper.getUrlForResource("/resources/foo.css"); + String url = generator.getResourceUrl("/resources/foo.css"); assertEquals("/resources/foo-e36d2e05253c6c7085a91522ce43a0b4.css", url); } @@ -89,9 +91,9 @@ public class ResourceUrlMapperTests { resolvers.add(new PathExtensionResourceResolver()); resolvers.add(new PathResourceResolver()); handler.setResourceResolvers(resolvers); - resetMapper(); + initGenerator(); - String url = mapper.getUrlForResource("/resources/zoo.css"); + String url = generator.getResourceUrl("/resources/zoo.css"); assertEquals("/resources/zoo.css", url); }