From 77bbfb6e7ec16e2744f2c43bc12c9736fd6949cf Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 30 Sep 2014 10:36:39 -0400 Subject: [PATCH] Add order attribute to MVC ViewResolver config The ViewResolverComposite that contains the ViewResolver's registered throug the MVC Java config and namespace can now be assigned an explicit order. --- .../ViewResolversBeanDefinitionParser.java | 5 +++- .../annotation/ViewResolverRegistry.java | 20 ++++++++++++++-- .../web/servlet/config/spring-mvc-4.1.xsd | 14 +++++++++++ .../web/servlet/config/MvcNamespaceTests.java | 10 ++++++++ .../WebMvcConfigurationSupportTests.java | 24 +++++++++++++++++++ ...vc-config-view-resolution-custom-order.xml | 14 +++++++++++ 6 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-view-resolution-custom-order.xml diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java index fcce66e29b..2a7fbfe148 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java @@ -133,7 +133,6 @@ public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser { beanDef.getPropertyValues().add("viewResolvers", resolvers); ManagedList list = new ManagedList(1); list.add(beanDef); - compositeResolverBeanDef.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); compositeResolverBeanDef.getPropertyValues().add("viewResolvers", list); } @@ -141,6 +140,10 @@ public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser { throw new IllegalArgumentException("Only one element is allowed."); } + if (element.hasAttribute("order")) { + compositeResolverBeanDef.getPropertyValues().add("order", element.getAttribute("order")); + } + context.getReaderContext().getRegistry().registerBeanDefinition(beanName, compositeResolverBeanDef); context.registerComponent(new BeanComponentDefinition(compositeResolverBeanDef, beanName)); context.popAndRegisterContainingComponent(); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistry.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistry.java index 81108fb521..f70650bd0d 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistry.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistry.java @@ -57,7 +57,7 @@ public class ViewResolverRegistry { private final List viewResolvers = new ArrayList(4); - private int order = Ordered.LOWEST_PRECEDENCE; + private Integer order; private ContentNegotiationManager contentNegotiationManager; @@ -112,7 +112,7 @@ public class ViewResolverRegistry { private void initContentNegotiatingViewResolver(View[] defaultViews) { // ContentNegotiatingResolver in the registry: elevate its precedence! - this.order = Ordered.HIGHEST_PRECEDENCE; + this.order = (this.order == null ? Ordered.HIGHEST_PRECEDENCE : this.order); if (this.contentNegotiatingResolver != null) { if (!ObjectUtils.isEmpty(defaultViews)) { @@ -257,6 +257,22 @@ public class ViewResolverRegistry { this.viewResolvers.add(viewResolver); } + /** + * ViewResolver's registered through this registry are encapsulated in an + * instance of {@link org.springframework.web.servlet.view.ViewResolverComposite + * ViewResolverComposite} and follow the order of registration. + * This property determines the order of the ViewResolverComposite itself + * relative to any additional ViewResolver's (not registered here) present in + * the Spring configuration + *

By default this property is not set, which means the resolver is ordered + * at {@link Ordered#LOWEST_PRECEDENCE} unless content negotiation is enabled + * in which case the order (if not set explicitly) is changed to + * {@link Ordered#HIGHEST_PRECEDENCE}. + */ + public void order(int order) { + this.order = order; + } + protected boolean hasBeanOfType(Class beanType) { return !ObjectUtils.isEmpty(BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.applicationContext, beanType, false, false)); diff --git a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.1.xsd b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.1.xsd index 987d0f954b..037d85f9c8 100644 --- a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.1.xsd +++ b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.1.xsd @@ -949,6 +949,20 @@ + + + + + diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java index d712d62123..f9348deb2d 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java @@ -767,6 +767,16 @@ public class MvcNamespaceTests { assertSame(manager, this.appContext.getBean(ContentNegotiationManager.class)); } + @Test + public void testViewResolutionWithOrderSet() throws Exception { + loadBeanDefinitions("mvc-config-view-resolution-custom-order.xml", 1); + + ViewResolverComposite compositeResolver = this.appContext.getBean(ViewResolverComposite.class); + assertNotNull(compositeResolver); + assertEquals("Actual: " + compositeResolver.getViewResolvers(), 1, compositeResolver.getViewResolvers().size()); + assertEquals(123, compositeResolver.getOrder()); + } + @Test public void testPathMatchingHandlerMappings() throws Exception { loadBeanDefinitions("mvc-config-path-matching-mappings.xml", 22); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java index c6b0cf291c..4e08fcb677 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java @@ -246,6 +246,20 @@ public class WebMvcConfigurationSupportTests { assertNull(resolver.resolveViewName("anyViewName", Locale.ENGLISH)); } + @Test + public void mvcViewResolverWithOrderSet() { + ApplicationContext context = initContext(CustomViewResolverOrderConfig.class); + ViewResolverComposite resolver = context.getBean("mvcViewResolver", ViewResolverComposite.class); + + Map map = BeanFactoryUtils.beansOfTypeIncludingAncestors( + context, ViewResolver.class, true, false); + + assertNotNull(resolver); + assertEquals(1, resolver.getViewResolvers().size()); + assertEquals(InternalResourceViewResolver.class, resolver.getViewResolvers().get(0).getClass()); + assertEquals(123, resolver.getOrder()); + } + @Test public void defaultPathMatchConfiguration() throws Exception { ApplicationContext context = initContext(WebConfig.class); @@ -286,6 +300,16 @@ public class WebMvcConfigurationSupportTests { } } + @EnableWebMvc + @Configuration + public static class CustomViewResolverOrderConfig extends WebMvcConfigurerAdapter { + + @Override + public void configureViewResolvers(ViewResolverRegistry registry) { + registry.jsp(); + registry.order(123); + } + } @Controller public static class TestController { diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-view-resolution-custom-order.xml b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-view-resolution-custom-order.xml new file mode 100644 index 0000000000..5138c6b29b --- /dev/null +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-view-resolution-custom-order.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file