mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-10-04 05:59:12 +00:00
Further improve Detect custom CNVR
Refine the approach of having <mvc:view-resolvers> detect and use the ContentNegotiationManager instance registered with <mvc:annotation-driven> introduced in the last commit. Issue: SPR-13559
This commit is contained in:
+25
-20
@@ -34,6 +34,7 @@ import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.beans.factory.xml.XmlReaderContext;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
|
||||
@@ -147,6 +148,10 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv
|
||||
*/
|
||||
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
public static final String HANDLER_MAPPING_BEAN_NAME = RequestMappingHandlerMapping.class.getName();
|
||||
|
||||
public static final String HANDLER_ADAPTER_BEAN_NAME = RequestMappingHandlerAdapter.class.getName();
|
||||
|
||||
public static final String CONTENT_NEGOTIATION_MANAGER_BEAN_NAME = "mvcContentNegotiationManager";
|
||||
|
||||
private static final boolean javaxValidationPresent =
|
||||
@@ -172,6 +177,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
XmlReaderContext readerContext = parserContext.getReaderContext();
|
||||
|
||||
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);
|
||||
parserContext.pushContainingComponent(compDefinition);
|
||||
@@ -183,7 +189,6 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
handlerMappingDef.getPropertyValues().add("order", 0);
|
||||
handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
|
||||
String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef);
|
||||
|
||||
if (element.hasAttribute("enable-matrix-variables")) {
|
||||
Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
|
||||
@@ -195,6 +200,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
configurePathMatchingProperties(handlerMappingDef, element, parserContext);
|
||||
readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME , handlerMappingDef);
|
||||
|
||||
RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);
|
||||
RuntimeBeanReference validator = getValidator(element, source, parserContext);
|
||||
@@ -248,14 +254,14 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);
|
||||
handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);
|
||||
String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef);
|
||||
readerContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME , handlerAdapterDef);
|
||||
|
||||
String uriCompContribName = MvcUriComponentsBuilder.MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME;
|
||||
RootBeanDefinition uriCompContribDef = new RootBeanDefinition(CompositeUriComponentsContributorFactoryBean.class);
|
||||
uriCompContribDef.setSource(source);
|
||||
uriCompContribDef.getPropertyValues().addPropertyValue("handlerAdapter", handlerAdapterDef);
|
||||
uriCompContribDef.getPropertyValues().addPropertyValue("conversionService", conversionService);
|
||||
parserContext.getReaderContext().getRegistry().registerBeanDefinition(uriCompContribName, uriCompContribDef);
|
||||
readerContext.getRegistry().registerBeanDefinition(uriCompContribName, uriCompContribDef);
|
||||
|
||||
RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
|
||||
csInterceptorDef.setSource(source);
|
||||
@@ -265,7 +271,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
mappedCsInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
|
||||
mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, csInterceptorDef);
|
||||
String mappedInterceptorName = parserContext.getReaderContext().registerWithGeneratedName(mappedCsInterceptorDef);
|
||||
String mappedInterceptorName = readerContext.registerWithGeneratedName(mappedCsInterceptorDef);
|
||||
|
||||
RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
|
||||
exceptionHandlerExceptionResolver.setSource(source);
|
||||
@@ -275,25 +281,24 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);
|
||||
addResponseBodyAdvice(exceptionHandlerExceptionResolver);
|
||||
|
||||
String methodExceptionResolverName =
|
||||
parserContext.getReaderContext().registerWithGeneratedName(exceptionHandlerExceptionResolver);
|
||||
String methodExceptionResolverName = readerContext.registerWithGeneratedName(exceptionHandlerExceptionResolver);
|
||||
|
||||
RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);
|
||||
responseStatusExceptionResolver.setSource(source);
|
||||
responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
responseStatusExceptionResolver.getPropertyValues().add("order", 1);
|
||||
String responseStatusExceptionResolverName =
|
||||
parserContext.getReaderContext().registerWithGeneratedName(responseStatusExceptionResolver);
|
||||
readerContext.registerWithGeneratedName(responseStatusExceptionResolver);
|
||||
|
||||
RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
|
||||
defaultExceptionResolver.setSource(source);
|
||||
defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
defaultExceptionResolver.getPropertyValues().add("order", 2);
|
||||
String defaultExceptionResolverName =
|
||||
parserContext.getReaderContext().registerWithGeneratedName(defaultExceptionResolver);
|
||||
readerContext.registerWithGeneratedName(defaultExceptionResolver);
|
||||
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, methodMappingName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(uriCompContribDef, uriCompContribName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));
|
||||
parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));
|
||||
@@ -349,14 +354,13 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
}
|
||||
|
||||
private RuntimeBeanReference getContentNegotiationManager(Element element, Object source, ParserContext parserContext) {
|
||||
RuntimeBeanReference contentNegotiationManagerRef;
|
||||
private RuntimeBeanReference getContentNegotiationManager(Element element, Object source,
|
||||
ParserContext parserContext) {
|
||||
|
||||
RuntimeBeanReference beanRef;
|
||||
if (element.hasAttribute("content-negotiation-manager")) {
|
||||
String name = element.getAttribute("content-negotiation-manager");
|
||||
contentNegotiationManagerRef = new RuntimeBeanReference(name);
|
||||
if (!CONTENT_NEGOTIATION_MANAGER_BEAN_NAME.equals(name)) {
|
||||
parserContext.getRegistry().registerAlias(name, CONTENT_NEGOTIATION_MANAGER_BEAN_NAME);
|
||||
}
|
||||
beanRef = new RuntimeBeanReference(name);
|
||||
}
|
||||
else {
|
||||
RootBeanDefinition factoryBeanDef = new RootBeanDefinition(ContentNegotiationManagerFactoryBean.class);
|
||||
@@ -367,13 +371,14 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
|
||||
String name = CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
|
||||
parserContext.getReaderContext().getRegistry().registerBeanDefinition(name , factoryBeanDef);
|
||||
parserContext.registerComponent(new BeanComponentDefinition(factoryBeanDef, name));
|
||||
contentNegotiationManagerRef = new RuntimeBeanReference(name);
|
||||
beanRef = new RuntimeBeanReference(name);
|
||||
}
|
||||
return contentNegotiationManagerRef;
|
||||
return beanRef;
|
||||
}
|
||||
|
||||
private void configurePathMatchingProperties(RootBeanDefinition handlerMappingDef,
|
||||
Element element, ParserContext parserContext) {
|
||||
private void configurePathMatchingProperties(RootBeanDefinition handlerMappingDef, Element element,
|
||||
ParserContext parserContext) {
|
||||
|
||||
Element pathMatchingElement = DomUtils.getChildElementByTagName(element, "path-matching");
|
||||
if (pathMatchingElement != null) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
|
||||
+16
-3
@@ -185,11 +185,24 @@ public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser {
|
||||
if (resolverElement.hasAttribute("use-not-acceptable")) {
|
||||
values.add("useNotAcceptableStatusCode", resolverElement.getAttribute("use-not-acceptable"));
|
||||
}
|
||||
String name = AnnotationDrivenBeanDefinitionParser.CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
|
||||
if (context.getRegistry().containsBeanDefinition(name) || context.getRegistry().isAlias(name)) {
|
||||
values.add("contentNegotiationManager", new RuntimeBeanReference(name));
|
||||
Object manager = 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -680,7 +680,7 @@ public class MvcNamespaceTests {
|
||||
|
||||
@Test
|
||||
public void testContentNegotiationManager() throws Exception {
|
||||
loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 15);
|
||||
loadBeanDefinitions("mvc-config-content-negotiation-manager.xml", 14);
|
||||
|
||||
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
|
||||
ContentNegotiationManager manager = mapping.getContentNegotiationManager();
|
||||
|
||||
+2
-2
@@ -7,13 +7,13 @@
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
|
||||
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
|
||||
<mvc:annotation-driven content-negotiation-manager="mvcContentNegotiationManager" />
|
||||
|
||||
<mvc:view-resolvers>
|
||||
<mvc:content-negotiation/>
|
||||
</mvc:view-resolvers>
|
||||
|
||||
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
|
||||
<bean id="mvcContentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
|
||||
<property name="mediaTypes">
|
||||
<value>
|
||||
xml=application/rss+xml
|
||||
|
||||
Reference in New Issue
Block a user