Skip to content

Commit 77bbfb6

Browse files
committed
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.
1 parent 3b1d325 commit 77bbfb6

File tree

6 files changed

+84
-3
lines changed

6 files changed

+84
-3
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewResolversBeanDefinitionParser.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,17 @@ else if (contentnNegotiationElements.size() == 1) {
133133
beanDef.getPropertyValues().add("viewResolvers", resolvers);
134134
ManagedList<Object> list = new ManagedList<Object>(1);
135135
list.add(beanDef);
136-
137136
compositeResolverBeanDef.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
138137
compositeResolverBeanDef.getPropertyValues().add("viewResolvers", list);
139138
}
140139
else if (contentnNegotiationElements.size() > 1) {
141140
throw new IllegalArgumentException("Only one <content-negotiation> element is allowed.");
142141
}
143142

143+
if (element.hasAttribute("order")) {
144+
compositeResolverBeanDef.getPropertyValues().add("order", element.getAttribute("order"));
145+
}
146+
144147
context.getReaderContext().getRegistry().registerBeanDefinition(beanName, compositeResolverBeanDef);
145148
context.registerComponent(new BeanComponentDefinition(compositeResolverBeanDef, beanName));
146149
context.popAndRegisterContainingComponent();

spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistry.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public class ViewResolverRegistry {
5757

5858
private final List<ViewResolver> viewResolvers = new ArrayList<ViewResolver>(4);
5959

60-
private int order = Ordered.LOWEST_PRECEDENCE;
60+
private Integer order;
6161

6262
private ContentNegotiationManager contentNegotiationManager;
6363

@@ -112,7 +112,7 @@ public void enableContentNegotiation(boolean useNotAcceptableStatus, View... def
112112
private void initContentNegotiatingViewResolver(View[] defaultViews) {
113113

114114
// ContentNegotiatingResolver in the registry: elevate its precedence!
115-
this.order = Ordered.HIGHEST_PRECEDENCE;
115+
this.order = (this.order == null ? Ordered.HIGHEST_PRECEDENCE : this.order);
116116

117117
if (this.contentNegotiatingResolver != null) {
118118
if (!ObjectUtils.isEmpty(defaultViews)) {
@@ -257,6 +257,22 @@ public void viewResolver(ViewResolver viewResolver) {
257257
this.viewResolvers.add(viewResolver);
258258
}
259259

260+
/**
261+
* ViewResolver's registered through this registry are encapsulated in an
262+
* instance of {@link org.springframework.web.servlet.view.ViewResolverComposite
263+
* ViewResolverComposite} and follow the order of registration.
264+
* This property determines the order of the ViewResolverComposite itself
265+
* relative to any additional ViewResolver's (not registered here) present in
266+
* the Spring configuration
267+
* <p>By default this property is not set, which means the resolver is ordered
268+
* at {@link Ordered#LOWEST_PRECEDENCE} unless content negotiation is enabled
269+
* in which case the order (if not set explicitly) is changed to
270+
* {@link Ordered#HIGHEST_PRECEDENCE}.
271+
*/
272+
public void order(int order) {
273+
this.order = order;
274+
}
275+
260276
protected boolean hasBeanOfType(Class<?> beanType) {
261277
return !ObjectUtils.isEmpty(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
262278
this.applicationContext, beanType, false, false));

spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.1.xsd

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,20 @@
949949
</xsd:annotation>
950950
</xsd:element>
951951
</xsd:choice>
952+
<xsd:attribute name="order" type="xsd:int">
953+
<xsd:annotation>
954+
<xsd:documentation><![CDATA[
955+
ViewResolver's registered through this element are encapsulated in an
956+
instance of org.springframework.web.servlet.view.ViewResolverComposite and
957+
follow the order of registration. This attribute determines the order of the
958+
ViewResolverComposite itself relative to any additional ViewResolver's
959+
(not registered through this element) present in the Spring configuration
960+
By default this property is not set, which means the resolver is ordered at
961+
Ordered.LOWEST_PRECEDENCE unless content negotiation is enabled in which case
962+
the order (if not set explicitly) is changed to Ordered.HIGHEST_PRECEDENCE.
963+
]]></xsd:documentation>
964+
</xsd:annotation>
965+
</xsd:attribute>
952966
</xsd:complexType>
953967
</xsd:element>
954968

spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,16 @@ public void testViewResolutionWithContentNegotiation() throws Exception {
767767
assertSame(manager, this.appContext.getBean(ContentNegotiationManager.class));
768768
}
769769

770+
@Test
771+
public void testViewResolutionWithOrderSet() throws Exception {
772+
loadBeanDefinitions("mvc-config-view-resolution-custom-order.xml", 1);
773+
774+
ViewResolverComposite compositeResolver = this.appContext.getBean(ViewResolverComposite.class);
775+
assertNotNull(compositeResolver);
776+
assertEquals("Actual: " + compositeResolver.getViewResolvers(), 1, compositeResolver.getViewResolvers().size());
777+
assertEquals(123, compositeResolver.getOrder());
778+
}
779+
770780
@Test
771781
public void testPathMatchingHandlerMappings() throws Exception {
772782
loadBeanDefinitions("mvc-config-path-matching-mappings.xml", 22);

spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,20 @@ public void mvcViewResolverWithExistingResolver() throws Exception {
246246
assertNull(resolver.resolveViewName("anyViewName", Locale.ENGLISH));
247247
}
248248

249+
@Test
250+
public void mvcViewResolverWithOrderSet() {
251+
ApplicationContext context = initContext(CustomViewResolverOrderConfig.class);
252+
ViewResolverComposite resolver = context.getBean("mvcViewResolver", ViewResolverComposite.class);
253+
254+
Map<String, ViewResolver> map = BeanFactoryUtils.beansOfTypeIncludingAncestors(
255+
context, ViewResolver.class, true, false);
256+
257+
assertNotNull(resolver);
258+
assertEquals(1, resolver.getViewResolvers().size());
259+
assertEquals(InternalResourceViewResolver.class, resolver.getViewResolvers().get(0).getClass());
260+
assertEquals(123, resolver.getOrder());
261+
}
262+
249263
@Test
250264
public void defaultPathMatchConfiguration() throws Exception {
251265
ApplicationContext context = initContext(WebConfig.class);
@@ -286,6 +300,16 @@ public ViewResolver beanNameViewResolver() {
286300
}
287301
}
288302

303+
@EnableWebMvc
304+
@Configuration
305+
public static class CustomViewResolverOrderConfig extends WebMvcConfigurerAdapter {
306+
307+
@Override
308+
public void configureViewResolvers(ViewResolverRegistry registry) {
309+
registry.jsp();
310+
registry.order(123);
311+
}
312+
}
289313

290314
@Controller
291315
public static class TestController {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<beans xmlns="http://www.springframework.org/schema/beans"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:mvc="http://www.springframework.org/schema/mvc"
5+
xsi:schemaLocation="
6+
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
7+
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
8+
9+
<mvc:view-resolvers order="123">
10+
<mvc:bean-name />
11+
</mvc:view-resolvers>
12+
13+
</beans>
14+

0 commit comments

Comments
 (0)