Update ResourceHandlerReg. API for Resource handling

This change adds new methods in the ResourceHandlerRegistration API
for registering ResourceResolvers and ResourceTransformers, allowing
to better handle server-side resources in web applications.i

Here is an example of configuration for an HTML5 web application
that uses JavaScript and HTML5 appcache manifests:

    registry.addResourceHandler("/**")
      .addResourceLocations("classpath:static/")
      .addTransformer(new AppCacheManifestTransfomer())
      .addVersion("v1", "/**/*.js")
      .addVersionHash("/**");

Issue: SPR-11982
This commit is contained in:
Brian Clozel
2014-07-10 23:53:37 +02:00
committed by Brian Clozel
parent 7d1e33d88d
commit 95e9b380d3
4 changed files with 283 additions and 65 deletions

View File

@@ -16,20 +16,32 @@
package org.springframework.web.servlet.config.annotation;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.cache.concurrent.ConcurrentMapCache;
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.support.GenericWebApplicationContext;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.resource.AppCacheManifestTransfomer;
import org.springframework.web.servlet.resource.CachingResourceResolver;
import org.springframework.web.servlet.resource.CachingResourceTransformer;
import org.springframework.web.servlet.resource.CssLinkResourceTransformer;
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;
import org.springframework.web.servlet.resource.VersionResourceResolver;
import org.springframework.web.servlet.resource.VersionStrategy;
import static org.junit.Assert.*;
@@ -96,18 +108,90 @@ public class ResourceHandlerRegistryTests {
}
@Test
public void resourceResolversAndTransformers() {
ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
this.registry.setResourceResolvers(resolver);
public void simpleResourceChain() throws Exception {
ResourceTransformer transformer = Mockito.mock(ResourceTransformer.class);
this.registry.setResourceTransformers(transformer);
ResourceResolver mockResolver = Mockito.mock(ResourceResolver.class);
ResourceTransformer mockTransformer = Mockito.mock(ResourceTransformer.class);
this.registration.addResolver(mockResolver).addTransformer(mockTransformer);
SimpleUrlHandlerMapping hm = (SimpleUrlHandlerMapping) this.registry.getHandlerMapping();
ResourceHttpRequestHandler handler = (ResourceHttpRequestHandler) hm.getUrlMap().values().iterator().next();
ResourceHttpRequestHandler handler = getHandler("/resources/**");
List<ResourceResolver> resolvers = handler.getResourceResolvers();
assertThat(resolvers, Matchers.hasSize(3));
assertThat(resolvers.get(0), Matchers.instanceOf(CachingResourceResolver.class));
CachingResourceResolver cachingResolver = (CachingResourceResolver) resolvers.get(0);
assertThat(cachingResolver.getCache(), Matchers.instanceOf(ConcurrentMapCache.class));
assertThat(resolvers.get(1), Matchers.equalTo(mockResolver));
assertThat(resolvers.get(2), Matchers.instanceOf(PathResourceResolver.class));
assertEquals(Arrays.asList(resolver), handler.getResourceResolvers());
assertEquals(Arrays.asList(transformer), handler.getResourceTransformers());
List<ResourceTransformer> transformers = handler.getResourceTransformers();
assertThat(transformers, Matchers.hasSize(2));
assertThat(transformers.get(0), Matchers.instanceOf(CachingResourceTransformer.class));
assertThat(transformers.get(1), Matchers.equalTo(mockTransformer));
}
@Test
public void noCacheResourceChain() throws Exception {
this.registration.enableDevMode();
ResourceHttpRequestHandler handler = getHandler("/resources/**");
List<ResourceResolver> resolvers = handler.getResourceResolvers();
assertThat(resolvers, Matchers.hasSize(1));
assertThat(resolvers.get(0), Matchers.instanceOf(PathResourceResolver.class));
List<ResourceTransformer> transformers = handler.getResourceTransformers();
assertThat(transformers, Matchers.hasSize(0));
}
@Test
public void versionResourceChain() throws Exception {
this.registration
.addTransformer(new AppCacheManifestTransfomer())
.addVersion("fixed", "/**/*.js")
.addVersionHash("/**");
ResourceHttpRequestHandler handler = getHandler("/resources/**");
List<ResourceResolver> resolvers = handler.getResourceResolvers();
assertThat(resolvers, Matchers.hasSize(3));
assertThat(resolvers.get(0), Matchers.instanceOf(CachingResourceResolver.class));
assertThat(resolvers.get(1), Matchers.instanceOf(VersionResourceResolver.class));
DirectFieldAccessor fieldAccessor = new DirectFieldAccessor(resolvers.get(1));
Map<String, VersionStrategy> strategies =
(Map<String, VersionStrategy>) fieldAccessor.getPropertyValue("versionStrategyMap");
assertNotNull(strategies.get("/**/*.js"));
assertNotNull(strategies.get("/**"));
assertThat(resolvers.get(2), Matchers.instanceOf(PathResourceResolver.class));
List<ResourceTransformer> transformers = handler.getResourceTransformers();
assertThat(transformers, Matchers.hasSize(3));
assertThat(transformers.get(0), Matchers.instanceOf(CachingResourceTransformer.class));
assertThat(transformers.get(1), Matchers.instanceOf(CssLinkResourceTransformer.class));
assertThat(transformers.get(2), Matchers.instanceOf(AppCacheManifestTransfomer.class));
}
@Test
public void customResourceChain() throws Exception {
CachingResourceResolver cachingResolver = Mockito.mock(CachingResourceResolver.class);
CachingResourceTransformer cachingTransformer = Mockito.mock(CachingResourceTransformer.class);
this.registration
.addTransformer(cachingTransformer)
.addTransformer(new AppCacheManifestTransfomer())
.addResolver(cachingResolver)
.addVersion("fixed", "/**/*.js")
.addVersionHash("/**")
.setCachePeriod(3600);
ResourceHttpRequestHandler handler = getHandler("/resources/**");
List<ResourceResolver> resolvers = handler.getResourceResolvers();
assertThat(resolvers, Matchers.hasSize(3));
assertThat(resolvers.get(0), Matchers.equalTo(cachingResolver));
assertThat(resolvers.get(1), Matchers.instanceOf(VersionResourceResolver.class));
assertThat(resolvers.get(2), Matchers.instanceOf(PathResourceResolver.class));
List<ResourceTransformer> transformers = handler.getResourceTransformers();
assertThat(transformers, Matchers.hasSize(3));
assertThat(transformers.get(0), Matchers.equalTo(cachingTransformer));
assertThat(transformers.get(1), Matchers.instanceOf(CssLinkResourceTransformer.class));
assertThat(transformers.get(2), Matchers.instanceOf(AppCacheManifestTransfomer.class));
}
private ResourceHttpRequestHandler getHandler(String pathPattern) {

View File

@@ -32,9 +32,6 @@ import org.springframework.web.servlet.config.annotation.*;
import static org.junit.Assert.*;
import java.util.HashMap;
import java.util.Map;
/**
* Integration tests using {@link ResourceUrlEncodingFilter} and
@@ -114,14 +111,9 @@ public class ResourceUrlProviderJavaConfigTests {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
Map<String, VersionStrategy> versionStrategyMap = new HashMap<>();
versionStrategyMap.put("/**", new ContentVersionStrategy());
VersionResourceResolver versionResolver = new VersionResourceResolver();
versionResolver.setStrategyMap(versionStrategyMap);
registry.addResourceHandler("/resources/**")
.addResourceLocations("classpath:org/springframework/web/servlet/resource/test/")
.setResourceResolvers(versionResolver, new PathResourceResolver());
.addVersionHash("/**");
}
}