From f54cee47b06c041c5c976ce23fc2079d70fad404 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Sat, 12 Jul 2014 16:52:02 -0400 Subject: [PATCH] Update ViewResolver registration classes Following the separation of FreeMarker/Velocity/TilesConfigurer-related configuration via separate interface, simplify and streamline the view registration helper classes which no longer have much difference (most are UrlBasedViewResolver's). Updates to Javadoc and tests. Issue: SPR-7093 --- .../samples/context/JavaConfigTests.java | 2 +- .../servlet/samples/spr/EncodedUriTests.java | 6 +- .../annotation/BeanNameRegistration.java | 34 -- .../ContentNegotiatingRegistration.java | 71 ----- .../DelegatingWebMvcConfiguration.java | 4 +- .../config/annotation/EnableWebMvc.java | 38 ++- .../annotation/FreeMarkerRegistration.java | 69 ----- .../config/annotation/JspRegistration.java | 40 --- .../config/annotation/TilesRegistration.java | 58 ---- .../UrlBasedViewResolverRegistration.java | 118 +++++++ .../annotation/VelocityRegistration.java | 69 ----- .../ViewResolutionRegistration.java | 48 --- .../annotation/ViewResolutionRegistry.java | 172 ----------- .../annotation/ViewResolverRegistry.java | 290 ++++++++++++++++++ .../WebMvcConfigurationSupport.java | 62 ++-- .../config/annotation/WebMvcConfigurer.java | 6 +- .../annotation/WebMvcConfigurerAdapter.java | 2 +- .../annotation/WebMvcConfigurerComposite.java | 4 +- .../WebMvcFreeMarkerConfiguration.java | 2 +- .../annotation/WebMvcTilesConfiguration.java | 2 +- .../WebMvcVelocityConfiguration.java | 2 +- .../view/ContentNegotiatingViewResolver.java | 8 + .../{ => view}/ViewResolverComposite.java | 82 +++-- .../ViewResolutionIntegrationTests.java | 24 +- .../ViewResolutionRegistryTests.java | 172 ----------- .../annotation/ViewResolverRegistryTests.java | 211 +++++++++++++ ...MvcConfigurationSupportExtensionTests.java | 85 ++--- .../WebMvcConfigurationSupportTests.java | 6 +- 28 files changed, 800 insertions(+), 887 deletions(-) delete mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/BeanNameRegistration.java delete mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ContentNegotiatingRegistration.java delete mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/FreeMarkerRegistration.java delete mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/JspRegistration.java delete mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/TilesRegistration.java create mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/UrlBasedViewResolverRegistration.java delete mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/VelocityRegistration.java delete mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistration.java delete mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistry.java create mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistry.java rename spring-webmvc/src/main/java/org/springframework/web/servlet/{ => view}/ViewResolverComposite.java (53%) delete mode 100644 spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistryTests.java create mode 100644 spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistryTests.java diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/JavaConfigTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/JavaConfigTests.java index 03b105a77e..fe246232b7 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/JavaConfigTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context/JavaConfigTests.java @@ -126,7 +126,7 @@ public class JavaConfigTests { } @Override - public void configureViewResolution(ViewResolutionRegistry registry) { + public void configureViewResolvers(ViewResolverRegistry registry) { registry.tiles(); } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/spr/EncodedUriTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/spr/EncodedUriTests.java index cf3e373c8d..9a62c789d8 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/spr/EncodedUriTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/spr/EncodedUriTests.java @@ -40,7 +40,7 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.ViewResolutionRegistry; +import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.util.UriComponentsBuilder; @@ -97,7 +97,7 @@ public class EncodedUriTests { } @Override - public void configureViewResolution(ViewResolutionRegistry registry) { + public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("", ""); } } @@ -121,9 +121,7 @@ public class EncodedUriTests { // URL decode after request mapping, not before. requestMappingHandlerMapping.setUrlDecode(false); - } - return bean; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/BeanNameRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/BeanNameRegistration.java deleted file mode 100644 index 9aff9fe1ee..0000000000 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/BeanNameRegistration.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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. - */ - -package org.springframework.web.servlet.config.annotation; - -import org.springframework.web.servlet.view.BeanNameViewResolver; - -/** - * Encapsulates information required to create a - * {@link org.springframework.web.servlet.view.BeanNameViewResolver} bean. - * - * @author Sebastien Deleuze - * @since 4.1 - */ -public class BeanNameRegistration extends ViewResolutionRegistration { - - public BeanNameRegistration(ViewResolutionRegistry registry) { - super(registry, new BeanNameViewResolver()); - } - -} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ContentNegotiatingRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ContentNegotiatingRegistration.java deleted file mode 100644 index 1bc875eb2a..0000000000 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ContentNegotiatingRegistration.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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. - */ - -package org.springframework.web.servlet.config.annotation; - -import org.springframework.web.servlet.View; -import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * Encapsulates information required to create a {@link ContentNegotiatingViewResolver} bean. - * - * @author Sebastien Deleuze - * @since 4.1 - */ -public class ContentNegotiatingRegistration extends ViewResolutionRegistration { - - private List defaultViews; - - public ContentNegotiatingRegistration(ViewResolutionRegistry registry) { - super(registry, new ContentNegotiatingViewResolver()); - } - - /** - * Indicate whether a {@link javax.servlet.http.HttpServletResponse#SC_NOT_ACCEPTABLE 406 Not Acceptable} - * status code should be returned if no suitable view can be found. - * - * @see ContentNegotiatingViewResolver#setUseNotAcceptableStatusCode(boolean) - */ - public ContentNegotiatingRegistration useNotAcceptable(boolean useNotAcceptable) { - this.viewResolver.setUseNotAcceptableStatusCode(useNotAcceptable); - return this; - } - - /** - * - * Set the default views to use when a more specific view can not be obtained - * from the {@link org.springframework.web.servlet.ViewResolver} chain. - * - * @see ContentNegotiatingViewResolver#setDefaultViews(java.util.List) - */ - public ContentNegotiatingRegistration defaultViews(View... defaultViews) { - if(this.defaultViews == null) { - this.defaultViews = new ArrayList(); - } - this.defaultViews.addAll(Arrays.asList(defaultViews)); - return this; - } - - @Override - protected ContentNegotiatingViewResolver getViewResolver() { - this.viewResolver.setDefaultViews(this.defaultViews); - return super.getViewResolver(); - } -} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java index c8fce889af..16dc2e186d 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java @@ -76,8 +76,8 @@ public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { } @Override - protected void configureViewResolution(ViewResolutionRegistry registry) { - this.configurers.configureViewResolution(registry); + protected void configureViewResolvers(ViewResolverRegistry registry) { + this.configurers.configureViewResolvers(registry); } @Override diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/EnableWebMvc.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/EnableWebMvc.java index 63f46f422d..ec699fc621 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/EnableWebMvc.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/EnableWebMvc.java @@ -21,8 +21,8 @@ import java.lang.annotation.Target; import org.springframework.context.annotation.Import; /** - * Add this annotation to an {@code @Configuration} class to have the Spring MVC - * configuration defined in {@link WebMvcConfigurationSupport} imported: + * Adding this annotation to an {@code @Configuration} class imports the Spring MVC + * configuration from {@link WebMvcConfigurationSupport}, e.g.: * *
  * @Configuration
@@ -32,9 +32,14 @@ import org.springframework.context.annotation.Import;
  *
  * }
  * 
- *

Customize the imported configuration by implementing the - * {@link WebMvcConfigurer} interface or more likely by extending the - * {@link WebMvcConfigurerAdapter} base class and overriding individual methods: + * + *

As of 4.1 this annotation may also import {@link WebMvcFreeMarkerConfiguration}, + * {@link WebMvcVelocityConfiguration}, or {@link WebMvcTilesConfiguration} if + * those libraries are found on the classpath. + * + *

To customize the imported configuration, implement the interface + * {@link WebMvcConfigurer} or more likely extend the empty method base class + * {@link WebMvcConfigurerAdapter} and override individual methods, e.g.: * *

  * @Configuration
@@ -56,10 +61,13 @@ import org.springframework.context.annotation.Import;
  * }
  * 
* - *

If the customization options of {@link WebMvcConfigurer} do not expose - * something you need to configure, consider removing the {@code @EnableWebMvc} - * annotation and extending directly from {@link WebMvcConfigurationSupport} - * overriding selected {@code @Bean} methods: + *

To customize the FreeMarker, Velocity, or Tiles configuration, additionally + * implement {@link FreeMarkerWebMvcConfigurer}, {@link VelocityWebMvcConfigurer}, + * and/or {@link TilesWebMvcConfigurer}. + * + *

If {@link WebMvcConfigurer} does not expose some advanced setting that + * needs to be configured, consider removing the {@code @EnableWebMvc} + * annotation and extending directly from {@link WebMvcConfigurationSupport}, e.g.: * *

  * @Configuration
@@ -79,17 +87,23 @@ import org.springframework.context.annotation.Import;
  * }
  * 
* - * @see WebMvcConfigurer - * @see WebMvcConfigurerAdapter + *

When the {@code @EnableWebMvc} annotation is removed, the FreeMarker, + * Velocity, and Tiles configuration is no longer automatically imported and need + * to be imported explicitly. * * @author Dave Syer * @author Rossen Stoyanchev * @author Sebastien Deleuze * @since 3.1 + * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurer + * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter + * @see org.springframework.web.servlet.config.annotation.FreeMarkerWebMvcConfigurer + * @see org.springframework.web.servlet.config.annotation.VelocityWebMvcConfigurer + * @see org.springframework.web.servlet.config.annotation.TilesWebMvcConfigurer */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented -@Import({DelegatingWebMvcConfiguration.class, ViewResolutionImportSelector.class}) +@Import({DelegatingWebMvcConfiguration.class, ViewConfigurationImportSelector.class}) public @interface EnableWebMvc { } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/FreeMarkerRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/FreeMarkerRegistration.java deleted file mode 100644 index 5d743b95aa..0000000000 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/FreeMarkerRegistration.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package org.springframework.web.servlet.config.annotation; - -import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver; - -/** - * Encapsulates information required to create a - * {@link org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver} and a - * {@link org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer} beans. - * Default configuration is "" prefix, ".ftl" suffix and "/WEB-INF/" templateLoaderPath. - * - * @author Sebastien Deleuze - * @since 4.1 - */ -public class FreeMarkerRegistration extends ViewResolutionRegistration { - - - public FreeMarkerRegistration(ViewResolutionRegistry registry) { - super(registry, new FreeMarkerViewResolver()); - this.prefix(""); - this.suffix(".ftl"); - } - - /** - * Set the prefix that gets prepended to view names when building a URL. - * - * @see org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver#setPrefix(String) - */ - public FreeMarkerRegistration prefix(String prefix) { - this.viewResolver.setPrefix(prefix); - return this; - } - - /** - * Set the suffix that gets appended to view names when building a URL. - * - * @see org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver#setSuffix(String) - */ - public FreeMarkerRegistration suffix(String suffix) { - this.viewResolver.setSuffix(suffix); - return this; - } - - /** - * Enable or disable caching. - * - * @see org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver#setCache(boolean) - */ - public FreeMarkerRegistration cache(boolean cache) { - this.viewResolver.setCache(cache); - return this; - } - -} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/JspRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/JspRegistration.java deleted file mode 100644 index bfa401320f..0000000000 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/JspRegistration.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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. - */ - -package org.springframework.web.servlet.config.annotation; - -import org.springframework.web.servlet.view.InternalResourceViewResolver; - -/** - * Encapsulates information required to create an {@link InternalResourceViewResolver} bean. - * Default configuration is "/WEB-INF/" prefix and ".jsp" suffix. - * - * @author Sebastien Deleuze - * @since 4.1 - */ -public class JspRegistration extends ViewResolutionRegistration { - - public JspRegistration(ViewResolutionRegistry registry) { - this(registry, "/WEB-INF/", ".jsp"); - } - - public JspRegistration(ViewResolutionRegistry registry, String prefix, String suffix) { - super(registry, new InternalResourceViewResolver()); - this.viewResolver.setPrefix(prefix); - this.viewResolver.setSuffix(suffix); - } - -} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/TilesRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/TilesRegistration.java deleted file mode 100644 index 80908ef0a1..0000000000 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/TilesRegistration.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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. - */ - -package org.springframework.web.servlet.config.annotation; - -import org.springframework.web.servlet.view.tiles3.TilesViewResolver; - -/** - * Encapsulates information required to create a - * {@link org.springframework.web.servlet.view.tiles3.TilesViewResolver} and a - * {@link org.springframework.web.servlet.view.tiles3.TilesConfigurer} beans. - * - * Default definition is "/WEB-INF/tiles.xml" and no Tiles definition check refresh. - * - * @author Sebastien Deleuze - * @since 4.1 - */ -public class TilesRegistration extends ViewResolutionRegistration { - - - public TilesRegistration(ViewResolutionRegistry registry) { - super(registry, new TilesViewResolver()); - } - - /** - * Set the prefix that gets prepended to view names when building a URL. - * - * @see TilesViewResolver#setPrefix(String) - */ - public TilesRegistration prefix(String prefix) { - this.viewResolver.setPrefix(prefix); - return this; - } - - /** - * Set the suffix that gets appended to view names when building a URL. - * - * @see TilesViewResolver#setSuffix(String) - */ - public TilesRegistration suffix(String suffix) { - this.viewResolver.setSuffix(suffix); - return this; - } - -} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/UrlBasedViewResolverRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/UrlBasedViewResolverRegistration.java new file mode 100644 index 0000000000..b63be7e894 --- /dev/null +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/UrlBasedViewResolverRegistration.java @@ -0,0 +1,118 @@ +/* + * 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. + */ + +package org.springframework.web.servlet.config.annotation; + +import org.springframework.web.servlet.view.UrlBasedViewResolver; + +import java.util.Map; + +/** + * Assist with configuring a {@link org.springframework.web.servlet.view.UrlBasedViewResolver}. + * + * @author Sebastien Deleuze + * @author Rossen Stoyanchev + * @since 4.1 + */ +public class UrlBasedViewResolverRegistration { + + protected final UrlBasedViewResolver viewResolver; + + + public UrlBasedViewResolverRegistration(UrlBasedViewResolver viewResolver) { + this.viewResolver = viewResolver; + } + + + protected UrlBasedViewResolver getViewResolver() { + return this.viewResolver; + } + + /** + * Set the prefix that gets prepended to view names when building a URL. + * @see org.springframework.web.servlet.view.UrlBasedViewResolver#setPrefix + */ + public UrlBasedViewResolverRegistration prefix(String prefix) { + this.viewResolver.setPrefix(prefix); + return this; + } + + /** + * Set the suffix that gets appended to view names when building a URL. + * @see org.springframework.web.servlet.view.UrlBasedViewResolver#setSuffix + */ + public UrlBasedViewResolverRegistration suffix(String suffix) { + this.viewResolver.setSuffix(suffix); + return this; + } + + /** + * Set the view class that should be used to create views. + * @see org.springframework.web.servlet.view.UrlBasedViewResolver#setViewClass + */ + public UrlBasedViewResolverRegistration viewClass(Class viewClass) { + this.viewResolver.setViewClass(viewClass); + return this; + } + + /** + * Set the view names (or name patterns) that can be handled by this view + * resolver. View names can contain simple wildcards such that 'my*', '*Report' + * and '*Repo*' will all match the view name 'myReport'. + * @see org.springframework.web.servlet.view.UrlBasedViewResolver#setViewNames + */ + public UrlBasedViewResolverRegistration viewNames(String... viewNames) { + this.viewResolver.setViewNames(viewNames); + return this; + } + + /** + * Set static attributes to be added to the model of every request for all + * views resolved by this view resolver. This allows for setting any kind of + * attribute values, for example bean references. + * @see org.springframework.web.servlet.view.UrlBasedViewResolver#setAttributesMap + */ + public UrlBasedViewResolverRegistration attributes(Map attributes) { + this.viewResolver.setAttributesMap(attributes); + return this; + } + + /** + * Specify the maximum number of entries for the view cache. + * Default is 1024. + * @see org.springframework.web.servlet.view.UrlBasedViewResolver#setCache(boolean) + */ + public UrlBasedViewResolverRegistration cacheLimit(int cacheLimit) { + this.viewResolver.setCacheLimit(cacheLimit); + return this; + } + + /** + * Enable or disable caching. + *

This is equivalent to setting the {@link #cacheLimit "cacheLimit"} + * property to the default limit (1024) or to 0, respectively. + *

Default is "true": caching is enabled. + * Disable this only for debugging and development. + * @see org.springframework.web.servlet.view.UrlBasedViewResolver#setCache(boolean) + */ + public UrlBasedViewResolverRegistration cache(boolean cache) { + this.viewResolver.setCache(cache); + return this; + } + +} + + diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/VelocityRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/VelocityRegistration.java deleted file mode 100644 index 05f7bc28f6..0000000000 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/VelocityRegistration.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - */ - -package org.springframework.web.servlet.config.annotation; - -import org.springframework.web.servlet.view.velocity.VelocityViewResolver; - -/** - * Encapsulates information required to create a - * {@link org.springframework.web.servlet.view.velocity.VelocityViewResolver} and a - * {@link org.springframework.web.servlet.view.velocity.VelocityConfigurer beans}. - * Default configuration is "" prefix, ".vm" suffix and "/WEB-INF/" resourceLoaderPath. - * - * @author Sebastien Deleuze - * @since 4.1 - */ -public class VelocityRegistration extends ViewResolutionRegistration { - - - public VelocityRegistration(ViewResolutionRegistry registry) { - super(registry, new VelocityViewResolver()); - this.prefix(""); - this.suffix(".vm"); - } - - /** - * Set the prefix that gets prepended to view names when building a URL. - * - * @see org.springframework.web.servlet.view.velocity.VelocityViewResolver#setPrefix(String) - */ - public VelocityRegistration prefix(String prefix) { - this.viewResolver.setPrefix(prefix); - return this; - } - - /** - * Set the suffix that gets appended to view names when building a URL. - * - * @see org.springframework.web.servlet.view.velocity.VelocityViewResolver#setSuffix(String) - */ - public VelocityRegistration suffix(String suffix) { - this.viewResolver.setSuffix(suffix); - return this; - } - - /** - * Enable or disable caching. - * - * @see org.springframework.web.servlet.view.velocity.VelocityViewResolver#setCache(boolean) - */ - public VelocityRegistration cache(boolean cache) { - this.viewResolver.setCache(cache); - return this; - } - -} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistration.java deleted file mode 100644 index c15b739247..0000000000 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistration.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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. - */ - -package org.springframework.web.servlet.config.annotation; - -import org.springframework.web.servlet.ViewResolver; - -/** - * Encapsulates information required to create a view resolver. - * - * @author Sebastien Deleuze - * @since 4.1 - */ -public class ViewResolutionRegistration { - - protected final ViewResolutionRegistry registry; - - protected final T viewResolver; - - public ViewResolutionRegistration(ViewResolutionRegistry registry, T viewResolver) { - this.registry = registry; - this.viewResolver = viewResolver; - } - - public ViewResolutionRegistry and() { - return this.registry; - } - - protected T getViewResolver() { - return this.viewResolver; - } - -} - - diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistry.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistry.java deleted file mode 100644 index e37dde4744..0000000000 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistry.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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. - */ - -package org.springframework.web.servlet.config.annotation; - -import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.beans.factory.BeanInitializationException; -import org.springframework.context.ApplicationContext; -import org.springframework.util.ObjectUtils; -import org.springframework.web.servlet.View; -import org.springframework.web.servlet.ViewResolver; -import org.springframework.web.servlet.view.freemarker.FreeMarkerConfig; -import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; -import org.springframework.web.servlet.view.tiles3.TilesConfigurer; -import org.springframework.web.servlet.view.velocity.VelocityConfigurer; - -import java.util.ArrayList; -import java.util.List; - -/** - * Helps with configuring a list of view resolvers. - * - * @author Sebastien Deleuze - * @since 4.1 - */ -public class ViewResolutionRegistry { - - private final List> registrations = new ArrayList>(); - - private final ApplicationContext applicationContext; - - - public ViewResolutionRegistry(ApplicationContext context) { - this.applicationContext = context; - } - - - /** - * Register a custom {@link ViewResolver} bean. - */ - public ViewResolutionRegistration addViewResolver(ViewResolver viewResolver) { - ViewResolutionRegistration registration = new ViewResolutionRegistration(this, viewResolver); - registrations.add(registration); - return registration; - } - - /** - * Register an {@link org.springframework.web.servlet.view.InternalResourceViewResolver} - * bean with default "/WEB-INF/" prefix and ".jsp" suffix. - */ - public JspRegistration jsp() { - JspRegistration registration = new JspRegistration(this); - addAndCheckViewResolution(registration); - return registration; - } - - /** - * Register an {@link org.springframework.web.servlet.view.InternalResourceViewResolver} - * bean with specified prefix and suffix. - */ - public JspRegistration jsp(String prefix, String suffix) { - JspRegistration registration = new JspRegistration(this, prefix, suffix); - addAndCheckViewResolution(registration); - return registration; - } - - /** - * Register a {@link org.springframework.web.servlet.view.BeanNameViewResolver} bean. - */ - public BeanNameRegistration beanName() { - BeanNameRegistration registration = new BeanNameRegistration(this); - addAndCheckViewResolution(registration); - return registration; - } - - /** - * Register a {@link org.springframework.web.servlet.view.tiles3.TilesViewResolver} and - * a {@link org.springframework.web.servlet.view.tiles3.TilesConfigurer} with - * default "/WEB-INF/tiles.xml" definition and no Tiles definition check refresh. - */ - public TilesRegistration tiles() { - if (!hasBeanOfType(TilesConfigurer.class)) { - throw new BeanInitializationException( - "It looks like you're trying to configure Tiles view resolution. " + - "If not using @EnableWebMvc you must import WebMvcTilesConfiguration, " + - "or declare your own TilesConfigurer bean."); - } - TilesRegistration registration = new TilesRegistration(this); - addAndCheckViewResolution(registration); - return registration; - } - - /** - * Register a {@link org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver} - * and a {@link org.springframework.web.servlet.view.velocity.VelocityConfigurer} beans with - * default "" prefix, ".vm" suffix and "/WEB-INF/" resourceLoaderPath. - */ - public VelocityRegistration velocity() { - if (!hasBeanOfType(VelocityConfigurer.class)) { - throw new BeanInitializationException( - "It looks like you're trying to configure Velocity view resolution. " + - "If not using @EnableWebMvc you must import WebMvcVelocityConfiguration, " + - "or declare your own VelocityConfigurer bean."); - } - VelocityRegistration registration = new VelocityRegistration(this); - addAndCheckViewResolution(registration); - return registration; - } - - /** - * Register a {@link org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver} - * and a {@link org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer} beans with - * "" prefix, ".ftl" suffix and "/WEB-INF/" templateLoaderPath. - */ - public FreeMarkerRegistration freemarker() { - if (!hasBeanOfType(FreeMarkerConfigurer.class)) { - throw new BeanInitializationException( - "It looks like you're trying to configure FreeMarker view resolution. " + - "If not using @EnableWebMvc you must import WebMvcFreeMarkerConfiguration, " + - "or declare your own FreeMarkerConfigurer bean."); - } - FreeMarkerRegistration registration = new FreeMarkerRegistration(this); - addAndCheckViewResolution(registration); - return registration; - } - - protected boolean hasBeanOfType(Class beanType) { - return !ObjectUtils.isEmpty(BeanFactoryUtils.beanNamesForTypeIncludingAncestors( - this.applicationContext, beanType, false, false)); - } - - /** - * Register a {@link org.springframework.web.servlet.view.ContentNegotiatingViewResolver} bean. - */ - public ContentNegotiatingRegistration contentNegotiating(View... defaultViews) { - ContentNegotiatingRegistration registration = new ContentNegotiatingRegistration(this); - registration.defaultViews(defaultViews); - addAndCheckViewResolution(registration); - return registration; - } - - protected List getViewResolvers() { - List viewResolvers = new ArrayList(); - for(ViewResolutionRegistration registration : this.registrations) { - viewResolvers.add(registration.getViewResolver()); - } - return viewResolvers; - } - - private void addAndCheckViewResolution(ViewResolutionRegistration registration) { - for(ViewResolutionRegistration existingRegistration : this.registrations) { - if(existingRegistration.getClass().equals(registration.getClass())) { - throw new IllegalStateException("An instance of " + registration.getClass().getSimpleName() - + " is already registered, and multiple view resolvers and configurers beans are not supported by this registry"); - } - } - registrations.add(registration); - } -} 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 new file mode 100644 index 0000000000..2e0957933d --- /dev/null +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistry.java @@ -0,0 +1,290 @@ +/* + * 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. + */ + +package org.springframework.web.servlet.config.annotation; + +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.BeanInitializationException; +import org.springframework.context.ApplicationContext; +import org.springframework.core.Ordered; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; +import org.springframework.web.accept.ContentNegotiationManager; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.view.BeanNameViewResolver; +import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; +import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver; +import org.springframework.web.servlet.view.tiles3.TilesConfigurer; +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 java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Assist with the configuration of a chain of + * {@link org.springframework.web.servlet.ViewResolver ViewResolver} instances. + * This class is expected to be used via {@link WebMvcConfigurer#configureViewResolvers}. + * + * @author Sebastien Deleuze + * @author Rossen Stoyanchev + * @since 4.1 + */ +public class ViewResolverRegistry { + + private ContentNegotiatingViewResolver contentNegotiatingResolver; + + private final List viewResolvers = new ArrayList(4); + + private int order = Ordered.LOWEST_PRECEDENCE; + + private ContentNegotiationManager contentNegotiationManager; + + private ApplicationContext applicationContext; + + + protected void setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager) { + this.contentNegotiationManager = contentNegotiationManager; + } + + protected void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + /** + * Whether any view resolvers have been registered. + */ + public boolean hasRegistrations() { + return (this.contentNegotiatingResolver != null || !this.viewResolvers.isEmpty()); + } + + + /** + * Enable use of a {@link ContentNegotiatingViewResolver} to front all other + * configured view resolvers and select among all selected Views based on + * media types requested by the client (e.g. in the Accept header). + * + *

If invoked multiple times the provided default views will be added to + * any other default views that may have been configured already. + * + * @see ContentNegotiatingViewResolver#setDefaultViews + */ + public void enableContentNegotiation(View... defaultViews) { + initContentNegotiatingViewResolver(defaultViews); + } + + /** + * Enable use of a {@link ContentNegotiatingViewResolver} to front all other + * configured view resolvers and select among all selected Views based on + * media types requested by the client (e.g. in the Accept header). + * + *

If invoked multiple times the provided default views will be added to + * any other default views that may have been configured already. + * + * @see ContentNegotiatingViewResolver#setDefaultViews + */ + public void enableContentNegotiation(boolean useNotAcceptableStatus, View... defaultViews) { + initContentNegotiatingViewResolver(defaultViews); + this.contentNegotiatingResolver.setUseNotAcceptableStatusCode(useNotAcceptableStatus); + } + + private void initContentNegotiatingViewResolver(View[] defaultViews) { + + // ContentNegotiatingResolver in the registry: elevate its precedence! + this.order = Ordered.HIGHEST_PRECEDENCE; + + if (this.contentNegotiatingResolver != null) { + if (!ObjectUtils.isEmpty(defaultViews)) { + if (!CollectionUtils.isEmpty(this.contentNegotiatingResolver.getDefaultViews())) { + List views = new ArrayList(this.contentNegotiatingResolver.getDefaultViews()); + views.addAll(Arrays.asList(defaultViews)); + this.contentNegotiatingResolver.setDefaultViews(views); + } + } + } + else { + this.contentNegotiatingResolver = new ContentNegotiatingViewResolver(); + this.contentNegotiatingResolver.setDefaultViews(Arrays.asList(defaultViews)); + this.contentNegotiatingResolver.setViewResolvers(this.viewResolvers); + this.contentNegotiatingResolver.setContentNegotiationManager(this.contentNegotiationManager); + } + } + + /** + * Enable view resolution by forwarding to JSP pages with a default view name + * prefix of "/WEB-INF/" and a default suffix of ".jsp". + * + *

This method may be invoked multiple and each call will register a + * separate ViewResolver instance. Note that since it's not easy to determine + * if a JSP exists without forwarding to it, using multiple JSP-based view + * resolvers only makes sense in combination with the "viewNames" property + * that indicates which view names are handled by which resolver. + */ + public UrlBasedViewResolverRegistration jsp() { + return jsp("/WEB-INF/", ".jsp"); + } + + /** + * Enable view resolution by forwarding to JSP pages with the specified + * prefix and suffix. + * + *

This method may be invoked multiple and each call will register a + * separate ViewResolver instance. Note that since it's not easy to determine + * if a JSP exists without forwarding to it, using multiple JSP-based view + * resolvers only makes sense in combination with the "viewNames" property + * that indicates which view names are handled by which resolver. + */ + public UrlBasedViewResolverRegistration jsp(String prefix, String suffix) { + InternalResourceViewResolver resolver = new InternalResourceViewResolver(); + resolver.setPrefix(prefix); + resolver.setSuffix(suffix); + this.viewResolvers.add(resolver); + return new UrlBasedViewResolverRegistration(resolver); + } + + /** + * Enable Tiles-based view resolution. + * + *

By default tiles definitions are expected to be in "/WEB-INF/tiles.xml". + * To change that and other Tiles-related options please also implement the + * interface {@link TilesWebMvcConfigurer}. + */ + public UrlBasedViewResolverRegistration tiles() { + if (this.applicationContext != null && !hasBeanOfType(TilesConfigurer.class)) { + throw new BeanInitializationException( + "It looks like you're trying to configure Tiles view resolution. " + + "If not using @EnableWebMvc you must import WebMvcTilesConfiguration, " + + "or declare your own TilesConfigurer bean."); + } + TilesRegistration registration = new TilesRegistration(); + this.viewResolvers.add(registration.getViewResolver()); + return registration; + } + + /** + * Enable FreeMarker-based view resolution with an empty default view name + * prefix and a default suffix of ".ftl". + * + *

By default the FreeMarker template loader path is set to "/WEB-INF/". + * To change that and other FreeMarker-related options please also implement + * the interface {@link FreeMarkerWebMvcConfigurer}. + */ + public UrlBasedViewResolverRegistration freeMarker() { + if (this.applicationContext != null && !hasBeanOfType(FreeMarkerConfigurer.class)) { + throw new BeanInitializationException( + "It looks like you're trying to configure FreeMarker view resolution. " + + "If not using @EnableWebMvc you must import WebMvcFreeMarkerConfiguration, " + + "or declare your own FreeMarkerConfigurer bean."); + } + FreeMarkerRegistration registration = new FreeMarkerRegistration(); + this.viewResolvers.add(registration.getViewResolver()); + return registration; + } + + /** + * Enable Velocity-based view resolution with an empty default view name + * prefix, a default suffix of ".vm". + * + *

By default the Velocity resource loader path is set to "/WEB-INF/". + * To change that and other Velocity-related options please also implement + * the interface {@link VelocityWebMvcConfigurer}. + */ + public UrlBasedViewResolverRegistration velocity() { + if (this.applicationContext != null && !hasBeanOfType(VelocityConfigurer.class)) { + throw new BeanInitializationException( + "It looks like you're trying to configure Velocity view resolution. " + + "If not using @EnableWebMvc you must import WebMvcVelocityConfiguration, " + + "or declare your own VelocityConfigurer bean."); + } + VelocityRegistration registration = new VelocityRegistration(); + this.viewResolvers.add(registration.getViewResolver()); + return registration; + } + + /** + * Enable the ability to map view names returned from controllers to + * {@link org.springframework.web.servlet.View} beans. + */ + public void beanName() { + BeanNameViewResolver resolver = new BeanNameViewResolver(); + this.viewResolvers.add(resolver); + } + + /** + * Register a {@link ViewResolver} bean instance. This may be useful to + * configure a custom (or 3rd party) resolver implementation. It may also be + * used as an alternative to other registration methods in this class when + * they don't expose some more advanced property that needs to be set. + */ + public void viewResolver(ViewResolver viewResolver) { + if (viewResolver instanceof ContentNegotiatingViewResolver) { + throw new BeanInitializationException( + "addViewResolver cannot be used to configure a ContentNegotiatingViewResolver. " + + "Please use the method enableContentNegotiation instead."); + } + this.viewResolvers.add(viewResolver); + } + + protected boolean hasBeanOfType(Class beanType) { + return !ObjectUtils.isEmpty(BeanFactoryUtils.beanNamesForTypeIncludingAncestors( + this.applicationContext, beanType, false, false)); + } + + + protected int getOrder() { + return this.order; + } + + protected List getViewResolvers() { + if (this.contentNegotiatingResolver != null) { + return Collections.singletonList(this.contentNegotiatingResolver); + } + else { + return this.viewResolvers; + } + } + + + private static class TilesRegistration extends UrlBasedViewResolverRegistration { + + private TilesRegistration() { + super(new TilesViewResolver()); + } + } + + private static class VelocityRegistration extends UrlBasedViewResolverRegistration { + + private VelocityRegistration() { + super(new VelocityViewResolver()); + getViewResolver().setSuffix(".vm"); + } + } + + private static class FreeMarkerRegistration extends UrlBasedViewResolverRegistration { + + private FreeMarkerRegistration() { + super(new FreeMarkerViewResolver()); + getViewResolver().setSuffix(".ftl"); + } + } + +} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java index b23d1dc0e6..ed56b8612a 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java @@ -81,7 +81,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver; import org.springframework.web.servlet.resource.ResourceUrlProvider; import org.springframework.web.servlet.resource.ResourceUrlProviderExposingInterceptor; -import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; +import org.springframework.web.servlet.view.ViewResolverComposite; import org.springframework.web.util.UrlPathHelper; /** @@ -197,7 +197,6 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv private PathMatchConfigurer pathMatchConfigurer; - private ViewResolutionRegistry viewResolutionRegistry; /** * Set the {@link javax.servlet.ServletContext}, e.g. for resource handling, @@ -354,13 +353,6 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv protected void addViewControllers(ViewControllerRegistry registry) { } - /** - * Override this method to configure view resolution. - * @see ViewResolutionRegistry - */ - protected void configureViewResolution(ViewResolutionRegistry registry) { - } - /** * Return a {@link BeanNameUrlHandlerMapping} ordered at 2 to map URL * paths to controller bean names. @@ -791,45 +783,33 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv } /** - * Register a {@link ViewResolverComposite} that contains an ordered list of + * Register a {@link org.springframework.web.servlet.view.ViewResolverComposite} that contains an ordered list of * view resolvers obtained either through - * {@link #configureViewResolution(ViewResolutionRegistry)}. + * {@link #configureViewResolvers(ViewResolverRegistry)}. */ @Bean - public ViewResolverComposite viewResolverComposite() { - ViewResolutionRegistry registry = getViewResolutionRegistry(); - ViewResolverComposite compositeViewResolver = new ViewResolverComposite(); - List viewResolvers = registry.getViewResolvers(); - ContentNegotiatingViewResolver contentNegotiatingViewResolver = null; - List filteredViewResolvers = new ArrayList(); - for(ViewResolver viewResolver : viewResolvers) { - if(viewResolver instanceof ContentNegotiatingViewResolver) { - contentNegotiatingViewResolver = (ContentNegotiatingViewResolver)viewResolver; - contentNegotiatingViewResolver.setContentNegotiationManager(this.mvcContentNegotiationManager()); - } else { - filteredViewResolvers.add(viewResolver); - } - } - if(contentNegotiatingViewResolver != null) { - contentNegotiatingViewResolver.setViewResolvers(filteredViewResolvers); - viewResolvers = new ArrayList(); - viewResolvers.add(contentNegotiatingViewResolver); - } - compositeViewResolver.setViewResolvers(viewResolvers); - compositeViewResolver.setApplicationContext(this.applicationContext); - compositeViewResolver.setServletContext(this.servletContext); - - return compositeViewResolver; + public ViewResolver mvcViewResolver() { + ViewResolverRegistry registry = new ViewResolverRegistry(); + registry.setContentNegotiationManager(mvcContentNegotiationManager()); + registry.setApplicationContext(this.applicationContext); + configureViewResolvers(registry); + + ViewResolverComposite composite = new ViewResolverComposite(); + composite.setOrder(registry.getOrder()); + composite.setViewResolvers(registry.getViewResolvers()); + composite.setApplicationContext(this.applicationContext); + composite.setServletContext(this.servletContext); + return composite; } - protected ViewResolutionRegistry getViewResolutionRegistry() { - if(this.viewResolutionRegistry == null) { - this.viewResolutionRegistry = new ViewResolutionRegistry(this.applicationContext); - configureViewResolution(this.viewResolutionRegistry); - } - return this.viewResolutionRegistry; + /** + * Override this method to configure view resolution. + * @see ViewResolverRegistry + */ + protected void configureViewResolvers(ViewResolverRegistry registry) { } + private final static class EmptyHandlerMapping extends AbstractHandlerMapping { @Override diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java index 80ec304b38..7f6021581f 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java @@ -139,9 +139,11 @@ public interface WebMvcConfigurer { void addViewControllers(ViewControllerRegistry registry); /** - * Configure view resolution to translate view names to view implementations. + * Configure view resolvers to translate String-based view names returned from + * controllers into concrete {@link org.springframework.web.servlet.View} + * implementations to perform rendering with. */ - void configureViewResolution(ViewResolutionRegistry registry); + void configureViewResolvers(ViewResolverRegistry registry); /** * Add handlers to serve static resources such as images, js, and, css diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java index 2c8bb9d032..e40f6c2010 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java @@ -138,7 +138,7 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer { *

This implementation is empty. */ @Override - public void configureViewResolution(ViewResolutionRegistry registry) { + public void configureViewResolvers(ViewResolverRegistry registry) { } /** diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java index d01bc4fc46..c524092d54 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java @@ -114,9 +114,9 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer { } @Override - public void configureViewResolution(ViewResolutionRegistry registry) { + public void configureViewResolvers(ViewResolverRegistry registry) { for (WebMvcConfigurer delegate : this.delegates) { - delegate.configureViewResolution(registry); + delegate.configureViewResolvers(registry); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcFreeMarkerConfiguration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcFreeMarkerConfiguration.java index 7defb00b29..da1af95545 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcFreeMarkerConfiguration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcFreeMarkerConfiguration.java @@ -56,7 +56,7 @@ public class WebMvcFreeMarkerConfiguration { @Bean @Lazy - public FreeMarkerConfigurer freeMarkerConfigurer() { + public FreeMarkerConfigurer mvcFreeMarkerConfigurer() { FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); configurer.setTemplateLoaderPath("/WEB-INF/"); for (FreeMarkerWebMvcConfigurer webMvcConfigurer : this.webMvcConfigurers) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcTilesConfiguration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcTilesConfiguration.java index 8d55e4a3df..dcc9ed9014 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcTilesConfiguration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcTilesConfiguration.java @@ -66,7 +66,7 @@ public class WebMvcTilesConfiguration implements ResourceLoaderAware { @Bean - public TilesConfigurer tilesConfigurer() { + public TilesConfigurer mvcTilesConfigurer() { TilesConfigurer configurer = new TilesConfigurer(); if (!this.webMvcConfigurers.isEmpty()) { for (TilesWebMvcConfigurer webMvcConfigurer : this.webMvcConfigurers) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcVelocityConfiguration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcVelocityConfiguration.java index 02f0296dd1..4641850088 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcVelocityConfiguration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcVelocityConfiguration.java @@ -56,7 +56,7 @@ public class WebMvcVelocityConfiguration { @Bean @Lazy - public VelocityConfigurer velocityConfigurer() { + public VelocityConfigurer mvcVelocityConfigurer() { VelocityConfigurer configurer = new VelocityConfigurer(); configurer.setResourceLoaderPath("/WEB-INF/"); for (VelocityWebMvcConfigurer webMvcConfigurer : this.webMvcConfigurers) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java index eec86d9569..6a1aef469b 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.java @@ -228,6 +228,10 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport this.defaultViews = defaultViews; } + public List getDefaultViews() { + return Collections.unmodifiableList(this.defaultViews); + } + /** * Sets the view resolvers to be wrapped by this view resolver. *

If this property is not set, view resolvers will be detected automatically. @@ -236,6 +240,10 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport this.viewResolvers = viewResolvers; } + public List getViewResolvers() { + return Collections.unmodifiableList(this.viewResolvers); + } + @Override protected void initServletContext(ServletContext servletContext) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/ViewResolverComposite.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/ViewResolverComposite.java similarity index 53% rename from spring-webmvc/src/main/java/org/springframework/web/servlet/ViewResolverComposite.java rename to spring-webmvc/src/main/java/org/springframework/web/servlet/view/ViewResolverComposite.java index 4f2e324135..414bfbeccf 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/ViewResolverComposite.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/ViewResolverComposite.java @@ -14,87 +14,101 @@ * limitations under the License. */ -package org.springframework.web.servlet; +package org.springframework.web.servlet.view; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.Ordered; +import org.springframework.util.CollectionUtils; import org.springframework.web.context.ServletContextAware; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.ViewResolver; import javax.servlet.ServletContext; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; /** - * A {@link ViewResolverComposite} that delegates to a list of other {@link ViewResolver}s. + * A {@link org.springframework.web.servlet.ViewResolver} that delegates to others. * * @author Sebastien Deleuze + * @author Rossen Stoyanchev * @since 4.1 */ -public class ViewResolverComposite implements ApplicationContextAware, ServletContextAware, ViewResolver, Ordered { +public class ViewResolverComposite implements ViewResolver, Ordered, InitializingBean, + ApplicationContextAware, ServletContextAware { - private List viewResolvers; + private final List viewResolvers = new ArrayList(); private int order = Ordered.LOWEST_PRECEDENCE; - public void setOrder(int order) { - this.order = order; - } - - @Override - public int getOrder() { - return this.order; - } /** * Set the list of view viewResolvers to delegate to. */ public void setViewResolvers(List viewResolvers) { - this.viewResolvers = viewResolvers; + this.viewResolvers.clear(); + if (!CollectionUtils.isEmpty(viewResolvers)) { + this.viewResolvers.addAll(viewResolvers); + } } /** * Return the list of view viewResolvers to delegate to. */ public List getViewResolvers() { - return Collections.unmodifiableList(viewResolvers); + return Collections.unmodifiableList(this.viewResolvers); + } + + public void setOrder(int order) { + this.order = order; } @Override - public View resolveViewName(String viewName, Locale locale) throws Exception { - if (viewResolvers != null) { - for (ViewResolver viewResolver : viewResolvers) { - View v = viewResolver.resolveViewName(viewName, locale); - if (v != null) { - return v; - } + public int getOrder() { + return this.order; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + for (ViewResolver viewResolver : this.viewResolvers) { + if (viewResolver instanceof ApplicationContextAware) { + ((ApplicationContextAware)viewResolver).setApplicationContext(applicationContext); } } + } - return null; + @Override + public void setServletContext(ServletContext servletContext) { + for (ViewResolver viewResolver : this.viewResolvers) { + if (viewResolver instanceof ServletContextAware) { + ((ServletContextAware)viewResolver).setServletContext(servletContext); + } + } } @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if (viewResolvers != null) { - for (ViewResolver viewResolver : viewResolvers) { - if(viewResolver instanceof ApplicationContextAware) { - ((ApplicationContextAware)viewResolver).setApplicationContext(applicationContext); - } + public void afterPropertiesSet() throws Exception { + for (ViewResolver viewResolver : this.viewResolvers) { + if (viewResolver instanceof InitializingBean) { + ((InitializingBean) viewResolver).afterPropertiesSet(); } } } @Override - public void setServletContext(ServletContext servletContext) { - if (viewResolvers != null) { - for (ViewResolver viewResolver : viewResolvers) { - if(viewResolver instanceof ServletContextAware) { - ((ServletContextAware)viewResolver).setServletContext(servletContext); - } + public View resolveViewName(String viewName, Locale locale) throws Exception { + for (ViewResolver viewResolver : this.viewResolvers) { + View view = viewResolver.resolveViewName(viewName, locale); + if (view != null) { + return view; } } + return null; } + } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionIntegrationTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionIntegrationTests.java index 5780e07134..eb50ad4f78 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionIntegrationTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionIntegrationTests.java @@ -147,15 +147,15 @@ public class ViewResolutionIntegrationTests { @Configuration static class MinimalFreeMarkerWebConfig extends AbstractWebConfig { @Override - public void configureViewResolution(ViewResolutionRegistry registry) { - registry.freemarker(); + public void configureViewResolvers(ViewResolverRegistry registry) { + registry.freeMarker(); } } @Configuration static class MinimalVelocityWebConfig extends AbstractWebConfig { @Override - public void configureViewResolution(ViewResolutionRegistry registry) { + public void configureViewResolvers(ViewResolverRegistry registry) { registry.velocity(); } } @@ -163,7 +163,7 @@ public class ViewResolutionIntegrationTests { @Configuration static class MinimalTilesWebConfig extends AbstractWebConfig { @Override - public void configureViewResolution(ViewResolutionRegistry registry) { + public void configureViewResolvers(ViewResolverRegistry registry) { registry.tiles(); } } @@ -171,8 +171,8 @@ public class ViewResolutionIntegrationTests { @Configuration static class FreeMarkerWebConfig extends AbstractWebConfig implements FreeMarkerWebMvcConfigurer { @Override - public void configureViewResolution(ViewResolutionRegistry registry) { - registry.freemarker(); + public void configureViewResolvers(ViewResolverRegistry registry) { + registry.freeMarker(); } @Override public void configureFreeMarker(FreeMarkerConfigurer configurer) { @@ -183,7 +183,7 @@ public class ViewResolutionIntegrationTests { @Configuration static class VelocityWebConfig extends AbstractWebConfig implements VelocityWebMvcConfigurer { @Override - public void configureViewResolution(ViewResolutionRegistry registry) { + public void configureViewResolvers(ViewResolverRegistry registry) { registry.velocity(); } @Override @@ -195,7 +195,7 @@ public class ViewResolutionIntegrationTests { @Configuration static class TilesWebConfig extends AbstractWebConfig implements TilesWebMvcConfigurer { @Override - public void configureViewResolution(ViewResolutionRegistry registry) { + public void configureViewResolvers(ViewResolverRegistry registry) { registry.tiles(); } @Override @@ -209,8 +209,8 @@ public class ViewResolutionIntegrationTests { // No @EnableWebMvc and no FreeMarkerConfigurer bean @Override - public void configureViewResolution(ViewResolutionRegistry registry) { - registry.freemarker(); + public void configureViewResolvers(ViewResolverRegistry registry) { + registry.freeMarker(); } } @@ -220,7 +220,7 @@ public class ViewResolutionIntegrationTests { // No @EnableWebMvc and no VelocityConfigurer bean @Override - public void configureViewResolution(ViewResolutionRegistry registry) { + public void configureViewResolvers(ViewResolverRegistry registry) { registry.velocity(); } } @@ -231,7 +231,7 @@ public class ViewResolutionIntegrationTests { // No @EnableWebMvc and no TilesConfigurer bean @Override - public void configureViewResolution(ViewResolutionRegistry registry) { + public void configureViewResolvers(ViewResolverRegistry registry) { registry.tiles(); } } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistryTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistryTests.java deleted file mode 100644 index 6ef68dd926..0000000000 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolutionRegistryTests.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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. - */ - -package org.springframework.web.servlet.config.annotation; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.beans.DirectFieldAccessor; -import org.springframework.web.context.support.StaticWebApplicationContext; -import org.springframework.web.servlet.view.BeanNameViewResolver; -import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; -import org.springframework.web.servlet.view.InternalResourceViewResolver; -import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver; -import org.springframework.web.servlet.view.json.MappingJackson2JsonView; -import org.springframework.web.servlet.view.tiles3.TilesViewResolver; -import org.springframework.web.servlet.view.velocity.VelocityViewResolver; - -import static org.junit.Assert.*; -import static org.junit.Assert.assertEquals; - -/** - * Test fixture with a {@link ViewResolutionRegistry}. - * - * @author Sebastien Deleuze - */ -public class ViewResolutionRegistryTests { - - private ViewResolutionRegistry registry; - - @Before - public void setUp() { - registry = new ViewResolutionRegistry(new StaticWebApplicationContext()); - } - - @Test - public void noViewResolution() { - assertNotNull(registry.getViewResolvers()); - assertEquals(0, registry.getViewResolvers().size()); - } - - @Test - public void customViewResolution() { - InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); - viewResolver.setPrefix("/"); - viewResolver.setSuffix(".jsp"); - registry.addViewResolver(viewResolver); - assertEquals(InternalResourceViewResolver.class, registry.getViewResolvers().get(0).getClass()); - InternalResourceViewResolver resolver = (InternalResourceViewResolver)registry.getViewResolvers().get(0); - DirectFieldAccessor resolverDirectFieldAccessor = new DirectFieldAccessor(resolver); - assertEquals("/", resolverDirectFieldAccessor.getPropertyValue("prefix")); - assertEquals(".jsp", resolverDirectFieldAccessor.getPropertyValue("suffix")); - } - - @Test - public void beanNameViewResolution() { - registry.beanName(); - assertNotNull(registry.getViewResolvers()); - assertEquals(1, registry.getViewResolvers().size()); - assertEquals(BeanNameViewResolver.class, registry.getViewResolvers().get(0).getClass()); - } - - @Test - public void jspViewResolution() { - registry.jsp("/", ".jsp"); - assertNotNull(registry.getViewResolvers()); - assertEquals(1, registry.getViewResolvers().size()); - assertEquals(InternalResourceViewResolver.class, registry.getViewResolvers().get(0).getClass()); - InternalResourceViewResolver resolver = (InternalResourceViewResolver)registry.getViewResolvers().get(0); - DirectFieldAccessor resolverDirectFieldAccessor = new DirectFieldAccessor(resolver); - assertEquals("/", resolverDirectFieldAccessor.getPropertyValue("prefix")); - assertEquals(".jsp", resolverDirectFieldAccessor.getPropertyValue("suffix")); - } - - @Test - public void defaultJspViewResolution() { - registry.jsp(); - assertNotNull(registry.getViewResolvers()); - assertEquals(1, registry.getViewResolvers().size()); - assertEquals(InternalResourceViewResolver.class, registry.getViewResolvers().get(0).getClass()); - InternalResourceViewResolver resolver = (InternalResourceViewResolver)registry.getViewResolvers().get(0); - DirectFieldAccessor resolverDirectFieldAccessor = new DirectFieldAccessor(resolver); - assertEquals("/WEB-INF/", resolverDirectFieldAccessor.getPropertyValue("prefix")); - assertEquals(".jsp", resolverDirectFieldAccessor.getPropertyValue("suffix")); - } - - @Test - public void tilesViewResolution() { - this.registry.tiles(); - assertNotNull(this.registry.getViewResolvers()); - assertEquals(1, this.registry.getViewResolvers().size()); - assertEquals(TilesViewResolver.class, this.registry.getViewResolvers().get(0).getClass()); - } - - @Test - public void velocityViewResolution() { - registry.velocity().prefix("/").suffix(".vm").cache(true); - assertNotNull(registry.getViewResolvers()); - assertEquals(1, registry.getViewResolvers().size()); - assertEquals(VelocityViewResolver.class, registry.getViewResolvers().get(0).getClass()); - VelocityViewResolver resolver = (VelocityViewResolver)registry.getViewResolvers().get(0); - DirectFieldAccessor resolverDirectFieldAccessor = new DirectFieldAccessor(resolver); - assertEquals("/", resolverDirectFieldAccessor.getPropertyValue("prefix")); - assertEquals(".vm", resolverDirectFieldAccessor.getPropertyValue("suffix")); - assertEquals(1024, resolverDirectFieldAccessor.getPropertyValue("cacheLimit")); - } - - @Test - public void defaultVelocityViewResolution() { - registry.velocity(); - assertNotNull(registry.getViewResolvers()); - assertEquals(1, registry.getViewResolvers().size()); - assertEquals(VelocityViewResolver.class, registry.getViewResolvers().get(0).getClass()); - VelocityViewResolver resolver = (VelocityViewResolver)registry.getViewResolvers().get(0); - DirectFieldAccessor resolverDirectFieldAccessor = new DirectFieldAccessor(resolver); - assertEquals("", resolverDirectFieldAccessor.getPropertyValue("prefix")); - assertEquals(".vm", resolverDirectFieldAccessor.getPropertyValue("suffix")); - } - - @Test - public void freeMarkerViewResolution() { - registry.freemarker().prefix("/").suffix(".fmt").cache(false); - assertNotNull(registry.getViewResolvers()); - assertEquals(1, registry.getViewResolvers().size()); - assertEquals(FreeMarkerViewResolver.class, registry.getViewResolvers().get(0).getClass()); - FreeMarkerViewResolver resolver = (FreeMarkerViewResolver)registry.getViewResolvers().get(0); - DirectFieldAccessor resolverDirectFieldAccessor = new DirectFieldAccessor(resolver); - assertEquals("/", resolverDirectFieldAccessor.getPropertyValue("prefix")); - assertEquals(".fmt", resolverDirectFieldAccessor.getPropertyValue("suffix")); - assertEquals(0, resolverDirectFieldAccessor.getPropertyValue("cacheLimit")); - } - - @Test - public void defaultFreeMarkerViewResolution() { - registry.freemarker(); - assertNotNull(registry.getViewResolvers()); - assertEquals(1, registry.getViewResolvers().size()); - assertEquals(FreeMarkerViewResolver.class, registry.getViewResolvers().get(0).getClass()); - FreeMarkerViewResolver resolver = (FreeMarkerViewResolver)registry.getViewResolvers().get(0); - DirectFieldAccessor resolverDirectFieldAccessor = new DirectFieldAccessor(resolver); - assertEquals("", resolverDirectFieldAccessor.getPropertyValue("prefix")); - assertEquals(".ftl", resolverDirectFieldAccessor.getPropertyValue("suffix")); - } - - @Test - public void contentNegotiatingViewResolution() { - registry.contentNegotiating().useNotAcceptable(false).defaultViews(new MappingJackson2JsonView()); - assertNotNull(registry.getViewResolvers()); - assertEquals(1, registry.getViewResolvers().size()); - assertEquals(ContentNegotiatingViewResolver.class, registry.getViewResolvers().get(0).getClass()); - } - - @Test - public void multipleViewResolutions() { - registry.jsp().and().beanName(); - assertNotNull(registry.getViewResolvers()); - assertEquals(2, registry.getViewResolvers().size()); - } - -} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistryTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistryTests.java new file mode 100644 index 0000000000..622a3e68c3 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ViewResolverRegistryTests.java @@ -0,0 +1,211 @@ +/* + * 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. + */ + +package org.springframework.web.servlet.config.annotation; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.DirectFieldAccessor; +import org.springframework.core.Ordered; +import org.springframework.web.accept.ContentNegotiationManager; +import org.springframework.web.context.support.StaticWebApplicationContext; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.view.BeanNameViewResolver; +import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; +import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver; +import org.springframework.web.servlet.view.json.MappingJackson2JsonView; +import org.springframework.web.servlet.view.tiles3.TilesConfigurer; +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 org.springframework.web.servlet.view.xml.MarshallingView; + +import java.util.Arrays; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; + +/** + * Test fixture with a {@link ViewResolverRegistry}. + * + * @author Sebastien Deleuze + * @author Rossen Stoyanchev + */ +public class ViewResolverRegistryTests { + + private ViewResolverRegistry registry; + + + @Before + public void setUp() { + StaticWebApplicationContext context = new StaticWebApplicationContext(); + context.registerSingleton("freeMarkerConfigurer", FreeMarkerConfigurer.class); + context.registerSingleton("velocityConfigurer", VelocityConfigurer.class); + context.registerSingleton("tilesConfigurer", TilesConfigurer.class); + this.registry = new ViewResolverRegistry(); + this.registry.setApplicationContext(context); + this.registry.setContentNegotiationManager(new ContentNegotiationManager()); + } + + + @Test + public void order() { + assertEquals(Ordered.LOWEST_PRECEDENCE, this.registry.getOrder()); + this.registry.enableContentNegotiation(); + assertEquals(Ordered.HIGHEST_PRECEDENCE, this.registry.getOrder()); + } + + @Test + public void hasRegistrations() { + assertFalse(this.registry.hasRegistrations()); + this.registry.velocity(); + assertTrue(this.registry.hasRegistrations()); + } + + @Test + public void hasRegistrationsWhenContentNegotiationEnabled() { + assertFalse(this.registry.hasRegistrations()); + this.registry.enableContentNegotiation(); + assertTrue(this.registry.hasRegistrations()); + } + + @Test + public void noResolvers() { + assertNotNull(this.registry.getViewResolvers()); + assertEquals(0, this.registry.getViewResolvers().size()); + assertFalse(this.registry.hasRegistrations()); + } + + @Test + public void customViewResolver() { + InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setPrefix("/"); + viewResolver.setSuffix(".jsp"); + this.registry.viewResolver(viewResolver); + assertSame(viewResolver, this.registry.getViewResolvers().get(0)); + } + + @Test + public void beanName() { + this.registry.beanName(); + assertEquals(1, this.registry.getViewResolvers().size()); + assertEquals(BeanNameViewResolver.class, registry.getViewResolvers().get(0).getClass()); + } + + @Test + public void jspDefaultValues() { + this.registry.jsp(); + InternalResourceViewResolver resolver = checkAndGetResolver(InternalResourceViewResolver.class); + checkPropertyValues(resolver, "prefix", "/WEB-INF/", "suffix", ".jsp"); + } + + @Test + public void jsp() { + this.registry.jsp("/", ".jsp"); + InternalResourceViewResolver resolver = checkAndGetResolver(InternalResourceViewResolver.class); + checkPropertyValues(resolver, "prefix", "/", "suffix", ".jsp"); + } + + @Test + public void jspMultipleResolvers() { + this.registry.jsp().viewNames("view1", "view2"); + this.registry.jsp().viewNames("view3", "view4"); + assertNotNull(this.registry.getViewResolvers()); + assertEquals(2, this.registry.getViewResolvers().size()); + assertEquals(InternalResourceViewResolver.class, this.registry.getViewResolvers().get(0).getClass()); + assertEquals(InternalResourceViewResolver.class, this.registry.getViewResolvers().get(1).getClass()); + } + + @Test + public void tiles() { + this.registry.tiles(); + checkAndGetResolver(TilesViewResolver.class); + } + + @Test + public void velocity() { + this.registry.velocity().prefix("/").suffix(".vm").cache(true); + VelocityViewResolver resolver = checkAndGetResolver(VelocityViewResolver.class); + checkPropertyValues(resolver, "prefix", "/", "suffix", ".vm", "cacheLimit", 1024); + } + + @Test + public void velocityDefaultValues() { + this.registry.velocity(); + VelocityViewResolver resolver = checkAndGetResolver(VelocityViewResolver.class); + checkPropertyValues(resolver, "prefix", "", "suffix", ".vm"); + } + + @Test + public void freeMarker() { + this.registry.freeMarker().prefix("/").suffix(".fmt").cache(false); + FreeMarkerViewResolver resolver = checkAndGetResolver(FreeMarkerViewResolver.class); + checkPropertyValues(resolver, "prefix", "/", "suffix", ".fmt", "cacheLimit", 0); + } + + @Test + public void freeMarkerDefaultValues() { + this.registry.freeMarker(); + FreeMarkerViewResolver resolver = checkAndGetResolver(FreeMarkerViewResolver.class); + checkPropertyValues(resolver, "prefix", "", "suffix", ".ftl"); + } + + @Test + public void contentNegotiation() { + MappingJackson2JsonView view = new MappingJackson2JsonView(); + this.registry.enableContentNegotiation(view); + ContentNegotiatingViewResolver resolver = checkAndGetResolver(ContentNegotiatingViewResolver.class); + assertEquals(Arrays.asList(view), resolver.getDefaultViews()); + assertEquals(Ordered.HIGHEST_PRECEDENCE, this.registry.getOrder()); + } + + @Test + public void contentNegotiationAddsDefaultViewRegistrations() { + MappingJackson2JsonView view1 = new MappingJackson2JsonView(); + this.registry.enableContentNegotiation(view1); + + ContentNegotiatingViewResolver resolver1 = checkAndGetResolver(ContentNegotiatingViewResolver.class); + assertEquals(Arrays.asList(view1), resolver1.getDefaultViews()); + + MarshallingView view2 = new MarshallingView(); + this.registry.enableContentNegotiation(view2); + + ContentNegotiatingViewResolver resolver2 = checkAndGetResolver(ContentNegotiatingViewResolver.class); + assertEquals(Arrays.asList(view1, view2), resolver2.getDefaultViews()); + assertSame(resolver1, resolver2); + } + + + @SuppressWarnings("unchecked") + private T checkAndGetResolver(Class resolverType) { + assertNotNull(this.registry.getViewResolvers()); + assertEquals(1, this.registry.getViewResolvers().size()); + assertEquals(resolverType, this.registry.getViewResolvers().get(0).getClass()); + return (T) registry.getViewResolvers().get(0); + } + + private void checkPropertyValues(ViewResolver resolver, Object... nameValuePairs) { + DirectFieldAccessor accessor = new DirectFieldAccessor(resolver); + for (int i = 0; i < nameValuePairs.length ; i++, i++) { + Object expected = nameValuePairs[i + 1]; + Object actual = accessor.getPropertyValue((String) nameValuePairs[i]); + assertEquals(expected, actual); + } + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java index a1cc57a3d7..17283da269 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java @@ -65,39 +65,46 @@ import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.servlet.resource.ResourceUrlProviderExposingInterceptor; +import org.springframework.web.servlet.view.ViewResolverComposite; import org.springframework.web.util.UrlPathHelper; import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.json.MappingJackson2JsonView; /** - * A test fixture with a sub-class of {@link WebMvcConfigurationSupport} that + * A test fixture with a sub-class of {@link WebMvcConfigurationSupport} that also * implements the various {@link WebMvcConfigurer} extension points. * + * The former doesn't implement the latter but the two must have compatible + * callback method signatures to support moving from simple to advanced + * configuration -- i.e. dropping @EnableWebMvc + WebMvcConfigurer and extending + * directly from WebMvcConfigurationSupport. + * * @author Rossen Stoyanchev * @author Sebastien Deleuze */ public class WebMvcConfigurationSupportExtensionTests { - private TestWebMvcConfigurationSupport webConfig; + private TestWebMvcConfigurationSupport config; + + private StaticWebApplicationContext context; - private StaticWebApplicationContext webAppContext; @Before public void setUp() { - this.webAppContext = new StaticWebApplicationContext(); - this.webAppContext.setServletContext(new MockServletContext(new FileSystemResourceLoader())); - this.webAppContext.registerSingleton("controller", TestController.class); + this.context = new StaticWebApplicationContext(); + this.context.setServletContext(new MockServletContext(new FileSystemResourceLoader())); + this.context.registerSingleton("controller", TestController.class); - this.webConfig = new TestWebMvcConfigurationSupport(); - this.webConfig.setApplicationContext(this.webAppContext); - this.webConfig.setServletContext(this.webAppContext.getServletContext()); + this.config = new TestWebMvcConfigurationSupport(); + this.config.setApplicationContext(this.context); + this.config.setServletContext(this.context.getServletContext()); } @Test public void handlerMappings() throws Exception { - RequestMappingHandlerMapping rmHandlerMapping = webConfig.requestMappingHandlerMapping(); - rmHandlerMapping.setApplicationContext(webAppContext); + RequestMappingHandlerMapping rmHandlerMapping = this.config.requestMappingHandlerMapping(); + rmHandlerMapping.setApplicationContext(this.context); rmHandlerMapping.afterPropertiesSet(); assertEquals(TestPathHelper.class, rmHandlerMapping.getUrlPathHelper().getClass()); assertEquals(TestPathMatcher.class, rmHandlerMapping.getPathMatcher().getClass()); @@ -108,8 +115,8 @@ public class WebMvcConfigurationSupportExtensionTests { assertEquals(ConversionServiceExposingInterceptor.class, chain.getInterceptors()[1].getClass()); assertEquals(ResourceUrlProviderExposingInterceptor.class, chain.getInterceptors()[2].getClass()); - AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) webConfig.viewControllerHandlerMapping(); - handlerMapping.setApplicationContext(webAppContext); + AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) this.config.viewControllerHandlerMapping(); + handlerMapping.setApplicationContext(this.context); assertNotNull(handlerMapping); assertEquals(1, handlerMapping.getOrder()); assertEquals(TestPathHelper.class, handlerMapping.getUrlPathHelper().getClass()); @@ -117,17 +124,17 @@ public class WebMvcConfigurationSupportExtensionTests { HandlerExecutionChain handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/path")); assertNotNull(handler.getHandler()); - handlerMapping = (AbstractHandlerMapping) webConfig.resourceHandlerMapping(); - handlerMapping.setApplicationContext(webAppContext); + handlerMapping = (AbstractHandlerMapping) this.config.resourceHandlerMapping(); + handlerMapping.setApplicationContext(this.context); assertNotNull(handlerMapping); - assertEquals(Integer.MAX_VALUE-1, handlerMapping.getOrder()); + assertEquals(Integer.MAX_VALUE - 1, handlerMapping.getOrder()); assertEquals(TestPathHelper.class, handlerMapping.getUrlPathHelper().getClass()); assertEquals(TestPathMatcher.class, handlerMapping.getPathMatcher().getClass()); handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/resources/foo.gif")); assertNotNull(handler.getHandler()); - handlerMapping = (AbstractHandlerMapping) webConfig.defaultServletHandlerMapping(); - handlerMapping.setApplicationContext(webAppContext); + handlerMapping = (AbstractHandlerMapping) this.config.defaultServletHandlerMapping(); + handlerMapping.setApplicationContext(this.context); assertNotNull(handlerMapping); assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder()); handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/anyPath")); @@ -137,10 +144,10 @@ public class WebMvcConfigurationSupportExtensionTests { @SuppressWarnings("unchecked") @Test public void requestMappingHandlerAdapter() throws Exception { - RequestMappingHandlerAdapter adapter = webConfig.requestMappingHandlerAdapter(); + RequestMappingHandlerAdapter adapter = this.config.requestMappingHandlerAdapter(); // ConversionService - String actual = webConfig.mvcConversionService().convert(new TestBean(), String.class); + String actual = this.config.mvcConversionService().convert(new TestBean(), String.class); assertEquals("converted", actual); // Message converters @@ -174,7 +181,7 @@ public class WebMvcConfigurationSupportExtensionTests { @Test public void webBindingInitializer() throws Exception { - RequestMappingHandlerAdapter adapter = webConfig.requestMappingHandlerAdapter(); + RequestMappingHandlerAdapter adapter = this.config.requestMappingHandlerAdapter(); ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) adapter.getWebBindingInitializer(); assertNotNull(initializer); @@ -192,7 +199,7 @@ public class WebMvcConfigurationSupportExtensionTests { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo.json"); NativeWebRequest webRequest = new ServletWebRequest(request); - ContentNegotiationManager manager = webConfig.requestMappingHandlerMapping().getContentNegotiationManager(); + ContentNegotiationManager manager = this.config.requestMappingHandlerMapping().getContentNegotiationManager(); assertEquals(Arrays.asList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(webRequest)); request.setRequestURI("/foo.xml"); @@ -211,33 +218,38 @@ public class WebMvcConfigurationSupportExtensionTests { @Test public void exceptionResolvers() throws Exception { - HandlerExceptionResolverComposite composite = (HandlerExceptionResolverComposite) webConfig.handlerExceptionResolver(); - assertEquals(1, composite.getExceptionResolvers().size()); + HandlerExceptionResolver exceptionResolver = this.config.handlerExceptionResolver(); + assertEquals(1, ((HandlerExceptionResolverComposite) exceptionResolver).getExceptionResolvers().size()); } + @SuppressWarnings("unchecked") @Test public void viewResolvers() throws Exception { - ViewResolverComposite viewResolver = webConfig.viewResolverComposite(); - assertEquals(Ordered.LOWEST_PRECEDENCE, viewResolver.getOrder()); + ViewResolverComposite viewResolver = (ViewResolverComposite) this.config.mvcViewResolver(); + assertEquals(Ordered.HIGHEST_PRECEDENCE, viewResolver.getOrder()); List viewResolvers = viewResolver.getViewResolvers(); - DirectFieldAccessor viewResolverFieldAccessor = new DirectFieldAccessor(viewResolvers.get(0)); + + DirectFieldAccessor accessor = new DirectFieldAccessor(viewResolvers.get(0)); assertEquals(1, viewResolvers.size()); assertEquals(ContentNegotiatingViewResolver.class, viewResolvers.get(0).getClass()); - assertFalse((Boolean)viewResolverFieldAccessor.getPropertyValue("useNotAcceptableStatusCode")); - List defaultViews = (List)viewResolverFieldAccessor.getPropertyValue("defaultViews"); + assertFalse((Boolean) accessor.getPropertyValue("useNotAcceptableStatusCode")); + assertNotNull(accessor.getPropertyValue("contentNegotiationManager")); + + List defaultViews = (List)accessor.getPropertyValue("defaultViews"); assertNotNull(defaultViews); assertEquals(1, defaultViews.size()); assertEquals(MappingJackson2JsonView.class, defaultViews.get(0).getClass()); - assertNotNull(viewResolverFieldAccessor.getPropertyValue("contentNegotiationManager")); - viewResolvers = (List)viewResolverFieldAccessor.getPropertyValue("viewResolvers"); + + viewResolvers = (List)accessor.getPropertyValue("viewResolvers"); assertNotNull(viewResolvers); assertEquals(1, viewResolvers.size()); assertEquals(InternalResourceViewResolver.class, viewResolvers.get(0).getClass()); - viewResolverFieldAccessor = new DirectFieldAccessor(viewResolvers.get(0)); - assertEquals("/", viewResolverFieldAccessor.getPropertyValue("prefix")); - assertEquals(".jsp", viewResolverFieldAccessor.getPropertyValue("suffix")); + accessor = new DirectFieldAccessor(viewResolvers.get(0)); + assertEquals("/", accessor.getPropertyValue("prefix")); + assertEquals(".jsp", accessor.getPropertyValue("suffix")); } + @Controller private static class TestController { @@ -339,9 +351,9 @@ public class WebMvcConfigurationSupportExtensionTests { } @Override - public void configureViewResolution(ViewResolutionRegistry registry) { + public void configureViewResolvers(ViewResolverRegistry registry) { + registry.enableContentNegotiation(new MappingJackson2JsonView()); registry.jsp("/", ".jsp"); - registry.contentNegotiating().useNotAcceptable(false).defaultViews(new MappingJackson2JsonView()); } @Override @@ -353,7 +365,6 @@ public class WebMvcConfigurationSupportExtensionTests { public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable("default"); } - } private class TestPathHelper extends UrlPathHelper {} 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 f1a0b83027..7e704842a7 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 @@ -49,7 +49,7 @@ import org.springframework.web.method.support.CompositeUriComponentsContributor; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.ViewResolver; -import org.springframework.web.servlet.ViewResolverComposite; +import org.springframework.web.servlet.view.ViewResolverComposite; import org.springframework.web.servlet.handler.AbstractHandlerMapping; import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping; import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor; @@ -207,8 +207,8 @@ public class WebMvcConfigurationSupportTests { public void viewResolvers() throws Exception { ViewResolverComposite compositeResolver = this.wac.getBean(ViewResolverComposite.class); assertEquals(Ordered.LOWEST_PRECEDENCE, compositeResolver.getOrder()); - List viewResolvers = compositeResolver.getViewResolvers(); - assertEquals(0, viewResolvers.size()); + List resolvers = compositeResolver.getViewResolvers(); + assertEquals(0, resolvers.size()); } @Test -- GitLab