Update MVC config to use CNM for static resources

The MVC config now plugs the configured ContentNegotiationManager into
resource request handling.

Issue: SPR-13658
This commit is contained in:
Rossen Stoyanchev
2016-03-04 16:01:35 -05:00
parent f162256906
commit ff2a911baa
8 changed files with 77 additions and 28 deletions

View File

@@ -178,4 +178,23 @@ abstract class MvcNamespaceUtils {
return new RuntimeBeanReference(CORS_CONFIGURATION_BEAN_NAME);
}
/**
* Find the {@code ContentNegotiationManager} bean created by or registered
* with the {@code annotation-driven} element.
* @return a bean definition, bean reference, or null.
*/
public static Object getContentNegotiationManager(ParserContext context) {
String name = AnnotationDrivenBeanDefinitionParser.HANDLER_MAPPING_BEAN_NAME;
if (context.getRegistry().containsBeanDefinition(name)) {
BeanDefinition handlerMappingBeanDef = context.getRegistry().getBeanDefinition(name);
return handlerMappingBeanDef.getPropertyValues().get("contentNegotiationManager");
}
name = AnnotationDrivenBeanDefinitionParser.CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
if (context.getRegistry().containsBeanDefinition(name)) {
return new RuntimeBeanReference(name);
}
return null;
}
}

View File

@@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit;
import org.w3c.dom.Element;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
@@ -165,17 +166,19 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
RootBeanDefinition resourceHandlerDef = new RootBeanDefinition(ResourceHttpRequestHandler.class);
resourceHandlerDef.setSource(source);
resourceHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
resourceHandlerDef.getPropertyValues().add("locations", locations);
MutablePropertyValues values = resourceHandlerDef.getPropertyValues();
values.add("locations", locations);
String cacheSeconds = element.getAttribute("cache-period");
if (StringUtils.hasText(cacheSeconds)) {
resourceHandlerDef.getPropertyValues().add("cacheSeconds", cacheSeconds);
values.add("cacheSeconds", cacheSeconds);
}
Element cacheControlElement = DomUtils.getChildElementByTagName(element, "cache-control");
if (cacheControlElement != null) {
CacheControl cacheControl = parseCacheControl(cacheControlElement);
resourceHandlerDef.getPropertyValues().add("cacheControl", cacheControl);
values.add("cacheControl", cacheControl);
}
Element resourceChainElement = DomUtils.getChildElementByTagName(element, "resource-chain");
@@ -183,6 +186,11 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
parseResourceChain(resourceHandlerDef, parserContext, resourceChainElement, source);
}
Object manager = MvcNamespaceUtils.getContentNegotiationManager(parserContext);
if (manager != null) {
values.add("contentNegotiationManager", manager);
}
String beanName = parserContext.getReaderContext().generateBeanName(resourceHandlerDef);
parserContext.getRegistry().registerBeanDefinition(beanName, resourceHandlerDef);
parserContext.registerComponent(new BeanComponentDefinition(resourceHandlerDef, beanName));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -22,7 +22,6 @@ import org.w3c.dom.Element;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.ManagedList;
@@ -192,24 +191,11 @@ public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser {
if (resolverElement.hasAttribute("use-not-acceptable")) {
values.add("useNotAcceptableStatusCode", resolverElement.getAttribute("use-not-acceptable"));
}
Object manager = getContentNegotiationManager(context);
Object manager = MvcNamespaceUtils.getContentNegotiationManager(context);
if (manager != null) {
values.add("contentNegotiationManager", manager);
}
return beanDef;
}
private Object getContentNegotiationManager(ParserContext context) {
String name = AnnotationDrivenBeanDefinitionParser.HANDLER_MAPPING_BEAN_NAME;
if (context.getRegistry().containsBeanDefinition(name)) {
BeanDefinition handlerMappingBeanDef = context.getRegistry().getBeanDefinition(name);
return handlerMappingBeanDef.getPropertyValues().get("contentNegotiationManager");
}
name = AnnotationDrivenBeanDefinitionParser.CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
if (context.getRegistry().containsBeanDefinition(name)) {
return new RuntimeBeanReference(name);
}
return null;
}
}

View File

@@ -27,6 +27,7 @@ import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
@@ -55,15 +56,23 @@ public class ResourceHandlerRegistry {
private final ApplicationContext appContext;
private final ContentNegotiationManager contentNegotiationManager;
private final List<ResourceHandlerRegistration> registrations = new ArrayList<ResourceHandlerRegistration>();
private int order = Integer.MAX_VALUE -1;
public ResourceHandlerRegistry(ApplicationContext applicationContext, ServletContext servletContext) {
this(applicationContext, servletContext, null);
}
public ResourceHandlerRegistry(ApplicationContext applicationContext, ServletContext servletContext,
ContentNegotiationManager contentNegotiationManager) {
Assert.notNull(applicationContext, "ApplicationContext is required");
this.appContext = applicationContext;
this.servletContext = servletContext;
this.contentNegotiationManager = contentNegotiationManager;
}
@@ -113,6 +122,7 @@ public class ResourceHandlerRegistry {
ResourceHttpRequestHandler handler = registration.getRequestHandler();
handler.setServletContext(this.servletContext);
handler.setApplicationContext(this.appContext);
handler.setContentNegotiationManager(this.contentNegotiationManager);
try {
handler.afterPropertiesSet();
}

View File

@@ -407,7 +407,8 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
*/
@Bean
public HandlerMapping resourceHandlerMapping() {
ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext, this.servletContext);
ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext,
this.servletContext, mvcContentNegotiationManager());
addResourceHandlers(registry);
AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();