Update resource handler XML Namespace
This change introduces a new <mvc:resource-chain/> tag that mirrors
the ResourceChainRegistration java config counterpart.
Resolvers and Transformers can be registered with bean/ref tags, and
specific tags have been created for <mvc:version-resovlver> and
<mvc:resource-cache> in order to make common configurations easier.
Note that a specific "auto-configuration" attribute on the
resource-chain allows to completely disable default registration of
Resolvers and Transformers (sane defaults considered by the Framework).
<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/">
<mvc:resource-chain>
<mvc:resource-cache cache="resourceCache"/>
<mvc:resolvers>
<mvc:version-resolver>
<mvc:fixed-version-strategy version="abc" patterns="/**/*.js"/>
<mvc:content-version-strategy patterns="/**"/>
</mvc:version-resolver>
</mvc:resolvers>
<mvc:transformers>
<bean class="org.springframework.web.servlet.resource.AppCacheManifestTransformer"/>
</mvc:transformers>
</mvc:resource-chain>
</mvc:resources>
This also fixes a typo in the class name of
AppCacheManifestResourceTransfo*r*mer.
Issue: SPR-12129
This commit is contained in:
@@ -22,6 +22,7 @@ import java.util.Map;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
@@ -29,25 +30,43 @@ import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
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.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
import org.springframework.web.servlet.resource.CachingResourceResolver;
|
||||
import org.springframework.web.servlet.resource.CachingResourceTransformer;
|
||||
import org.springframework.web.servlet.resource.ContentVersionStrategy;
|
||||
import org.springframework.web.servlet.resource.CssLinkResourceTransformer;
|
||||
import org.springframework.web.servlet.resource.FixedVersionStrategy;
|
||||
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;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses a
|
||||
* {@code resources} element to register a {@link ResourceHttpRequestHandler}.
|
||||
* Will also register a {@link SimpleUrlHandlerMapping} for mapping resource requests,
|
||||
* {@code resources} element to register a {@link ResourceHttpRequestHandler} and
|
||||
* register a {@link SimpleUrlHandlerMapping} for mapping resource requests,
|
||||
* and a {@link HttpRequestHandlerAdapter}.
|
||||
* Will also create a resource handling chain with {@link ResourceResolver}s and {@link ResourceTransformer}s.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Jeremy Grelle
|
||||
* @author Brian Clozel
|
||||
* @since 3.0.4
|
||||
*/
|
||||
class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String RESOURCE_CHAIN_CACHE = "spring-resource-chain-cache";
|
||||
private static final String VERSION_RESOLVER_ELEMENT = "version-resolver";
|
||||
private static final String VERSION_STRATEGY_ELEMENT = "version-strategy";
|
||||
private static final String FIXED_VERSION_STRATEGY_ELEMENT = "fixed-version-strategy";
|
||||
private static final String CONTENT_VERSION_STRATEGY_ELEMENT = "content-version-strategy";
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
@@ -109,14 +128,9 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
||||
resourceHandlerDef.getPropertyValues().add("cacheSeconds", cacheSeconds);
|
||||
}
|
||||
|
||||
ManagedList<? super Object> resourceResolvers = parseResourceResolvers(parserContext, element, source);
|
||||
if (!resourceResolvers.isEmpty()) {
|
||||
resourceHandlerDef.getPropertyValues().add("resourceResolvers", resourceResolvers);
|
||||
}
|
||||
|
||||
ManagedList<? super Object> resourceTransformers = parseResourceTransformers(parserContext, element, source);
|
||||
if (!resourceTransformers.isEmpty()) {
|
||||
resourceHandlerDef.getPropertyValues().add("resourceTransformers", resourceTransformers);
|
||||
Element resourceChainElement = DomUtils.getChildElementByTagName(element, "resource-chain");
|
||||
if(resourceChainElement != null) {
|
||||
parseResourceChain(resourceHandlerDef, parserContext, resourceChainElement, source);
|
||||
}
|
||||
|
||||
String beanName = parserContext.getReaderContext().generateBeanName(resourceHandlerDef);
|
||||
@@ -125,30 +139,145 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
||||
return beanName;
|
||||
}
|
||||
|
||||
private ManagedList<? super Object> parseResourceResolvers(ParserContext parserContext, Element element, Object source) {
|
||||
Element resolversElement = DomUtils.getChildElementByTagName(element, "resolvers");
|
||||
|
||||
private void parseResourceChain(RootBeanDefinition resourceHandlerDef, ParserContext parserContext,
|
||||
Element element, Object source) {
|
||||
|
||||
String autoRegistration = element.getAttribute("auto-registration");
|
||||
boolean isAutoRegistration = !(StringUtils.hasText(autoRegistration) && "false".equals(autoRegistration));
|
||||
|
||||
ManagedList<? super Object> resourceResolvers = new ManagedList<Object>();
|
||||
if (resolversElement != null) {
|
||||
resourceResolvers.setSource(source);
|
||||
for (Element beanElement : DomUtils.getChildElementsByTagName(resolversElement, "bean", "ref")) {
|
||||
Object object = parserContext.getDelegate().parsePropertySubElement(beanElement, null);
|
||||
resourceResolvers.add(object);
|
||||
}
|
||||
resourceResolvers.setSource(source);
|
||||
ManagedList<? super Object> resourceTransformers = new ManagedList<Object>();
|
||||
resourceTransformers.setSource(source);
|
||||
|
||||
parseResourceCache(resourceResolvers, resourceTransformers, element, source);
|
||||
parseResourceResolversTransformers(isAutoRegistration, resourceResolvers
|
||||
, resourceTransformers, parserContext, element, source);
|
||||
|
||||
if (!resourceResolvers.isEmpty()) {
|
||||
resourceHandlerDef.getPropertyValues().add("resourceResolvers", resourceResolvers);
|
||||
}
|
||||
if (!resourceTransformers.isEmpty()) {
|
||||
resourceHandlerDef.getPropertyValues().add("resourceTransformers", resourceTransformers);
|
||||
}
|
||||
return resourceResolvers;
|
||||
}
|
||||
|
||||
private ManagedList<? super Object> parseResourceTransformers(ParserContext parserContext, Element element, Object source) {
|
||||
private void parseResourceCache(ManagedList<? super Object> resourceResolvers,
|
||||
ManagedList<? super Object> resourceTransformers,
|
||||
Element element, Object source) {
|
||||
|
||||
Element resourceCacheElement = DomUtils.getChildElementByTagName(element, "resource-cache");
|
||||
if(resourceCacheElement != null) {
|
||||
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
|
||||
|
||||
RootBeanDefinition cachingResolverDef = new RootBeanDefinition(CachingResourceResolver.class);
|
||||
cachingResolverDef.setSource(source);
|
||||
cachingResolverDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
cachingResolverDef.setConstructorArgumentValues(cavs);
|
||||
|
||||
RootBeanDefinition cachingTransformerDef = new RootBeanDefinition(CachingResourceTransformer.class);
|
||||
cachingTransformerDef.setSource(source);
|
||||
cachingTransformerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
cachingTransformerDef.setConstructorArgumentValues(cavs);
|
||||
|
||||
String cacheBeanName = resourceCacheElement.getAttribute("cache");
|
||||
if (StringUtils.hasText(cacheBeanName)) {
|
||||
RuntimeBeanReference cacheRef = new RuntimeBeanReference(cacheBeanName);
|
||||
cavs.addIndexedArgumentValue(0, cacheRef);
|
||||
}
|
||||
else {
|
||||
ConstructorArgumentValues cacheCavs = new ConstructorArgumentValues();
|
||||
cacheCavs.addIndexedArgumentValue(0, RESOURCE_CHAIN_CACHE);
|
||||
|
||||
RootBeanDefinition cacheDef = new RootBeanDefinition(ConcurrentMapCache.class);
|
||||
cacheDef.setSource(source);
|
||||
cacheDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
cacheDef.setConstructorArgumentValues(cacheCavs);
|
||||
cavs.addIndexedArgumentValue(0, cacheDef);
|
||||
}
|
||||
resourceResolvers.add(cachingResolverDef);
|
||||
resourceTransformers.add(cachingTransformerDef);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void parseResourceResolversTransformers(boolean isAutoRegistration,
|
||||
ManagedList<? super Object> resourceResolvers, ManagedList<? super Object> resourceTransformers,
|
||||
ParserContext parserContext, Element element, Object source) {
|
||||
|
||||
Element resolversElement = DomUtils.getChildElementByTagName(element, "resolvers");
|
||||
if (resolversElement != null) {
|
||||
for (Element beanElement : DomUtils.getChildElements(resolversElement)) {
|
||||
if(VERSION_RESOLVER_ELEMENT.equals(beanElement.getLocalName())) {
|
||||
RootBeanDefinition versionResolverDef = parseVersionResolver(parserContext, beanElement, source);
|
||||
versionResolverDef.setSource(source);
|
||||
resourceResolvers.add(versionResolverDef);
|
||||
|
||||
if(isAutoRegistration) {
|
||||
RootBeanDefinition cssLinkTransformerDef = new RootBeanDefinition(CssLinkResourceTransformer.class);
|
||||
cssLinkTransformerDef.setSource(source);
|
||||
cssLinkTransformerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
resourceTransformers.add(cssLinkTransformerDef);
|
||||
}
|
||||
} else {
|
||||
Object object = parserContext.getDelegate().parsePropertySubElement(beanElement, null);
|
||||
resourceResolvers.add(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isAutoRegistration) {
|
||||
RootBeanDefinition pathResolverDef = new RootBeanDefinition(PathResourceResolver.class);
|
||||
pathResolverDef.setSource(source);
|
||||
pathResolverDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
resourceResolvers.add(pathResolverDef);
|
||||
}
|
||||
|
||||
Element transformersElement = DomUtils.getChildElementByTagName(element, "transformers");
|
||||
ManagedList<? super Object> resourceTransformers = new ManagedList<Object>();
|
||||
if (transformersElement != null) {
|
||||
resourceTransformers.setSource(source);
|
||||
for (Element beanElement : DomUtils.getChildElementsByTagName(transformersElement, "bean", "ref")) {
|
||||
Object object = parserContext.getDelegate().parsePropertySubElement(beanElement, null);
|
||||
resourceTransformers.add(object);
|
||||
}
|
||||
}
|
||||
return resourceTransformers;
|
||||
}
|
||||
|
||||
private RootBeanDefinition parseVersionResolver(ParserContext parserContext, Element element, Object source) {
|
||||
ManagedMap<String, ? super Object> strategyMap = new ManagedMap<String, Object>();
|
||||
strategyMap.setSource(source);
|
||||
RootBeanDefinition versionResolverDef = new RootBeanDefinition(VersionResourceResolver.class);
|
||||
versionResolverDef.setSource(source);
|
||||
versionResolverDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
versionResolverDef.getPropertyValues().addPropertyValue("strategyMap", strategyMap);
|
||||
|
||||
for (Element beanElement : DomUtils.getChildElements(element)) {
|
||||
String[] patterns = StringUtils.commaDelimitedListToStringArray(beanElement.getAttribute("patterns"));
|
||||
Object strategy = null;
|
||||
if(FIXED_VERSION_STRATEGY_ELEMENT.equals(beanElement.getLocalName())) {
|
||||
ConstructorArgumentValues cavs = new ConstructorArgumentValues();
|
||||
cavs.addIndexedArgumentValue(0, beanElement.getAttribute("version"));
|
||||
RootBeanDefinition strategyDef = new RootBeanDefinition(FixedVersionStrategy.class);
|
||||
strategyDef.setSource(source);
|
||||
strategyDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
strategyDef.setConstructorArgumentValues(cavs);
|
||||
strategy = strategyDef;
|
||||
}
|
||||
else if (CONTENT_VERSION_STRATEGY_ELEMENT.equals(beanElement.getLocalName())) {
|
||||
RootBeanDefinition strategyDef = new RootBeanDefinition(ContentVersionStrategy.class);
|
||||
strategyDef.setSource(source);
|
||||
strategyDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
strategy = strategyDef;
|
||||
}
|
||||
else if (VERSION_STRATEGY_ELEMENT.equals(beanElement.getLocalName())) {
|
||||
Element childElement = DomUtils.getChildElementsByTagName(beanElement, "bean", "ref").get(0);
|
||||
strategy = parserContext.getDelegate().parsePropertySubElement(childElement, null);
|
||||
}
|
||||
for(String pattern : patterns) {
|
||||
strategyMap.put(pattern, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
return versionResolverDef;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,13 +58,13 @@ import org.springframework.util.StringUtils;
|
||||
* applications spec</a>
|
||||
* @since 4.1
|
||||
*/
|
||||
public class AppCacheManifestTransfomer implements ResourceTransformer {
|
||||
public class AppCacheManifestTransformer implements ResourceTransformer {
|
||||
|
||||
private static final String MANIFEST_HEADER = "CACHE MANIFEST";
|
||||
|
||||
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AppCacheManifestTransfomer.class);
|
||||
private static final Log logger = LogFactory.getLog(AppCacheManifestTransformer.class);
|
||||
|
||||
private final Map<String, SectionTransformer> sectionTransformers = new HashMap<String, SectionTransformer>();
|
||||
|
||||
@@ -74,7 +74,7 @@ public class AppCacheManifestTransfomer implements ResourceTransformer {
|
||||
/**
|
||||
* Create an AppCacheResourceTransformer that transforms files with extension ".manifest"
|
||||
*/
|
||||
public AppCacheManifestTransfomer() {
|
||||
public AppCacheManifestTransformer() {
|
||||
this("manifest");
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class AppCacheManifestTransfomer implements ResourceTransformer {
|
||||
* Create an AppCacheResourceTransformer that transforms files with the extension
|
||||
* given as a parameter.
|
||||
*/
|
||||
public AppCacheManifestTransfomer(String fileExtension) {
|
||||
public AppCacheManifestTransformer(String fileExtension) {
|
||||
this.fileExtension = fileExtension;
|
||||
|
||||
SectionTransformer noOpSection = new NoOpSection();
|
||||
@@ -338,6 +338,77 @@
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="resource-cache">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.web.servlet.resource.CachingResourceResolver"><![CDATA[
|
||||
A ResourceResolver that resolves resources from a Cache or otherwise delegates to the resolver chain
|
||||
and saves the result in the cache. Can use a custom Cache if provided as a bean reference in the "cache" attribute.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="cache" type="xsd:string" use="optional"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="content-version-strategy">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.web.servlet.resource.ContentVersionStrategy"><![CDATA[
|
||||
A VersionStrategy that calculates an Hex MD5 hashes from the content of the resource and appends it
|
||||
to the file name, e.g. "styles/main-e36d2e05253c6c7085a91522ce43a0b4.css".
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="patterns" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="fixed-version-strategy">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.web.servlet.resource.FixedVersionStrategy"><![CDATA[
|
||||
A VersionStrategy that relies on a fixed version applied as a request path prefix,
|
||||
e.g. reduced SHA, version name, release date, etc.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="version" type="xsd:string" use="required" />
|
||||
<xsd:attribute name="patterns" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="resource-version-strategy">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.web.servlet.resource.VersionStrategy"><![CDATA[
|
||||
A strategy for extracting and embedding a resource version in its URL path.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:choice minOccurs="1" maxOccurs="1">
|
||||
<xsd:element ref="beans:bean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.web.servlet.resource.VersionStrategy"><![CDATA[
|
||||
A VersionStrategy bean definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element ref="beans:ref">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.web.servlet.resource.VersionStrategy"><![CDATA[
|
||||
A reference to a VersionStrategy bean.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="patterns" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="version-resolver">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.web.servlet.resource.VersionResourceResolver"><![CDATA[
|
||||
Resolves request paths containing a version string that can be used as part of an HTTP caching strategy
|
||||
in which a resource is cached with a far future date (e.g. 1 year) and cached until the version,
|
||||
and therefore the URL, is changed.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element type="content-version-strategy" name="content-version-strategy" />
|
||||
<xsd:element type="fixed-version-strategy" name="fixed-version-strategy" />
|
||||
<xsd:element type="resource-version-strategy" name="version-strategy" />
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="resource-resolvers">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.web.servlet.resource.ResourceResolver"><![CDATA[
|
||||
@@ -348,6 +419,7 @@
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element type="version-resolver" name="version-resolver" />
|
||||
<xsd:element ref="beans:bean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.web.servlet.resource.ResourceResolver"><![CDATA[
|
||||
@@ -393,6 +465,22 @@
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="resource-chain">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="org.springframework.web.servlet.config.annotation.ResourceChainRegistration"><![CDATA[
|
||||
Assists with the registration of resource resolvers and transformers.
|
||||
Unless set to "false", the auto-registration add default Resolvers (a PathResourceResolver) and Transformers
|
||||
(CssLinkResourceTransformer, if a VersionResourceResolver has been manually registered).
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="resource-cache" type="resource-cache" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="resolvers" type="resource-resolvers" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="transformers" type="resource-transformers" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="auto-registration" type="xsd:boolean" default="true" use="optional"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="resources">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation
|
||||
@@ -403,8 +491,7 @@
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="resolvers" type="resource-resolvers" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="transformers" type="resource-transformers" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="resource-chain" type="resource-chain" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="mapping" use="required" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.web.servlet.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -30,6 +32,7 @@ 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.concurrent.ConcurrentMapCache;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
@@ -76,14 +79,19 @@ import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||
import org.springframework.web.servlet.resource.AppCacheManifestTransformer;
|
||||
import org.springframework.web.servlet.resource.CachingResourceResolver;
|
||||
import org.springframework.web.servlet.resource.CachingResourceTransformer;
|
||||
import org.springframework.web.servlet.resource.ContentVersionStrategy;
|
||||
import org.springframework.web.servlet.resource.CssLinkResourceTransformer;
|
||||
import org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler;
|
||||
import org.springframework.web.servlet.resource.FixedVersionStrategy;
|
||||
import org.springframework.web.servlet.resource.GzipResourceResolver;
|
||||
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.theme.ThemeChangeInterceptor;
|
||||
import org.springframework.web.servlet.view.groovy.GroovyMarkupConfigurer;
|
||||
import org.springframework.web.servlet.view.groovy.GroovyMarkupViewResolver;
|
||||
@@ -96,8 +104,6 @@ import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
|
||||
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
|
||||
import org.springframework.web.servlet.view.velocity.VelocityViewResolver;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests loading actual MVC namespace configuration.
|
||||
*
|
||||
@@ -328,7 +334,7 @@ public class MvcNamespaceTests {
|
||||
|
||||
@Test
|
||||
public void testResourcesWithResolversTransformers() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-resources-resolvers-transformers.xml", 10);
|
||||
loadBeanDefinitions("mvc-config-resources-chain.xml", 8);
|
||||
|
||||
SimpleUrlHandlerMapping mapping = appContext.getBean(SimpleUrlHandlerMapping.class);
|
||||
assertNotNull(mapping);
|
||||
@@ -338,14 +344,54 @@ public class MvcNamespaceTests {
|
||||
assertNotNull(handler);
|
||||
|
||||
List<ResourceResolver> resolvers = handler.getResourceResolvers();
|
||||
assertThat(resolvers, Matchers.hasSize(2));
|
||||
assertThat(resolvers.get(0), Matchers.instanceOf(PathResourceResolver.class));
|
||||
assertThat(resolvers, Matchers.hasSize(3));
|
||||
assertThat(resolvers.get(0), Matchers.instanceOf(CachingResourceResolver.class));
|
||||
assertThat(resolvers.get(1), Matchers.instanceOf(VersionResourceResolver.class));
|
||||
assertThat(resolvers.get(2), Matchers.instanceOf(PathResourceResolver.class));
|
||||
|
||||
CachingResourceResolver cachingResolver = (CachingResourceResolver) resolvers.get(0);
|
||||
assertThat(cachingResolver.getCache(), Matchers.instanceOf(TestResourceCache.class));
|
||||
|
||||
VersionResourceResolver versionResolver = (VersionResourceResolver) resolvers.get(1);
|
||||
assertThat(versionResolver.getStrategyMap().get("/**/*.js"),
|
||||
Matchers.instanceOf(FixedVersionStrategy.class));
|
||||
assertThat(versionResolver.getStrategyMap().get("/**"),
|
||||
Matchers.instanceOf(ContentVersionStrategy.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(AppCacheManifestTransformer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourcesWithResolversTransformersCustom() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-resources-chain-no-auto.xml", 9);
|
||||
|
||||
SimpleUrlHandlerMapping mapping = appContext.getBean(SimpleUrlHandlerMapping.class);
|
||||
assertNotNull(mapping);
|
||||
assertNotNull(mapping.getUrlMap().get("/resources/**"));
|
||||
ResourceHttpRequestHandler handler = appContext.getBean((String)mapping.getUrlMap().get("/resources/**"),
|
||||
ResourceHttpRequestHandler.class);
|
||||
assertNotNull(handler);
|
||||
|
||||
List<ResourceResolver> resolvers = handler.getResourceResolvers();
|
||||
assertThat(resolvers, Matchers.hasSize(3));
|
||||
assertThat(resolvers.get(0), Matchers.instanceOf(VersionResourceResolver.class));
|
||||
assertThat(resolvers.get(1), Matchers.instanceOf(GzipResourceResolver.class));
|
||||
assertThat(resolvers.get(2), Matchers.instanceOf(PathResourceResolver.class));
|
||||
|
||||
VersionResourceResolver versionResolver = (VersionResourceResolver) resolvers.get(0);
|
||||
assertThat(versionResolver.getStrategyMap().get("/**/*.js"),
|
||||
Matchers.instanceOf(FixedVersionStrategy.class));
|
||||
assertThat(versionResolver.getStrategyMap().get("/**"),
|
||||
Matchers.instanceOf(ContentVersionStrategy.class));
|
||||
|
||||
List<ResourceTransformer> transformers = handler.getResourceTransformers();
|
||||
assertThat(transformers, Matchers.hasSize(2));
|
||||
assertThat(transformers.get(0), Matchers.instanceOf(CachingResourceTransformer.class));
|
||||
assertThat(transformers.get(1), Matchers.instanceOf(CssLinkResourceTransformer.class));
|
||||
assertThat(transformers.get(1), Matchers.instanceOf(AppCacheManifestTransformer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -823,5 +869,11 @@ public class MvcNamespaceTests {
|
||||
|
||||
public static class TestPathHelper extends UrlPathHelper { }
|
||||
|
||||
public static class TestResourceCache extends ConcurrentMapCache {
|
||||
public TestResourceCache(String name) {
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ 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.AppCacheManifestTransformer;
|
||||
import org.springframework.web.servlet.resource.CachingResourceResolver;
|
||||
import org.springframework.web.servlet.resource.CachingResourceTransformer;
|
||||
import org.springframework.web.servlet.resource.CssLinkResourceTransformer;
|
||||
@@ -145,7 +145,7 @@ public class ResourceHandlerRegistryTests {
|
||||
.addContentVersionStrategy("/**");
|
||||
|
||||
this.registration.resourceChain(true).addResolver(versionResolver)
|
||||
.addTransformer(new AppCacheManifestTransfomer());
|
||||
.addTransformer(new AppCacheManifestTransformer());
|
||||
|
||||
ResourceHttpRequestHandler handler = getHandler("/resources/**");
|
||||
List<ResourceResolver> resolvers = handler.getResourceResolvers();
|
||||
@@ -158,7 +158,7 @@ public class ResourceHandlerRegistryTests {
|
||||
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));
|
||||
assertThat(transformers.get(2), Matchers.instanceOf(AppCacheManifestTransformer.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -167,7 +167,7 @@ public class ResourceHandlerRegistryTests {
|
||||
VersionResourceResolver versionResolver = Mockito.mock(VersionResourceResolver.class);
|
||||
PathResourceResolver pathResourceResolver = new PathResourceResolver();
|
||||
CachingResourceTransformer cachingTransformer = Mockito.mock(CachingResourceTransformer.class);
|
||||
AppCacheManifestTransfomer appCacheTransformer = Mockito.mock(AppCacheManifestTransfomer.class);
|
||||
AppCacheManifestTransformer appCacheTransformer = Mockito.mock(AppCacheManifestTransformer.class);
|
||||
CssLinkResourceTransformer cssLinkTransformer = new CssLinkResourceTransformer();
|
||||
|
||||
this.registration.setCachePeriod(3600)
|
||||
|
||||
@@ -34,13 +34,13 @@ import static org.mockito.BDDMockito.*;
|
||||
|
||||
/**
|
||||
* Unit tests for
|
||||
* {@link AppCacheManifestTransfomer}.
|
||||
* {@link AppCacheManifestTransformer}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public class AppCacheManifestTransformerTests {
|
||||
|
||||
private AppCacheManifestTransfomer transformer;
|
||||
private AppCacheManifestTransformer transformer;
|
||||
|
||||
private ResourceTransformerChain chain;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class AppCacheManifestTransformerTests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.transformer = new AppCacheManifestTransfomer();
|
||||
this.transformer = new AppCacheManifestTransformer();
|
||||
this.chain = mock(ResourceTransformerChain.class);
|
||||
this.request = mock(HttpServletRequest.class);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/">
|
||||
<mvc:resource-chain auto-registration="false">
|
||||
<mvc:resolvers>
|
||||
<mvc:version-resolver>
|
||||
<mvc:fixed-version-strategy version="abc" patterns="/**/*.js"/>
|
||||
<mvc:version-strategy patterns="/**">
|
||||
<bean class="org.springframework.web.servlet.resource.ContentVersionStrategy" />
|
||||
</mvc:version-strategy>
|
||||
</mvc:version-resolver>
|
||||
<ref bean="gzipResourceResolver"/>
|
||||
<bean class="org.springframework.web.servlet.resource.PathResourceResolver"/>
|
||||
</mvc:resolvers>
|
||||
<mvc:transformers>
|
||||
<bean class="org.springframework.web.servlet.resource.CachingResourceTransformer">
|
||||
<constructor-arg name="cache" ref="resourceCache" />
|
||||
</bean>
|
||||
<bean class="org.springframework.web.servlet.resource.AppCacheManifestTransformer"/>
|
||||
</mvc:transformers>
|
||||
</mvc:resource-chain>
|
||||
</mvc:resources>
|
||||
|
||||
<bean id="gzipResourceResolver" class="org.springframework.web.servlet.resource.GzipResourceResolver" />
|
||||
<bean id="resourceCache" class="org.springframework.cache.concurrent.ConcurrentMapCache">
|
||||
<constructor-arg name="name" value="resourceCache"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2002-2014 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.
|
||||
-->
|
||||
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/">
|
||||
<mvc:resource-chain>
|
||||
<mvc:resource-cache cache="resourceCache"/>
|
||||
<mvc:resolvers>
|
||||
<mvc:version-resolver>
|
||||
<mvc:fixed-version-strategy version="abc" patterns="/**/*.js"/>
|
||||
<mvc:content-version-strategy patterns="/**"/>
|
||||
</mvc:version-resolver>
|
||||
</mvc:resolvers>
|
||||
<mvc:transformers>
|
||||
<bean class="org.springframework.web.servlet.resource.AppCacheManifestTransformer"/>
|
||||
</mvc:transformers>
|
||||
</mvc:resource-chain>
|
||||
</mvc:resources>
|
||||
|
||||
<bean id="resourceCache" class="org.springframework.web.servlet.config.MvcNamespaceTests$TestResourceCache">
|
||||
<constructor-arg name="name" value="resourceCache"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
|
||||
<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/">
|
||||
<mvc:resolvers>
|
||||
<bean class="org.springframework.web.servlet.resource.PathResourceResolver"/>
|
||||
<ref bean="gzipResourceResolver" />
|
||||
</mvc:resolvers>
|
||||
<mvc:transformers>
|
||||
<ref bean="cachingResourceTransformer" />
|
||||
<bean class="org.springframework.web.servlet.resource.CssLinkResourceTransformer" />
|
||||
</mvc:transformers>
|
||||
</mvc:resources>
|
||||
|
||||
<bean id="gzipResourceResolver" class="org.springframework.web.servlet.resource.GzipResourceResolver" />
|
||||
<bean id="resourceCache" class="org.springframework.cache.concurrent.ConcurrentMapCache">
|
||||
<constructor-arg name="name" value="resourceCache"/>
|
||||
</bean>
|
||||
<bean id="cachingResourceTransformer" class="org.springframework.web.servlet.resource.CachingResourceTransformer">
|
||||
<constructor-arg name="cache" ref="resourceCache" />
|
||||
</bean>
|
||||
</beans>
|
||||
Reference in New Issue
Block a user