Support Java and MVC namespace view resolution config

This commit improves and completes the initial MVC namespace
view resolution implementation. ContentNegotiatingViewResolver
registration is now also supported.

Java Config view resolution support has been added.
FreeMarker, Velocity and Tiles view configurers are registered
depending on the classpath thanks to an ImportSelector.

For both, a default configuration is provided and documented.

Issue: SPR-7093
This commit is contained in:
Sebastien Deleuze
2014-06-19 11:40:14 +02:00
committed by Rossen Stoyanchev
parent a26b1ef8d9
commit cc7e8f5558
34 changed files with 1995 additions and 263 deletions

View File

@@ -0,0 +1,100 @@
/*
* 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;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.Ordered;
import org.springframework.web.context.ServletContextAware;
import javax.servlet.ServletContext;
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.
*
* @author Sebastien Deleuze
* @since 4.1
*/
public class ViewResolverComposite implements ApplicationContextAware, ServletContextAware, ViewResolver, Ordered {
private List<ViewResolver> viewResolvers;
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<ViewResolver> viewResolvers) {
this.viewResolvers = viewResolvers;
}
/**
* Return the list of view viewResolvers to delegate to.
*/
public List<ViewResolver> getViewResolvers() {
return Collections.unmodifiableList(viewResolvers);
}
@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;
}
}
}
return null;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (viewResolvers != null) {
for (ViewResolver viewResolver : viewResolvers) {
if(viewResolver instanceof ApplicationContextAware) {
((ApplicationContextAware)viewResolver).setApplicationContext(applicationContext);
}
}
}
}
@Override
public void setServletContext(ServletContext servletContext) {
if (viewResolvers != null) {
for (ViewResolver viewResolver : viewResolvers) {
if(viewResolver instanceof ServletContextAware) {
((ServletContextAware)viewResolver).setServletContext(servletContext);
}
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* 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.
@@ -28,14 +28,14 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
*/
public class MvcNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
registerBeanDefinitionParser("view-resolution", new ViewResolutionBeanDefinitionParser());
}
}

View File

@@ -0,0 +1,252 @@
/*
* 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;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
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.ViewResolver;
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 org.w3c.dom.Element;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses a
* {@code view-resolution} element to register a set of {@link ViewResolver} definitions.
*
* @author Sivaprasad Valluru
* @author Sebastien Deleuze
* @since 4.1
*/
public class ViewResolutionBeanDefinitionParser implements BeanDefinitionParser {
private Object source;
public BeanDefinition parse(Element element, ParserContext parserContext) {
source= parserContext.extractSource(element);
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(),source);
parserContext.pushContainingComponent(compDefinition);
List<Element> viewResolverElements =
DomUtils.getChildElementsByTagName(element, new String[] { "jsp", "tiles", "bean-name", "freemarker", "velocity", "bean", "ref" });
ManagedList<Object> viewResolvers = new ManagedList<Object>();
viewResolvers.setSource(parserContext.extractSource(element));
int order = 0;
for (Element viewResolverElement : viewResolverElements) {
if ("jsp".equals(viewResolverElement.getLocalName())) {
viewResolvers.add(registerInternalResourceViewResolverBean(viewResolverElement, parserContext, order));
}
if("bean-name".equals(viewResolverElement.getLocalName())){
viewResolvers.add(registerBeanNameViewResolverBean(viewResolverElement, parserContext, order));
}
if ("tiles".equals(viewResolverElement.getLocalName())) {
viewResolvers.add(registerTilesViewResolverBean(viewResolverElement, parserContext, order));
registerTilesConfigurerBean(viewResolverElement, parserContext);
}
if("freemarker".equals(viewResolverElement.getLocalName())){
viewResolvers.add(registerFreemarkerViewResolverBean(viewResolverElement, parserContext, order));
registerFreemarkerConfigurerBean(viewResolverElement, parserContext);
}
if("velocity".equals(viewResolverElement.getLocalName())){
viewResolvers.add(registerVelocityViewResolverBean(viewResolverElement, parserContext, order));
registerVelocityConfigurerBean(viewResolverElement, parserContext);
}
if("bean".equals(viewResolverElement.getLocalName()) || "ref".equals(viewResolverElement.getLocalName())){
viewResolvers.add(parserContext.getDelegate().parsePropertySubElement(viewResolverElement, null));
}
order++;
}
viewResolverElements = DomUtils.getChildElementsByTagName(element, new String[] { "content-negotiating" });
if(!viewResolverElements.isEmpty()) {
registerContentNegotiatingViewResolverBean(viewResolverElements.get(0), parserContext, viewResolvers);
}
parserContext.popAndRegisterContainingComponent();
return null;
}
private BeanDefinition registerBean(Map<String,Object> propertyMap,Class<?> beanClass, ParserContext parserContext ){
RootBeanDefinition beanDef = new RootBeanDefinition(beanClass);
beanDef.setSource(source);
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
for(String propertyName:propertyMap.keySet()){
beanDef.getPropertyValues().add(propertyName, propertyMap.get(propertyName));
}
String beanName = parserContext.getReaderContext().generateBeanName(beanDef);
parserContext.getRegistry().registerBeanDefinition(beanName, beanDef);
parserContext.registerComponent(new BeanComponentDefinition(beanDef, beanName));
return beanDef;
}
private BeanDefinition registerContentNegotiatingViewResolverBean(Element viewResolverElement, ParserContext parserContext, ManagedList<Object> viewResolvers) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
ManagedList<Object> defaultViewBeanDefinitions = new ManagedList<Object>();
List<Element> defaultViewElements =
DomUtils.getChildElementsByTagName(viewResolverElement, new String[] { "default-views" });
if(!defaultViewElements.isEmpty()) {
for(Element beanElem : DomUtils.getChildElementsByTagName(defaultViewElements.get(0), "bean", "ref")) {
defaultViewBeanDefinitions.add(parserContext.getDelegate().parsePropertySubElement(beanElem, null));
}
}
if(viewResolverElement.hasAttribute("use-not-acceptable")) {
propertyMap.put("useNotAcceptableStatusCode", viewResolverElement.getAttribute("use-not-acceptable"));
}
if(viewResolverElement.hasAttribute("manager")) {
propertyMap.put("contentNegotiationManager", new RuntimeBeanReference(viewResolverElement.getAttribute("manager")));
} else {
propertyMap.put("contentNegotiationManager", new RuntimeBeanReference("mvcContentNegotiationManager"));
}
if(viewResolvers != null && !viewResolvers.isEmpty()) {
propertyMap.put("viewResolvers", viewResolvers);
}
if(defaultViewBeanDefinitions != null && !defaultViewBeanDefinitions.isEmpty()) {
propertyMap.put("defaultViews", defaultViewBeanDefinitions);
}
return registerBean(propertyMap, ContentNegotiatingViewResolver.class, parserContext);
}
private BeanDefinition registerFreemarkerConfigurerBean(Element viewResolverElement, ParserContext parserContext) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("template-loader-paths")) {
String[] paths = StringUtils.commaDelimitedListToStringArray(viewResolverElement.getAttribute("template-loader-paths"));
propertyMap.put("templateLoaderPaths", paths);
} else {
propertyMap.put("templateLoaderPaths", new String[]{"/WEB-INF/"});
}
return registerBean(propertyMap, FreeMarkerConfigurer.class, parserContext);
}
private BeanDefinition registerFreemarkerViewResolverBean(Element viewResolverElement, ParserContext parserContext, int order) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("prefix")) {
propertyMap.put("prefix", viewResolverElement.getAttribute("prefix"));
}
if(viewResolverElement.hasAttribute("suffix")) {
propertyMap.put("suffix", viewResolverElement.getAttribute("suffix"));
}
else {
propertyMap.put("suffix", ".ftl");
}
if(viewResolverElement.hasAttribute("cache")) {
propertyMap.put("cache", viewResolverElement.getAttribute("cache"));
}
propertyMap.put("order", order);
return registerBean(propertyMap, FreeMarkerViewResolver.class, parserContext);
}
private BeanDefinition registerVelocityConfigurerBean(Element viewResolverElement, ParserContext parserContext) {
String resourceLoaderPath = viewResolverElement.getAttribute("resource-loader-path");
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("resource-loader-path")) {
propertyMap.put("resourceLoaderPath", resourceLoaderPath);
} else {
propertyMap.put("resourceLoaderPath", "/WEB-INF/");
}
return registerBean(propertyMap, VelocityConfigurer.class, parserContext);
}
private BeanDefinition registerVelocityViewResolverBean(Element viewResolverElement, ParserContext parserContext, int order) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("prefix")) {
propertyMap.put("prefix", viewResolverElement.getAttribute("prefix"));
}
if(viewResolverElement.hasAttribute("suffix")) {
propertyMap.put("suffix", viewResolverElement.getAttribute("suffix"));
}
else {
propertyMap.put("suffix", ".vm");
}
if(viewResolverElement.hasAttribute("cache")) {
propertyMap.put("cache", viewResolverElement.getAttribute("cache"));
}
propertyMap.put("order", order);
return registerBean(propertyMap, VelocityViewResolver.class, parserContext);
}
private BeanDefinition registerBeanNameViewResolverBean(Element viewResolverElement, ParserContext parserContext, int order) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
propertyMap.put("order", order);
return registerBean(propertyMap, BeanNameViewResolver.class, parserContext);
}
private BeanDefinition registerTilesConfigurerBean(Element viewResolverElement, ParserContext parserContext) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("definitions")) {
String[] definitions = StringUtils.commaDelimitedListToStringArray(viewResolverElement.getAttribute("definitions"));
propertyMap.put("definitions", definitions);
}
if(viewResolverElement.hasAttribute("check-refresh")) {
propertyMap.put("checkRefresh", viewResolverElement.getAttribute("check-refresh"));
}
return registerBean(propertyMap, TilesConfigurer.class, parserContext);
}
private BeanDefinition registerTilesViewResolverBean(Element viewResolverElement, ParserContext parserContext, int order) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("prefix")) {
propertyMap.put("prefix", viewResolverElement.getAttribute("prefix"));
}
if(viewResolverElement.hasAttribute("suffix")) {
propertyMap.put("suffix", viewResolverElement.getAttribute("suffix"));
}
propertyMap.put("order", order);
return registerBean(propertyMap, TilesViewResolver.class, parserContext);
}
private BeanDefinition registerInternalResourceViewResolverBean(Element viewResolverElement, ParserContext parserContext, int order) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("prefix")) {
propertyMap.put("prefix", viewResolverElement.getAttribute("prefix"));
}
else {
propertyMap.put("prefix", "/WEB-INF/");
}
if(viewResolverElement.hasAttribute("suffix")) {
propertyMap.put("suffix", viewResolverElement.getAttribute("suffix"));
}
else {
propertyMap.put("suffix", ".jsp");
}
propertyMap.put("order", order);
return registerBean(propertyMap, InternalResourceViewResolver.class, parserContext);
}
}

View File

@@ -1,158 +0,0 @@
package org.springframework.web.servlet.config;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.xml.DomUtils;
import org.springframework.web.servlet.view.BeanNameViewResolver;
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.TilesView;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
import org.w3c.dom.Element;
public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser {
private static final String INTERNAL_VIEW_RESOLVER_BEAN_NAME =
"org.springframework.web.servlet.view.InternalResourceViewResolver";
private static final String TILES3_VIEW_RESOLVER_BEAN_NAME =
"org.springframework.web.servlet.view.tiles3.TilesViewResolver";
private static final String TILES3_CONFIGURER_BEAN_NAME =
"org.springframework.web.servlet.view.tiles3.TilesConfigurer";
private static final String BEANNAME_VIEW_RESOLVER_BEAN_NAME =
"org.springframework.web.servlet.view.BeanNameViewResolver";
private static final String FREEMARKER_CONFIGURER_BEAN_NAME =
"org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer";
private static final String FREEMARKER_VIEW_RESOLVER_BEAN_NAME =
"org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver";
private ParserContext parserContext;
private Object source;
public BeanDefinition parse(Element element, ParserContext parserContext) {
this.parserContext=parserContext;
source= parserContext.extractSource(element);
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(),source);
parserContext.pushContainingComponent(compDefinition);
List<Element> viewResolverElements = //DomUtils.getChildElements(element);
DomUtils.getChildElementsByTagName(element, new String[] { "jsp", "tiles","bean-name","freemarker" });
for (Element viewResolverElement : viewResolverElements) {
if ("jsp".equals(viewResolverElement.getLocalName())) {
registerInternalResourceViewResolverBean(parserContext,viewResolverElement);
System.out.println("Registered Internalresource view resolver");
}
if("bean-name".equals(viewResolverElement.getLocalName())){
registerBeanNameViewResolverBean(parserContext,viewResolverElement);
System.out.println("Registered BeanNameViewResolverBean view resolver");
}
if ("tiles".equals(viewResolverElement.getLocalName())) {
registerTilesViewResolverBean(parserContext,viewResolverElement);
registerTilesConfigurerBean(parserContext,viewResolverElement);
}
if("freemarker".equals(viewResolverElement.getLocalName())){
registerFreemarkerViewResolverBean(parserContext,viewResolverElement);
registerFreemarkerConfigurerBean(parserContext,viewResolverElement);
}
}
// MvcNamespaceUtils.registerDefaultComponents(parserContext, source);
parserContext.popAndRegisterContainingComponent();
return null;
}
private void registerBean(String beanName,Map<String,Object> propertyMap,Class<?> beanClass ){
RootBeanDefinition beanDef = new RootBeanDefinition(beanClass);
beanDef.setSource(source);
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
for(String propertyName:propertyMap.keySet()){
beanDef.getPropertyValues().add(propertyName, propertyMap.get(propertyName));
}
parserContext.getRegistry().registerBeanDefinition(beanName, beanDef);
parserContext.registerComponent(new BeanComponentDefinition(beanDef, beanName));
}
private void registerFreemarkerConfigurerBean(ParserContext parserContext, Element viewResolverElement) {
String templateLoaderPath=viewResolverElement.getAttribute("templateLoaderPath");
Map<String, Object> propertyMap= new HashMap<String, Object>();
propertyMap.put("templateLoaderPath", templateLoaderPath);
registerBean(FREEMARKER_CONFIGURER_BEAN_NAME, propertyMap, FreeMarkerConfigurer.class);
}
private void registerFreemarkerViewResolverBean(ParserContext parserContext, Element viewResolverElement) {
if (!parserContext.getRegistry().containsBeanDefinition(FREEMARKER_VIEW_RESOLVER_BEAN_NAME)) {
Map<String, Object> propertyMap= new HashMap<String, Object>();
propertyMap.put("prefix", viewResolverElement.getAttribute("prefix"));
propertyMap.put("suffix", viewResolverElement.getAttribute("suffix"));
propertyMap.put("order", 4);
registerBean(FREEMARKER_VIEW_RESOLVER_BEAN_NAME, propertyMap, FreeMarkerViewResolver.class);
}
}
private void registerBeanNameViewResolverBean(ParserContext parserContext, Element viewResolverElement) {
if (!parserContext.getRegistry().containsBeanDefinition(BEANNAME_VIEW_RESOLVER_BEAN_NAME)) {
Map<String, Object> propertyMap= new HashMap<String, Object>();
propertyMap.put("order", 3);
registerBean(BEANNAME_VIEW_RESOLVER_BEAN_NAME, propertyMap, BeanNameViewResolver.class);
System.out.println("Registered BeanNameViewResolverBean view resolver");
}
}
private void registerTilesConfigurerBean(ParserContext parserContext,Element viewResolverElement) {
if (!parserContext.getRegistry().containsBeanDefinition(TILES3_CONFIGURER_BEAN_NAME)) {
Map<String, Object> propertyMap= new HashMap<String, Object>();
propertyMap.put("definitions", viewResolverElement.getAttribute("definitions"));
registerBean(TILES3_CONFIGURER_BEAN_NAME, propertyMap, TilesConfigurer.class);
}
}
private void registerTilesViewResolverBean(ParserContext parserContext, Element viewResolverElement) {
if (!parserContext.getRegistry().containsBeanDefinition(TILES3_VIEW_RESOLVER_BEAN_NAME)) {
Map<String, Object> propertyMap= new HashMap<String, Object>();
propertyMap.put("viewClass", TilesView.class);
propertyMap.put("order", 1);
registerBean(TILES3_VIEW_RESOLVER_BEAN_NAME, propertyMap, TilesViewResolver.class);
}
}
private void registerInternalResourceViewResolverBean(ParserContext parserContext, Element viewResolverElement) {
if (!parserContext.getRegistry().containsBeanDefinition(INTERNAL_VIEW_RESOLVER_BEAN_NAME)) {
Map<String, Object> propertyMap= new HashMap<String, Object>();
propertyMap.put("prefix", viewResolverElement.getAttribute("prefix"));
propertyMap.put("suffix", viewResolverElement.getAttribute("suffix"));
propertyMap.put("order", 2);
registerBean(INTERNAL_VIEW_RESOLVER_BEAN_NAME, propertyMap, InternalResourceViewResolver.class);
}
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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<BeanNameViewResolver> {
public BeanNameRegistration(ViewResolutionRegistry registry) {
super(registry, new BeanNameViewResolver());
}
}

View File

@@ -0,0 +1,71 @@
/*
* 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<ContentNegotiatingViewResolver> {
private List<View> 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<View>();
}
this.defaultViews.addAll(Arrays.asList(defaultViews));
return this;
}
@Override
protected ContentNegotiatingViewResolver getViewResolver() {
this.viewResolver.setDefaultViews(this.defaultViews);
return super.getViewResolver();
}
}

View File

@@ -75,6 +75,11 @@ public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
this.configurers.addViewControllers(registry);
}
@Override
protected void configureViewResolution(ViewResolutionRegistry registry) {
this.configurers.configureViewResolution(registry);
}
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
this.configurers.addResourceHandlers(registry);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* 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
@@ -84,11 +84,12 @@ import org.springframework.context.annotation.Import;
*
* @author Dave Syer
* @author Rossen Stoyanchev
* @author Sebastien Deleuze
* @since 3.1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
@Import({DelegatingWebMvcConfiguration.class, ViewConfigurationsImportSelector.class})
public @interface EnableWebMvc {
}

View File

@@ -0,0 +1,59 @@
/*
* 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.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import java.util.List;
/**
* This class creates a FreeMarkerConfigurer bean.
* It is typically imported by adding {@link EnableWebMvc @EnableWebMvc} to an
* application {@link Configuration @Configuration} class when FreeMarker is
* in the classpath.
*
* @author Sebastien Deleuze
* @since 4.1
* @see org.springframework.web.servlet.config.annotation.ViewConfigurationsImportSelector
*/
@Configuration
public class FreeMarkerConfigurerConfigurationSupport {
private List<WebMvcConfigurationSupport> webMvcConfigurationSupports;
@Autowired(required = false)
public void setWebMvcConfigurationSupports(List<WebMvcConfigurationSupport> webMvcConfigurationSupports) {
this.webMvcConfigurationSupports = webMvcConfigurationSupports;
}
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = null;
if(webMvcConfigurationSupports != null) {
for(WebMvcConfigurationSupport configurationSupport : webMvcConfigurationSupports) {
configurer = configurationSupport.getViewResolutionRegistry().getFreeMarkerConfigurer();
if(configurer != null) {
break;
}
}
}
return configurer;
}
}

View File

@@ -0,0 +1,94 @@
/*
* 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.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import java.util.Arrays;
import java.util.List;
/**
* 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<FreeMarkerViewResolver> {
private final FreeMarkerConfigurer configurer;
private List<String> templateLoaderPaths;
public FreeMarkerRegistration(ViewResolutionRegistry registry) {
super(registry, new FreeMarkerViewResolver());
this.configurer = new FreeMarkerConfigurer();
this.prefix("");
this.suffix(".ftl");
this.templateLoaderPath("/WEB-INF/");
}
/**
* 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;
}
/**
* Set a List of {@code TemplateLoader}s that will be used to search
* for templates.
*
* @see org.springframework.ui.freemarker.FreeMarkerConfigurationFactory#setTemplateLoaderPaths(String...)
*/
public FreeMarkerRegistration templateLoaderPath(String... templateLoaderPath) {
this.templateLoaderPaths= Arrays.asList(templateLoaderPath);
return this;
}
protected FreeMarkerConfigurer getConfigurer() {
if(this.templateLoaderPaths != null && !this.templateLoaderPaths.isEmpty()) {
this.configurer.setTemplateLoaderPaths(this.templateLoaderPaths.toArray(new String[0]));
}
return this.configurer;
}
}

View File

@@ -0,0 +1,40 @@
/*
* 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<InternalResourceViewResolver> {
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);
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import java.util.List;
/**
* This class creates a TilesConfigurer bean.
* It is typically imported by adding {@link EnableWebMvc @EnableWebMvc} to an
* application {@link Configuration @Configuration} class when Tiles 3 is
* in the classpath.
*
* @author Sebastien Deleuze
* @since 4.1
* @see org.springframework.web.servlet.config.annotation.ViewConfigurationsImportSelector
*/
@Configuration
public class TilesConfigurerConfigurationSupport {
private List<WebMvcConfigurationSupport> webMvcConfigurationSupports;
@Autowired(required = false)
public void setWebMvcConfigurationSupports(List<WebMvcConfigurationSupport> webMvcConfigurationSupports) {
this.webMvcConfigurationSupports = webMvcConfigurationSupports;
}
@Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer configurer = null;
if(webMvcConfigurationSupports != null) {
for(WebMvcConfigurationSupport configurationSupport : webMvcConfigurationSupports) {
configurer = configurationSupport.getViewResolutionRegistry().getTilesConfigurer();
if(configurer != null) {
break;
}
}
}
return configurer;
}
}

View File

@@ -0,0 +1,99 @@
/*
* 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.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 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<TilesViewResolver> {
private List<String> definitions;
private Boolean checkRefresh;
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;
}
/**
* Set the Tiles definitions, i.e. a single value or a list of files containing the definitions.
*
* @see TilesConfigurer#setDefinitions(String...)
*/
public TilesRegistration definition(String... definitions) {
if(this.definitions == null) {
this.definitions = new ArrayList<String>();
}
this.definitions.addAll(Arrays.asList(definitions));
return this;
}
/**
* Set whether to check Tiles definition files for a refresh at runtime.
*
* @see TilesConfigurer#setCheckRefresh(boolean)
*/
public TilesRegistration checkRefresh(boolean checkRefresh) {
this.checkRefresh = checkRefresh;
return this;
}
protected TilesConfigurer getTilesConfigurer() {
TilesConfigurer tilesConfigurer = new TilesConfigurer();
if(this.definitions != null && !this.definitions.isEmpty()) {
tilesConfigurer.setDefinitions(this.definitions.toArray(new String[0]));
}
if(this.checkRefresh != null) {
tilesConfigurer.setCheckRefresh(this.checkRefresh);
}
return tilesConfigurer;
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
import java.util.List;
/**
* This class creates the VelocityConfigurer bean.
* It is typically imported by adding {@link EnableWebMvc @EnableWebMvc} to an
* application {@link Configuration @Configuration} class when Velocity in the classpath.
*
* @author Sebastien Deleuze
* @since 4.1
* @see org.springframework.web.servlet.config.annotation.ViewConfigurationsImportSelector
*/
@Configuration
public class VelocityConfigurerConfigurationSupport {
private List<WebMvcConfigurationSupport> webMvcConfigurationSupports;
@Autowired(required = false)
public void setWebMvcConfigurationSupports(List<WebMvcConfigurationSupport> webMvcConfigurationSupports) {
this.webMvcConfigurationSupports = webMvcConfigurationSupports;
}
@Bean
public VelocityConfigurer velocityConfigurer() {
VelocityConfigurer configurer = null;
if(webMvcConfigurationSupports != null) {
for(WebMvcConfigurationSupport configurationSupport : webMvcConfigurationSupports) {
configurer = configurationSupport.getViewResolutionRegistry().getVelocityConfigurer();
if(configurer != null) {
break;
}
}
}
return configurer;
}
}

View File

@@ -0,0 +1,86 @@
/*
* 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.VelocityConfigurer;
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<VelocityViewResolver> {
private final VelocityConfigurer configurer;
public VelocityRegistration(ViewResolutionRegistry registry) {
super(registry, new VelocityViewResolver());
this.configurer = new VelocityConfigurer();
this.prefix("");
this.suffix(".vm");
this.resourceLoaderPath("/WEB-INF/");
}
/**
* Set the Velocity resource loader path via a Spring resource location.
*
* @see org.springframework.web.servlet.view.velocity.VelocityConfigurer#setResourceLoaderPath(String)
*/
public VelocityRegistration resourceLoaderPath(String resourceLoaderPath) {
this.configurer.setResourceLoaderPath(resourceLoaderPath);
return this;
}
/**
* 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;
}
protected VelocityConfigurer getConfigurer() {
return this.configurer;
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;
import java.util.ArrayList;
import java.util.List;
/**
* This class imports @{@link org.springframework.context.annotation.Configuration}
* classes for view configurers based on a classpath criteria.
*
* @author Sebastien Deleuze
* @since 4.1
*/
public class ViewConfigurationsImportSelector implements ImportSelector {
private static final boolean tilesPresent =
ClassUtils.isPresent("org.apache.tiles.startup.TilesInitializer", ViewConfigurationsImportSelector.class.getClassLoader());
private static final boolean velocityPresent =
ClassUtils.isPresent("org.apache.velocity.app.VelocityEngine", ViewConfigurationsImportSelector.class.getClassLoader());
private static final boolean freeMarkerPresent =
ClassUtils.isPresent("freemarker.template.Configuration", ViewConfigurationsImportSelector.class.getClassLoader());
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
List<String> configurationClasses = new ArrayList<String>();
if(tilesPresent) {
configurationClasses.add(TilesConfigurerConfigurationSupport.class.getName());
}
if(velocityPresent) {
configurationClasses.add(VelocityConfigurerConfigurationSupport.class.getName());
}
if(freeMarkerPresent) {
configurationClasses.add(FreeMarkerConfigurerConfigurationSupport.class.getName());
}
return configurationClasses.toArray(new String[0]);
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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<T extends ViewResolver> {
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;
}
}

View File

@@ -0,0 +1,164 @@
/*
* 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.ViewResolver;
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<ViewResolutionRegistration<?>> registrations = new ArrayList<ViewResolutionRegistration<?>>();
/**
* Register a custom {@link ViewResolver} bean.
*/
public ViewResolutionRegistration<ViewResolver> addViewResolver(ViewResolver viewResolver) {
ViewResolutionRegistration<ViewResolver> registration = new ViewResolutionRegistration<ViewResolver>(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() {
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() {
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() {
FreeMarkerRegistration registration = new FreeMarkerRegistration(this);
addAndCheckViewResolution(registration);
return registration;
}
/**
* 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<ViewResolver> getViewResolvers() {
List<ViewResolver> viewResolvers = new ArrayList<ViewResolver>();
for(ViewResolutionRegistration<?> registration : this.registrations) {
viewResolvers.add(registration.getViewResolver());
}
return viewResolvers;
}
protected TilesConfigurer getTilesConfigurer() {
for(ViewResolutionRegistration<?> registration : this.registrations) {
if(registration instanceof TilesRegistration) {
return ((TilesRegistration) registration).getTilesConfigurer();
}
}
return null;
}
protected FreeMarkerConfigurer getFreeMarkerConfigurer() {
for(ViewResolutionRegistration<?> registration : this.registrations) {
if(registration instanceof FreeMarkerRegistration) {
return ((FreeMarkerRegistration) registration).getConfigurer();
}
}
return null;
}
protected VelocityConfigurer getVelocityConfigurer() {
for(ViewResolutionRegistration<?> registration : this.registrations) {
if(registration instanceof VelocityRegistration) {
return ((VelocityRegistration) registration).getConfigurer();
}
}
return null;
}
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);
}
}

View File

@@ -64,9 +64,7 @@ import org.springframework.web.context.ServletContextAware;
import org.springframework.web.method.support.CompositeUriComponentsContributor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.*;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
@@ -83,6 +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.util.UrlPathHelper;
/**
@@ -150,12 +149,25 @@ import org.springframework.web.util.UrlPathHelper;
* libraries available on the classpath.
* </ul>
*
* <p>When extending directly from this class instead of using
* {@link EnableWebMvc @EnableWebMvc}, an extra step is needed if you want to use Tiles, FreeMarker
* or Velocity view resolution configuration. Since view configurer beans are registered in their own
* {@link org.springframework.web.servlet.config.annotation.TilesConfigurerConfigurationSupport},
* {@link org.springframework.web.servlet.config.annotation.FreeMarkerConfigurerConfigurationSupport}
* and {@link org.springframework.web.servlet.config.annotation.VelocityConfigurerConfigurationSupport}
* classes, you should also extend those configuration classes (only the ones
* related to the view technology you are using), or register your own
* {@link org.springframework.web.servlet.view.tiles3.TilesConfigurer},
* {@link org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer} or
* {@link org.springframework.web.servlet.view.velocity.VelocityConfigurer} beans.
*
* @see EnableWebMvc
* @see WebMvcConfigurer
* @see WebMvcConfigurerAdapter
*
* @author Rossen Stoyanchev
* @author Brian Clozel
* @author Sebastien Deleuze
* @since 3.1
*/
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
@@ -186,6 +198,7 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
private PathMatchConfigurer pathMatchConfigurer;
private ViewResolutionRegistry viewResolutionRegistry;
/**
* Set the {@link javax.servlet.ServletContext}, e.g. for resource handling,
@@ -342,6 +355,13 @@ 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.
@@ -771,6 +791,46 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
exceptionResolvers.add(new DefaultHandlerExceptionResolver());
}
/**
* Register a {@link ViewResolverComposite} that contains an ordered list of
* view resolvers obtained either through
* {@link #configureViewResolution(ViewResolutionRegistry)}.
*/
@Bean
public ViewResolverComposite viewResolverComposite() {
ViewResolutionRegistry registry = getViewResolutionRegistry();
ViewResolverComposite compositeViewResolver = new ViewResolverComposite();
List<ViewResolver> viewResolvers = registry.getViewResolvers();
ContentNegotiatingViewResolver contentNegotiatingViewResolver = null;
List<ViewResolver> filteredViewResolvers = new ArrayList<ViewResolver>();
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<ViewResolver>();
viewResolvers.add(contentNegotiatingViewResolver);
}
compositeViewResolver.setViewResolvers(viewResolvers);
compositeViewResolver.setApplicationContext(this.applicationContext);
compositeViewResolver.setServletContext(this.servletContext);
return compositeViewResolver;
}
protected ViewResolutionRegistry getViewResolutionRegistry() {
if(this.viewResolutionRegistry == null) {
this.viewResolutionRegistry = new ViewResolutionRegistry();
configureViewResolution(this.viewResolutionRegistry);
}
return this.viewResolutionRegistry;
}
private final static class EmptyHandlerMapping extends AbstractHandlerMapping {
@Override

View File

@@ -138,6 +138,11 @@ public interface WebMvcConfigurer {
*/
void addViewControllers(ViewControllerRegistry registry);
/**
* Configure view resolution to translate view names to view implementations.
*/
void configureViewResolution(ViewResolutionRegistry registry);
/**
* Add handlers to serve static resources such as images, js, and, css
* files from specific locations under web application root, the classpath,

View File

@@ -133,6 +133,14 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
public void addViewControllers(ViewControllerRegistry registry) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.

View File

@@ -113,6 +113,13 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer {
}
}
@Override
public void configureViewResolution(ViewResolutionRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureViewResolution(registry);
}
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {