提交 446dfdbf 编写于 作者: C Chris Beams

Introduce @EnableMvcConfiguration

上级 01e5120a
......@@ -18,8 +18,6 @@ package org.springframework.web.servlet.config;
import java.util.List;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
......@@ -50,11 +48,12 @@ import org.springframework.web.bind.support.WebArgumentResolver;
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
import org.springframework.web.servlet.handler.MappedInterceptor;
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodMapping;
import org.springframework.web.servlet.mvc.method.annotation.support.ServletWebArgumentResolverAdapter;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
import org.w3c.dom.Element;
/**
* {@link BeanDefinitionParser} that parses the {@code annotation-driven} element to configure a Spring MVC web
......@@ -146,7 +145,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, csInterceptorDef);
String mappedInterceptorName = parserContext.getReaderContext().registerWithGeneratedName(mappedCsInterceptorDef);
RootBeanDefinition methodExceptionResolver = new RootBeanDefinition(RequestMappingHandlerMethodExceptionResolver.class);
RootBeanDefinition methodExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
methodExceptionResolver.setSource(source);
methodExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
methodExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);
......
/*
* Copyright 2002-2011 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 java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler;
/**
* Helps with configuring a handler for serving static resources by forwarding to the Servlet container's default
* Servlet. This is commonly used when the {@link DispatcherServlet} is mapped to "/", which results in cleaner
* URLs (without a servlet prefix) but may need to still allow some requests (e.g. static resources) to be handled
* by the Servlet container's default servlet.
*
* <p>It is important the configured handler remains last in the order of all {@link HandlerMapping} instances in
* the Spring MVC web application context. That is is the case if relying on @{@link EnableMvcConfiguration}.
* However, if you register your own HandlerMapping instance sure to set its "order" property to a value lower
* than that of the {@link DefaultServletHttpRequestHandler}, which is {@link Integer#MAX_VALUE}.
*
* @author Rossen Stoyanchev
* @since 3.1
*
* @see ResourceConfigurer
*/
public class DefaultServletHandlerConfigurer {
private DefaultServletHttpRequestHandler requestHandler;
private final ServletContext servletContext;
public DefaultServletHandlerConfigurer(ServletContext servletContext) {
this.servletContext = servletContext;
}
/**
* Enable forwarding to the Servlet container default servlet. The {@link DefaultServletHttpRequestHandler}
* will try to auto-detect the default Servlet at startup using a list of known names. Alternatively, you can
* specify the name of the default Servlet, see {@link #enable(String)}.
*/
public void enable() {
enable(null);
}
/**
* Enable forwarding to the Servlet container default servlet specifying explicitly the name of the default
* Servlet to forward static resource requests to. This is useful when the default Servlet cannot be detected
* (e.g. when using an unknown container or when it has been manually configured).
*/
public void enable(String defaultServletName) {
requestHandler = new DefaultServletHttpRequestHandler();
requestHandler.setDefaultServletName(defaultServletName);
requestHandler.setServletContext(servletContext);
}
/**
* Return a {@link SimpleUrlHandlerMapping} instance ordered at {@link Integer#MAX_VALUE} containing a
* {@link DefaultServletHttpRequestHandler} mapped to {@code /**}.
*/
protected SimpleUrlHandlerMapping getHandlerMapping() {
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
handlerMapping.setOrder(Integer.MAX_VALUE);
handlerMapping.setUrlMap(getUrlMap());
return handlerMapping;
}
private Map<String, HttpRequestHandler> getUrlMap() {
Map<String, HttpRequestHandler> urlMap = new HashMap<String, HttpRequestHandler>();
if (requestHandler != null) {
urlMap.put("/**", requestHandler);
}
return urlMap ;
}
}
\ No newline at end of file
/*
* Copyright 2002-2010 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 java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.DispatcherServlet;
/**
* Enables default Spring MVC configuration and registers Spring MVC infrastructure components expected by the
* {@link DispatcherServlet}. To use this annotation simply place it on an application @{@link Configuration} class
* and that will in turn import default Spring MVC configuration including support for annotated methods
* in @{@link Controller} classes.
* <pre>
* &#064;Configuration
* &#064;EnableMvcConfiguration
* &#064;ComponentScan(
* basePackageClasses = { MyMvcConfiguration.class },
* excludeFilters = { @Filter(type = FilterType.ANNOTATION, value = Configuration.class) }
* )
* public class MyMvcConfiguration {
*
* }
* </pre>
* <p>To customize the imported configuration you simply implement {@link MvcConfigurer}, or more likely extend
* {@link MvcConfigurerSupport} overriding selected methods only. The most obvious place to do this is
* the @{@link Configuration} class that enabled the Spring MVC configuration via @{@link EnableMvcConfiguration}.
* However any @{@link Configuration} class and more generally any Spring bean can implement {@link MvcConfigurer}
* to be detected and given an opportunity to customize Spring MVC configuration at startup.
* <pre>
* &#064;Configuration
* &#064;EnableMvcConfiguration
* &#064;ComponentScan(
* basePackageClasses = { MyMvcConfiguration.class },
* excludeFilters = { @Filter(type = FilterType.ANNOTATION, value = Configuration.class) }
* )
* public class MyMvcConfiguration extends MvcConfigurerSupport {
*
* &#064;Override
* public void registerFormatters(FormatterRegistry formatterRegistry) {
* formatterRegistry.addConverter(new MyConverter());
* }
*
* &#064;Override
* public void configureMessageConverters(List&lt;HttpMessageConverter&lt;?&gt;&gt; converters) {
* converters.add(new MyHttpMessageConverter());
* }
*
* ...
*
* }
* </pre>
*
* @see MvcConfigurer
* @see MvcConfigurerSupport
*
* @author Dave Syer
* @author Rossen Stoyanchev
* @since 3.1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MvcConfiguration.class)
public @interface EnableMvcConfiguration {
}
/*
* Copyright 2002-2011 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 java.util.ArrayList;
import java.util.List;
import org.springframework.util.Assert;
import org.springframework.web.context.request.WebRequestInterceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.MappedInterceptor;
import org.springframework.web.servlet.handler.MappedInterceptors;
import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
/**
* Helps with configuring an ordered set of Spring MVC interceptors of type {@link HandlerInterceptor} or
* {@link WebRequestInterceptor}. Registered interceptors will generally be detected by all {@link HandlerMapping}
* instances in a Spring MVC web application context. Interceptors can be added with a set of path patterns to
* which they should apply.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
public class InterceptorConfigurer {
private final List<MappedInterceptor> mappedInterceptors = new ArrayList<MappedInterceptor>();
/**
* Add a {@link HandlerInterceptor} that should apply to any request.
*/
public void addInterceptor(HandlerInterceptor interceptor) {
register(null, interceptor);
}
/**
* Add a {@link WebRequestInterceptor} that should apply to any request.
*/
public void addInterceptor(WebRequestInterceptor interceptor) {
register(null, asHandlerInterceptorArray(interceptor));
}
/**
* Add {@link HandlerInterceptor}s that should apply to any request.
*/
public void addInterceptors(HandlerInterceptor... interceptors) {
register(null, interceptors);
}
/**
* Add {@link WebRequestInterceptor}s that should apply to any request.
*/
public void addInterceptors(WebRequestInterceptor... interceptors) {
register(null, asHandlerInterceptorArray(interceptors));
}
/**
* Add a {@link HandlerInterceptor} with a set of URL path patterns it should apply to.
*/
public void mapInterceptor(String[] pathPatterns, HandlerInterceptor interceptor) {
register(pathPatterns, interceptor);
}
/**
* Add a {@link WebRequestInterceptor} with a set of URL path patterns it should apply to.
*/
public void mapInterceptor(String[] pathPatterns, WebRequestInterceptor interceptors) {
register(pathPatterns, asHandlerInterceptorArray(interceptors));
}
/**
* Add {@link HandlerInterceptor}s with a set of URL path patterns they should apply to.
*/
public void mapInterceptors(String[] pathPatterns, HandlerInterceptor... interceptors) {
register(pathPatterns, interceptors);
}
/**
* Add {@link WebRequestInterceptor}s with a set of URL path patterns they should apply to.
*/
public void mapInterceptors(String[] pathPatterns, WebRequestInterceptor... interceptors) {
register(pathPatterns, asHandlerInterceptorArray(interceptors));
}
private static HandlerInterceptor[] asHandlerInterceptorArray(WebRequestInterceptor...interceptors) {
HandlerInterceptor[] result = new HandlerInterceptor[interceptors.length];
for (int i = 0; i < result.length; i++) {
result[i] = new WebRequestHandlerInterceptorAdapter(interceptors[i]);
}
return result;
}
/**
* Stores the given set of {@link HandlerInterceptor}s and path patterns internally.
* @param pathPatterns path patterns or {@code null}
* @param interceptors one or more interceptors to be stored
*/
protected void register(String[] pathPatterns, HandlerInterceptor...interceptors) {
Assert.notEmpty(interceptors, "At least one interceptor must be provided");
for (HandlerInterceptor interceptor : interceptors) {
mappedInterceptors.add(new MappedInterceptor(pathPatterns, interceptor));
}
}
/**
* Returns a {@link MappedInterceptors} instance with all registered interceptors.
*/
protected MappedInterceptors getMappedInterceptors() {
return new MappedInterceptors(mappedInterceptors.toArray(new MappedInterceptor[mappedInterceptors.size()]));
}
}
/*
* Copyright 2002-2011 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 java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.xml.transform.Source;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter;
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter;
import org.springframework.util.ClassUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite;
import org.springframework.web.servlet.handler.MappedInterceptors;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodMapping;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
/**
* Provides default configuration for Spring MVC applications. Registers Spring MVC infrastructure components to be
* detected by the {@link DispatcherServlet}. Further below is a list of registered instances. This configuration is
* enabled through the {@link EnableMvcConfiguration} annotation.
*
* <p>A number of options are available for customizing the default configuration provided by this class.
* See {@link EnableMvcConfiguration} and {@link MvcConfigurer} for details.
*
* <p>Registers these handler mappings:
* <ul>
* <li>{@link RequestMappingHandlerMethodMapping} ordered at 0 for mapping requests to annotated controller methods.
* <li>{@link SimpleUrlHandlerMapping} ordered at 1 to map URL paths directly to view names.
* <li>{@link BeanNameUrlHandlerMapping} ordered at 2 to map URL paths to controller bean names.
* <li>{@link SimpleUrlHandlerMapping} ordered at {@code Integer.MAX_VALUE-1} to serve static resource requests.
* <li>{@link SimpleUrlHandlerMapping} ordered at {@code Integer.MAX_VALUE} to forward requests to the default servlet.
* </ul>
*
* <p><strong>Note:</strong> that the SimpleUrlHandlerMapping instances above will have empty URL maps and
* hence no effect until explicitly configured via {@link MvcConfigurer}.
*
* <p>Registers these handler adapters:
* <ul>
* <li>{@link RequestMappingHandlerMethodAdapter} for processing requests using annotated controller methods.
* <li>{@link HttpRequestHandlerAdapter} for processing requests with {@link HttpRequestHandler}s.
* <li>{@link SimpleControllerHandlerAdapter} for processing requests with interface-based {@link Controller}s.
* </ul>
*
* <p>Registers a {@link HandlerExceptionResolverComposite} with this chain of exception resolvers:
* <ul>
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions through @{@link ExceptionHandler} methods.
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated with @{@link ResponseStatus}.
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring exception types
* </ul>
*
* <p>Registers the following others:
* <ul>
* <li>{@link FormattingConversionService} for use with annotated controller methods and the spring:eval JSP tag.
* <li>{@link Validator} for validating model attributes on annotated controller methods.
* <li>{@link MappedInterceptors} containing a list Spring MVC lifecycle interceptors.
* </ul>
*
* @see EnableMvcConfiguration
* @see MvcConfigurer
*
* @author Rossen Stoyanchev
* @since 3.1
*/
@Configuration
class MvcConfiguration implements ApplicationContextAware, ServletContextAware {
private final MvcConfigurerComposite configurers = new MvcConfigurerComposite();
private ServletContext servletContext;
private ApplicationContext applicationContext;
@Autowired(required = false)
public void setConfigurers(List<MvcConfigurer> configurers) {
this.configurers.addConfigurers(configurers);
}
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Bean
RequestMappingHandlerMethodMapping requestMappingHandlerMapping() {
RequestMappingHandlerMethodMapping mapping = new RequestMappingHandlerMethodMapping();
mapping.setOrder(0);
return mapping;
}
@Bean
HandlerMapping viewControllerHandlerMapping() {
ViewControllerConfigurer configurer = new ViewControllerConfigurer();
configurer.setOrder(1);
configurers.addViewControllers(configurer);
return configurer.getHandlerMapping();
}
@Bean
BeanNameUrlHandlerMapping beanNameHandlerMapping() {
BeanNameUrlHandlerMapping mapping = new BeanNameUrlHandlerMapping();
mapping.setOrder(2);
return mapping;
}
@Bean
HandlerMapping resourceHandlerMapping() {
ResourceConfigurer configurer = new ResourceConfigurer(applicationContext, servletContext);
configurer.setOrder(Integer.MAX_VALUE-1);
configurers.configureResourceHandling(configurer);
return configurer.getHandlerMapping();
}
@Bean
HandlerMapping defaultServletHandlerMapping() {
DefaultServletHandlerConfigurer configurer = new DefaultServletHandlerConfigurer(servletContext);
configurers.configureDefaultServletHandling(configurer);
return configurer.getHandlerMapping();
}
@Bean
RequestMappingHandlerMethodAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerMethodAdapter adapter = new RequestMappingHandlerMethodAdapter();
ConfigurableWebBindingInitializer bindingInitializer = new ConfigurableWebBindingInitializer();
bindingInitializer.setConversionService(conversionService());
bindingInitializer.setValidator(validator());
adapter.setWebBindingInitializer(bindingInitializer);
List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<HandlerMethodArgumentResolver>();
configurers.addCustomArgumentResolvers(argumentResolvers);
adapter.setCustomArgumentResolvers(argumentResolvers);
List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
configurers.addCustomReturnValueHandlers(returnValueHandlers);
adapter.setCustomReturnValueHandlers(returnValueHandlers);
List<HttpMessageConverter<?>> converters = getDefaultHttpMessageConverters();
configurers.configureMessageConverters(converters);
adapter.setMessageConverters(converters);
return adapter;
}
@Bean(name="mvcConversionService")
FormattingConversionService conversionService() {
FormattingConversionService conversionService = new DefaultFormattingConversionService();
configurers.registerFormatters(conversionService);
return conversionService;
}
@Bean(name="mvcValidator")
Validator validator() {
Validator validator = configurers.getValidator();
if (validator != null) {
return validator;
}
else if (ClassUtils.isPresent("javax.validation.Validator", getClass().getClassLoader())) {
Class<?> clazz;
try {
String className = "org.springframework.validation.beanvalidation.LocalValidatorFactoryBean";
clazz = ClassUtils.forName(className, MvcConfiguration.class.getClassLoader());
} catch (ClassNotFoundException e) {
throw new BeanInitializationException("Could not find default validator");
} catch (LinkageError e) {
throw new BeanInitializationException("Could not find default validator");
}
return (Validator) BeanUtils.instantiate(clazz);
}
else {
return new Validator() {
public void validate(Object target, Errors errors) {
}
public boolean supports(Class<?> clazz) {
return false;
}
};
}
}
private List<HttpMessageConverter<?>> getDefaultHttpMessageConverters() {
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
stringConverter.setWriteAcceptCharset(false);
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(new ByteArrayHttpMessageConverter());
converters.add(stringConverter);
converters.add(new ResourceHttpMessageConverter());
converters.add(new SourceHttpMessageConverter<Source>());
converters.add(new XmlAwareFormHttpMessageConverter());
ClassLoader classLoader = getClass().getClassLoader();
if (ClassUtils.isPresent("javax.xml.bind.Binder", classLoader)) {
converters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper", classLoader)) {
converters.add(new MappingJacksonHttpMessageConverter());
}
if (ClassUtils.isPresent("com.sun.syndication.feed.WireFeed", classLoader)) {
converters.add(new AtomFeedHttpMessageConverter());
converters.add(new RssChannelHttpMessageConverter());
}
return converters;
}
@Bean
HttpRequestHandlerAdapter httpRequestHandlerAdapter() {
return new HttpRequestHandlerAdapter();
}
@Bean
SimpleControllerHandlerAdapter simpleControllerHandlerAdapter() {
return new SimpleControllerHandlerAdapter();
}
@Bean
HandlerExceptionResolver handlerExceptionResolver() throws Exception {
List<HandlerExceptionResolver> resolvers = new ArrayList<HandlerExceptionResolver>();
resolvers.add(createExceptionHandlerExceptionResolver());
resolvers.add(new ResponseStatusExceptionResolver());
resolvers.add(new DefaultHandlerExceptionResolver());
configurers.configureHandlerExceptionResolvers(resolvers);
HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
composite.setOrder(0);
composite.setExceptionResolvers(resolvers);
return composite;
}
private HandlerExceptionResolver createExceptionHandlerExceptionResolver() throws Exception {
ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
List<HttpMessageConverter<?>> converters = getDefaultHttpMessageConverters();
configurers.configureMessageConverters(converters);
resolver.setMessageConverters(converters);
resolver.setOrder(0);
resolver.afterPropertiesSet();
return resolver;
}
@Bean
MappedInterceptors mappedInterceptors() {
InterceptorConfigurer configurer = new InterceptorConfigurer();
configurer.addInterceptor(new ConversionServiceExposingInterceptor(conversionService()));
configurers.addInterceptors(configurer);
return configurer.getMappedInterceptors();
}
}
\ No newline at end of file
/*
* Copyright 2002-2011 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 java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.WebRequestInterceptor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerInterceptor;
import com.sun.corba.se.impl.presentation.rmi.ExceptionHandler;
/**
* Defines options for customizing or adding to the default Spring MVC configuration enabled through the use
* of @{@link EnableMvcConfiguration}. The @{@link Configuration} class annotated with @{@link EnableMvcConfiguration}
* is the most obvious place to implement this interface. However all @{@link Configuration} classes and more generally
* all Spring beans that implement this interface will be detected at startup and given a chance to customize Spring
* MVC configuration provided it is enabled through @{@link EnableMvcConfiguration}.
*
* <p>Implementations of this interface will find it convenient to extend {@link MvcConfigurerSupport} that
* provides default method implementations and allows overriding only methods of interest.
*
* @author Rossen Stoyanchev
* @author Keith Donald
* @author David Syer
* @since 3.1
*/
public interface MvcConfigurer {
/**
* Register application-specific {@link Converter}s and {@link Formatter}s for use in Spring MVC.
*/
void registerFormatters(FormatterRegistry formatterRegistry);
/**
* Customize the list of {@link HttpMessageConverter}s to use when resolving method arguments or handling
* return values from @{@link RequestMapping} and @{@link ExceptionHandler} methods.
* @param converters the list of converters, initially populated with the default set of converters
*/
void configureMessageConverters(List<HttpMessageConverter<?>> converters);
/**
* Provide a custom {@link Validator} type replacing the one that would be created by default otherwise. If this
* method returns {@code null}, and assuming a JSR-303 implementation is available on the classpath, a validator
* of type {@link org.springframework.validation.beanvalidation.LocalValidatorFactoryBean} is created by default.
*/
Validator getValidator();
/**
* Add custom {@link HandlerMethodArgumentResolver}s to use for resolving argument values
* on @{@link RequestMapping} and @{@link ExceptionHandler} methods.
* @param argumentResolvers the list of custom converters, initially empty
*/
void addCustomArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers);
/**
* Add custom {@link HandlerMethodReturnValueHandler}s to use for handling return values
* from @{@link RequestMapping} and @{@link ExceptionHandler} methods.
* @param returnValueHandlers the list of custom handlers, initially empty
*/
void addCustomReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers);
/**
* Customize the list of {@link HandlerExceptionResolver}s to use for handling controller exceptions.
* @param exceptionResolvers the list of resolvers, initially populated with the default set of resolvers
*/
void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers);
/**
* Add Spring MVC interceptors. Interceptors can be of type {@link HandlerInterceptor} or
* {@link WebRequestInterceptor}. They allow requests to be pre/post processed before/after controller
* invocation. Interceptors can be registered to apply to all requests or limited to a set of path patterns.
* @see InterceptorConfigurer
*/
void addInterceptors(InterceptorConfigurer interceptorConfigurer);
/**
* Map URL paths to view names. This is convenient when a request can be rendered without a controller.
*/
void addViewControllers(ViewControllerConfigurer viewControllerConfigurer);
/**
* Configure a handler for serving static resources such as images, js, and, css files through Spring MVC
* including setting cache headers optimized for efficient loading in a web browser. Resources can be served
* out of locations under web application root, from the classpath, and others.
*/
void configureResourceHandling(ResourceConfigurer resourceConfigurer);
/**
* Configure a handler for delegating unhandled requests by forwarding to the Servlet container's default
* servlet. This is commonly used when the {@link DispatcherServlet} is mapped to "/", which results in
* cleaner URLs (without a servlet prefix) but may need to still allow some requests (e.g. static resources)
* to be handled by the Servlet container's default servlet.
*/
void configureDefaultServletHandling(DefaultServletHandlerConfigurer handlerConfigurer);
}
/*
* Copyright 2002-2011 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 java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
/**
* An {@link MvcConfigurer} implementation that delegates to other {@link MvcConfigurer} instances.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
class MvcConfigurerComposite implements MvcConfigurer {
private final List<MvcConfigurer> configurers = new ArrayList<MvcConfigurer>();
void addConfigurers(List<MvcConfigurer> configurers) {
if (configurers != null) {
this.configurers.addAll(configurers);
}
}
public void registerFormatters(FormatterRegistry formatterRegistry) {
for (MvcConfigurer configurer : configurers) {
configurer.registerFormatters(formatterRegistry);
}
}
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
for (MvcConfigurer configurer : configurers) {
configurer.configureMessageConverters(converters);
}
}
public void addCustomArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
for (MvcConfigurer configurer : configurers) {
configurer.addCustomArgumentResolvers(argumentResolvers);
}
}
public void addCustomReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
for (MvcConfigurer configurer : configurers) {
configurer.addCustomReturnValueHandlers(returnValueHandlers);
}
}
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
for (MvcConfigurer configurer : configurers) {
configurer.configureHandlerExceptionResolvers(exceptionResolvers);
}
}
public void addInterceptors(InterceptorConfigurer interceptorRegistry) {
for (MvcConfigurer configurer : configurers) {
configurer.addInterceptors(interceptorRegistry);
}
}
public void addViewControllers(ViewControllerConfigurer viewControllerConfigurer) {
for (MvcConfigurer configurer : configurers) {
configurer.addViewControllers(viewControllerConfigurer);
}
}
public void configureResourceHandling(ResourceConfigurer resourceConfigurer) {
for (MvcConfigurer configurer : configurers) {
configurer.configureResourceHandling(resourceConfigurer);
}
}
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer handlerConfigurer) {
for (MvcConfigurer configurer : configurers) {
configurer.configureDefaultServletHandling(handlerConfigurer);
}
}
public Validator getValidator() {
Map<MvcConfigurer, Validator> validators = new HashMap<MvcConfigurer, Validator>();
for (MvcConfigurer configurer : configurers) {
Validator validator = configurer.getValidator();
if (validator != null) {
validators.put(configurer, validator);
}
}
if (validators.size() == 0) {
return null;
}
else if (validators.size() == 1) {
return validators.values().iterator().next();
}
else {
throw new IllegalStateException(
"Multiple custom validators provided from [" + validators.keySet() + "]");
}
}
}
/*
* Copyright 2002-2011 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 java.util.List;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.HandlerExceptionResolver;
/**
* An abstract class with empty method implementations of the {@link MvcConfigurer} interface for a simplified
* implementation of {@link MvcConfigurer} so that subclasses can override selected methods only.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
public abstract class MvcConfigurerSupport implements MvcConfigurer {
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void registerFormatters(FormatterRegistry formatterRegistry) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void configureValidator(Validator validator) {
}
/**
* {@inheritDoc}
* <p>This implementation returns {@code null}
*/
public Validator getValidator() {
return null;
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void addCustomArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void addInterceptors(InterceptorConfigurer interceptorConfigurer) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void addViewControllers(ViewControllerConfigurer viewControllerConfigurer) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void configureResourceHandling(ResourceConfigurer resourceConfigurer) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer handlerConfigurer) {
}
}
\ No newline at end of file
/*
* Copyright 2002-2011 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 java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
/**
* Helps with configuring a handler for serving static resources such as images, css files and others through
* Spring MVC including setting cache headers optimized for efficient loading in a web browser. Resources can
* be served out of locations under web application root, from the classpath, and others.
*
* <p>To configure resource handling, use {@link #addPathMappings(String...)} to add one or more URL path patterns
* within the current Servlet context, to use for serving resources from the handler, such as {@code "/resources/**"}.
*
* <p>Then use {@link #addResourceLocations(String...)} to add one or more locations from which to serve
* static content. For example, {{@code "/"}, {@code "classpath:/META-INF/public-web-resources/"}} allows resources
* to be served both from the web application root and from any JAR on the classpath that contains a
* {@code /META-INF/public-web-resources/} directory, with resources in the web application root taking precedence.
*
* <p>Optionally use {@link #setCachePeriod(Integer)} to specify the cache period for the resources served by the
* handler and {@link #setOrder(int)} to set the order in which to serve requests relative to other
* {@link HandlerMapping} instances in the Spring MVC web application context.
*
* @author Rossen Stoyanchev
* @since 3.1
*
* @see DefaultServletHandlerConfigurer
*/
public class ResourceConfigurer {
private final List<String> pathPatterns = new ArrayList<String>();
private final List<Resource> locations = new ArrayList<Resource>();
private Integer cachePeriod;
private int order = Integer.MAX_VALUE -1;
private final ServletContext servletContext;
private final ApplicationContext applicationContext;
public ResourceConfigurer(ApplicationContext applicationContext, ServletContext servletContext) {
Assert.notNull(applicationContext, "ApplicationContext is required");
this.applicationContext = applicationContext;
this.servletContext = servletContext;
}
/**
* Add a URL path pattern within the current Servlet context to use for serving static resources
* using the Spring MVC {@link ResourceHttpRequestHandler}, for example {@code "/resources/**"}.
* @return the same {@link ResourceConfigurer} instance for chained method invocation
*/
public ResourceConfigurer addPathMapping(String pathPattern) {
return addPathMappings(pathPattern);
}
/**
* Add several URL path patterns within the current Servlet context to use for serving static resources
* using the Spring MVC {@link ResourceHttpRequestHandler}, for example {@code "/resources/**"}.
* @return the same {@link ResourceConfigurer} instance for chained method invocation
*/
public ResourceConfigurer addPathMappings(String...pathPatterns) {
for (String path : pathPatterns) {
this.pathPatterns.add(path);
}
return this;
}
/**
* Add resource location from which to serve static content. The location must point to a valid
* directory. <p>For example, a value of {@code "/"} will allow resources to be served both from the web
* application root. Also see {@link #addResourceLocations(String...)} for mapping several resource locations.
* @return the same {@link ResourceConfigurer} instance for chained method invocation
*/
public ResourceConfigurer addResourceLocation(String resourceLocation) {
return addResourceLocations(resourceLocation);
}
/**
* Add one or more resource locations from which to serve static content. Each location must point to a valid
* directory. Multiple locations may be specified as a comma-separated list, and the locations will be checked
* for a given resource in the order specified.
* <p>For example, {{@code "/"}, {@code "classpath:/META-INF/public-web-resources/"}} allows resources to
* be served both from the web application root and from any JAR on the classpath that contains a
* {@code /META-INF/public-web-resources/} directory, with resources in the web application root taking precedence.
* @return the same {@link ResourceConfigurer} instance for chained method invocation
*/
public ResourceConfigurer addResourceLocations(String...resourceLocations) {
for (String location : resourceLocations) {
this.locations.add(applicationContext.getResource(location));
}
return this;
}
/**
* Specify the cache period for the resources served by the resource handler, in seconds. The default is to not
* send any cache headers but to rely on last-modified timestamps only. Set to 0 in order to send cache headers
* that prevent caching, or to a positive number of seconds to send cache headers with the given max-age value.
* @param cachePeriod the time to cache resources in seconds
* @return the same {@link ResourceConfigurer} instance for chained method invocation
*/
public ResourceConfigurer setCachePeriod(Integer cachePeriod) {
this.cachePeriod = cachePeriod;
return this;
}
/**
* Get the cache period for static resources served by the resource handler.
*/
public Integer getCachePeriod() {
return cachePeriod;
}
/**
* Specify the order in which to serve static resources relative to other {@link HandlerMapping} instances in the
* Spring MVC web application context. The default value is {@code Integer.MAX_VALUE-1}.
*/
public ResourceConfigurer setOrder(int order) {
this.order = order;
return this;
}
/**
* Get the order in which to serve static resources relative other {@link HandlerMapping} instances.
* @return the same {@link ResourceConfigurer} instance for chained method invocation
*/
public Integer getOrder() {
return order;
}
/**
* Return a {@link SimpleUrlHandlerMapping} with a {@link ResourceHttpRequestHandler} mapped to one or more
* URL path patterns. If the no path patterns were specified, the HandlerMapping returned contains an empty map.
*/
protected SimpleUrlHandlerMapping getHandlerMapping() {
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
handlerMapping.setOrder(order);
handlerMapping.setUrlMap(getUrlMap());
return handlerMapping;
}
private Map<String, HttpRequestHandler> getUrlMap() {
Map<String, HttpRequestHandler> urlMap = new LinkedHashMap<String, HttpRequestHandler>();
if (!pathPatterns.isEmpty()) {
ResourceHttpRequestHandler requestHandler = createRequestHandler();
for (String pathPattern : pathPatterns) {
urlMap.put(pathPattern, requestHandler);
}
}
return urlMap;
}
/**
* Create a {@link ResourceHttpRequestHandler} instance.
*/
protected ResourceHttpRequestHandler createRequestHandler() {
Assert.isTrue(!CollectionUtils.isEmpty(locations), "Path patterns specified but not resource locations.");
ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
requestHandler.setApplicationContext(applicationContext);
requestHandler.setServletContext(servletContext);
requestHandler.setLocations(locations);
if (cachePeriod != null) {
requestHandler.setCacheSeconds(cachePeriod);
}
return requestHandler;
}
}
\ No newline at end of file
/*
* Copyright 2002-2011 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 java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.RequestToViewNameTranslator;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.ParameterizableViewController;
/**
* Helps with view controllers. View controllers provide a direct mapping between a URL path and view name. This is
* useful when serving requests that don't require application-specific controller logic and can be forwarded
* directly to a view for rendering.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
public class ViewControllerConfigurer {
private final Map<String, Controller> urlMap = new LinkedHashMap<String, Controller>();
private int order = 1;
/**
* Map the URL path to a view name derived by convention through the DispatcherServlet's
* {@link RequestToViewNameTranslator}.
* @return the same {@link ViewControllerConfigurer} instance for convenient chained method invocation
*/
public ViewControllerConfigurer mapViewNameByConvention(String urlPath) {
return mapViewName(urlPath, null);
}
/**
* Map the URL path to the specified view name.
* @return the same {@link ViewControllerConfigurer} instance for convenient chained method invocation
*/
public ViewControllerConfigurer mapViewName(String urlPath, String viewName) {
ParameterizableViewController controller = new ParameterizableViewController();
controller.setViewName(viewName);
urlMap.put(urlPath, controller);
return this;
}
/**
* Specify the order in which to check view controller path mappings relative to other {@link HandlerMapping}
* instances in the Spring MVC web application context. The default value is 1.
*/
public void setOrder(int order) {
this.order = order;
}
/**
* Get the order in which to check view controller path mappings relative to other {@link HandlerMapping}s.
*/
public int getOrder() {
return order;
}
/**
* Return a {@link SimpleUrlHandlerMapping} with URL path to view controllers mappings.
*/
protected SimpleUrlHandlerMapping getHandlerMapping() {
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
handlerMapping.setOrder(order);
handlerMapping.setUrlMap(urlMap);
return handlerMapping;
}
}
\ No newline at end of file
package org.springframework.web.servlet.handler;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
/**
* A {@link HandlerExceptionResolver} that delegates to a list of {@link HandlerExceptionResolver}s.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
public class HandlerExceptionResolverComposite implements HandlerExceptionResolver, Ordered {
private List<HandlerExceptionResolver> resolvers;
private int order = Ordered.LOWEST_PRECEDENCE;
public void setOrder(int order) {
this.order = order;
}
public int getOrder() {
return this.order;
}
public void setExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
this.resolvers = exceptionResolvers;
}
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
if (resolvers != null) {
for (HandlerExceptionResolver handlerExceptionResolver : resolvers) {
ModelAndView mav = handlerExceptionResolver.resolveException(request, response, handler, ex);
if (mav != null) {
return mav;
}
}
}
return null;
}
}
\ No newline at end of file
......@@ -30,8 +30,10 @@ import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.servlet.HandlerMapping;
/**
* An {@link InitBinderMethodDataBinderFactory} that creates a {@link ServletRequestDataBinder}.
*
* An {@link InitBinderMethodDataBinderFactory} variation instantiating a data binder of type
* {@link ServletRequestDataBinder} and further extending it with the ability to add URI template variables
* to the values used in data binding.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
......@@ -39,7 +41,7 @@ public class ServletInitBinderMethodDataBinderFactory extends InitBinderMethodDa
/**
* Create an {@link ServletInitBinderMethodDataBinderFactory} instance.
* @param initBinderMethods init binder methods to use to initialize new data binders.
* @param initBinderMethods init binder methods to use to initialize new data binders.
* @param bindingInitializer a WebBindingInitializer to use to initialize created data binder instances.
*/
public ServletInitBinderMethodDataBinderFactory(List<InvocableHandlerMethod> initBinderMethods,
......@@ -48,34 +50,44 @@ public class ServletInitBinderMethodDataBinderFactory extends InitBinderMethodDa
}
/**
* Creates a Servlet data binder.
* {@inheritDoc}
* <p>This method creates a {@link ServletRequestDataBinder} instance that also adds URI template variables to
* the values used in data binding.
* <p>Subclasses wishing to override this method to provide their own ServletRequestDataBinder type can use the
* {@link #addUriTemplateVariables(MutablePropertyValues)} method to include URI template variables as follows:
* <pre>
* return new CustomServletRequestDataBinder(target, objectName) {
* protected void doBind(MutablePropertyValues mpvs) {
* addUriTemplateVariables(mpvs);
* super.doBind(mpvs);
* }
* };
* </pre>
*/
@Override
protected WebDataBinder createBinderInstance(Object target, String objectName) {
return new ServletRequestPathVarDataBinder(target, objectName);
return new ServletRequestDataBinder(target, objectName) {
protected void doBind(MutablePropertyValues mpvs) {
addUriTemplateVariables(mpvs);
super.doBind(mpvs);
}
};
}
/**
* Adds URI template variables to the map of request values used to do data binding.
* Adds URI template variables to the given property values.
* @param mpvs the PropertyValues to add URI template variables to
*/
private static class ServletRequestPathVarDataBinder extends ServletRequestDataBinder {
public ServletRequestPathVarDataBinder(Object target, String objectName) {
super(target, objectName);
}
@SuppressWarnings("unchecked")
@Override
protected void doBind(MutablePropertyValues mpvs) {
RequestAttributes requestAttrs = RequestContextHolder.getRequestAttributes();
if (requestAttrs != null) {
String key = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
int scope = RequestAttributes.SCOPE_REQUEST;
Map<String, String> uriTemplateVars = (Map<String, String>) requestAttrs.getAttribute(key, scope);
mpvs.addPropertyValues(uriTemplateVars);
}
super.doBind(mpvs);
@SuppressWarnings("unchecked")
protected void addUriTemplateVariables(MutablePropertyValues mpvs) {
RequestAttributes requestAttrs = RequestContextHolder.getRequestAttributes();
if (requestAttrs != null) {
String key = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
int scope = RequestAttributes.SCOPE_REQUEST;
Map<String, String> uriTemplateVars = (Map<String, String>) requestAttrs.getAttribute(key, scope);
mpvs.addPropertyValues(uriTemplateVars);
}
}
}
\ No newline at end of file
......@@ -30,16 +30,15 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandlerCom
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.mvc.method.annotation.support.ServletResponseMethodArgumentResolver;
/**
* Extends {@link InvocableHandlerMethod} with the ability to handle the value returned from the method through
* a registered {@link HandlerMethodArgumentResolver} that supports the given return value type.
* Extends {@link InvocableHandlerMethod} with the ability to handle the value returned from the method through
* a registered {@link HandlerMethodArgumentResolver} that supports the given return value type.
* Return value handling may include writing to the response or updating the {@link ModelAndViewContainer} structure.
*
* <p>If the underlying method has a {@link ResponseStatus} instruction, the status on the response is set
*
* <p>If the underlying method has a {@link ResponseStatus} instruction, the status on the response is set
* accordingly after the method is invoked but before the return value is handled.
*
*
* @author Rossen Stoyanchev
* @since 3.1
* @see #invokeAndHandle(NativeWebRequest, ModelAndViewContainer, Object...)
......@@ -47,9 +46,9 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ServletResp
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
private HttpStatus responseStatus;
private String responseReason;
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
public void setHandlerMethodReturnValueHandlers(HandlerMethodReturnValueHandlerComposite returnValueHandlers) {
......@@ -72,26 +71,26 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
}
/**
* Invokes the method and handles the return value through a registered {@link HandlerMethodReturnValueHandler}.
* Invokes the method and handles the return value through a registered {@link HandlerMethodReturnValueHandler}.
* <p>Return value handling may be skipped entirely when the method returns {@code null} (also possibly due
* to a {@code void} return type) and one of the following additional conditions is true:
* <ul>
* <li>A {@link HandlerMethodArgumentResolver} has set the {@link ModelAndViewContainer#setResolveView(boolean)}
* <li>A {@link HandlerMethodArgumentResolver} has set the {@link ModelAndViewContainer#setResolveView(boolean)}
* flag to {@code false} -- e.g. method arguments providing access to the response.
* <li>The request qualifies as "not modified" as defined in {@link ServletWebRequest#checkNotModified(long)}
* and {@link ServletWebRequest#checkNotModified(String)}. In this case a response with "not modified" response
* headers will be automatically generated without the need for return value handling.
* and {@link ServletWebRequest#checkNotModified(String)}. In this case a response with "not modified" response
* headers will be automatically generated without the need for return value handling.
* <li>The status on the response is set due to a @{@link ResponseStatus} instruction.
* </ul>
* <p>After the return value is handled, callers of this method can use the {@link ModelAndViewContainer}
* <p>After the return value is handled, callers of this method can use the {@link ModelAndViewContainer}
* to gain access to model attributes, view selection choices, and to check if view resolution is even needed.
*
*
* @param request the current request
* @param mavContainer the {@link ModelAndViewContainer} for the current request
* @param providedArgs argument values to try to use without the need for view resolution
*/
public final void invokeAndHandle(NativeWebRequest request,
ModelAndViewContainer mavContainer,
public final void invokeAndHandle(NativeWebRequest request,
ModelAndViewContainer mavContainer,
Object...providedArgs) throws Exception {
if (!returnValueHandlers.supportsReturnType(getReturnType())) {
......@@ -108,7 +107,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
return;
}
}
mavContainer.setResolveView(true);
returnValueHandlers.handleReturnValue(returnValue, getReturnType(), mavContainer, request);
......
......@@ -26,9 +26,9 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.support.ModelAttributeMethodProcessor;
/**
* A Servlet-specific {@link ModelAttributeMethodProcessor} variant that casts the {@link WebDataBinder}
* A Servlet-specific {@link ModelAttributeMethodProcessor} variant that casts the {@link WebDataBinder}
* instance to {@link ServletRequestDataBinder} prior to invoking data binding.
*
*
* @author Rossen Stoyanchev
* @since 3.1
*/
......@@ -36,7 +36,7 @@ public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodPr
/**
* @param useDefaultResolution in default resolution mode a method argument that isn't a simple type, as
* defined in {@link BeanUtils#isSimpleProperty(Class)}, is treated as a model attribute even if it doesn't
* defined in {@link BeanUtils#isSimpleProperty(Class)}, is treated as a model attribute even if it doesn't
* have an @{@link ModelAttribute} annotation with its name derived from the model attribute type.
*/
public ServletModelAttributeMethodProcessor(boolean useDefaultResolution) {
......@@ -44,12 +44,15 @@ public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodPr
}
/**
* Expects the data binder to be an instance of {@link ServletRequestDataBinder}.
* {@inheritDoc}
* <p>This method downcasts the binder instance to {@link ServletRequestDataBinder} and invokes
* its bind method passing a {@link ServletRequest} to it.
*/
@Override
protected void doBind(WebDataBinder binder, NativeWebRequest request) {
ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class);
((ServletRequestDataBinder) binder).bind(servletRequest);
ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder;
servletBinder.bind(servletRequest);
}
}
\ No newline at end of file
......@@ -17,31 +17,39 @@
package org.springframework.web.servlet.mvc.method.annotation.support;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.support.ModelAttributeMethodProcessor;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.RequestToViewNameTranslator;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator;
/**
* Handles return values that are of type {@link View} or {@link String} (i.e. a logical view name).
* <p>Since a {@link String} return value may handled in different ways, especially in combination with method
* annotations, this handler should be registered after return value handlers that look for method annotations
* such as the {@link ModelAttributeMethodProcessor} and the {@link RequestResponseBodyMethodProcessor}.
*
* Handles return values that are of type {@code void}, {@code String} (i.e. logical view name), or {@link View}.
*
* <p>A {@code null} return value, either due to a void return type or as the actual value returned from a
* method is left unhandled, leaving it to the configured {@link RequestToViewNameTranslator} to resolve the
* request to an actual view name. By default it is the {@link DefaultRequestToViewNameTranslator}.
*
* <p>Since a {@link String} return value may handled in different ways, especially in combination with method
* annotations such as @{@link ModelAttribute} and @{@link ResponseBody}, this handler should be ordered after
* return value handlers that support method annotations.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
public boolean supportsReturnType(MethodParameter returnType) {
Class<?> paramType = returnType.getParameterType();
return (View.class.isAssignableFrom(paramType) || (String.class.equals(paramType)));
Class<?> type = returnType.getParameterType();
return (void.class.equals(type) || String.class.equals(type) || View.class.isAssignableFrom(type));
}
public void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
public void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception {
if (returnValue == null) {
return;
......
/*
* Copyright 2002-2011 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import javax.servlet.RequestDispatcher;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockRequestDispatcher;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler;
/**
* Test fixture with a {@link DefaultServletHandlerConfigurer}.
*
* @author Rossen Stoyanchev
*/
public class DefaultServletHandlerConfigurerTests {
private DefaultServletHandlerConfigurer configurer;
private DispatchingMockServletContext servletContext;
private MockHttpServletResponse response;
@Before
public void setUp() {
response = new MockHttpServletResponse();
servletContext = new DispatchingMockServletContext();
configurer = new DefaultServletHandlerConfigurer(servletContext);
}
@Test
public void notEnabled() {
assertTrue(configurer.getHandlerMapping().getUrlMap().isEmpty());
}
@Test
public void enable() throws Exception {
configurer.enable();
SimpleUrlHandlerMapping handlerMapping = configurer.getHandlerMapping();
DefaultServletHttpRequestHandler handler = (DefaultServletHttpRequestHandler) handlerMapping.getUrlMap().get("/**");
assertNotNull(handler);
assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder());
handler.handleRequest(new MockHttpServletRequest(), response);
String expected = "default";
assertEquals("The ServletContext was not called with the default servlet name", expected, servletContext.url);
assertEquals("The request was not forwarded", expected, response.getForwardedUrl());
}
@Test
public void enableWithServletName() throws Exception {
configurer.enable("defaultServlet");
SimpleUrlHandlerMapping handlerMapping = configurer.getHandlerMapping();
DefaultServletHttpRequestHandler handler = (DefaultServletHttpRequestHandler) handlerMapping.getUrlMap().get("/**");
assertNotNull(handler);
assertEquals(Integer.MAX_VALUE, handlerMapping.getOrder());
handler.handleRequest(new MockHttpServletRequest(), response);
String expected = "defaultServlet";
assertEquals("The ServletContext was not called with the default servlet name", expected, servletContext.url);
assertEquals("The request was not forwarded", expected, response.getForwardedUrl());
}
private static class DispatchingMockServletContext extends MockServletContext {
private String url;
@Override
public RequestDispatcher getNamedDispatcher(String url) {
this.url = url;
return new MockRequestDispatcher(url);
}
}
}
/*
* Copyright 2002-2011 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 static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.ui.ModelMap;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.WebRequestInterceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
/**
* Test fixture with a {@link InterceptorConfigurer}, two {@link HandlerInterceptor}s and two
* {@link WebRequestInterceptor}s.
*
* @author Rossen Stoyanchev
*/
public class InterceptorConfigurerTests {
private InterceptorConfigurer configurer;
private final HandlerInterceptor interceptor1 = new LocaleChangeInterceptor();
private final HandlerInterceptor interceptor2 = new ThemeChangeInterceptor();
private TestWebRequestInterceptor webRequestInterceptor1;
private TestWebRequestInterceptor webRequestInterceptor2;
private final MockHttpServletRequest request = new MockHttpServletRequest();
private final MockHttpServletResponse response = new MockHttpServletResponse();
@Before
public void setUp() {
configurer = new InterceptorConfigurer();
webRequestInterceptor1 = new TestWebRequestInterceptor();
webRequestInterceptor2 = new TestWebRequestInterceptor();
}
@Test
public void addInterceptor() {
configurer.addInterceptor(interceptor1);
HandlerInterceptor[] interceptors = getInterceptorsForPath(null);
assertArrayEquals(new HandlerInterceptor[] {interceptor1}, interceptors);
}
@Test
public void addInterceptors() {
configurer.addInterceptors(interceptor1, interceptor2);
HandlerInterceptor[] interceptors = getInterceptorsForPath(null);
assertArrayEquals(new HandlerInterceptor[] {interceptor1, interceptor2}, interceptors);
}
@Test
public void mapInterceptor() {
configurer.mapInterceptor(new String[] {"/path1"}, interceptor1);
configurer.mapInterceptor(new String[] {"/path2"}, interceptor2);
assertArrayEquals(new HandlerInterceptor[] {interceptor1}, getInterceptorsForPath("/path1"));
assertArrayEquals(new HandlerInterceptor[] {interceptor2}, getInterceptorsForPath("/path2"));
}
@Test
public void mapInterceptors() {
configurer.mapInterceptors(new String[] {"/path1"}, interceptor1, interceptor2);
assertArrayEquals(new HandlerInterceptor[] {interceptor1, interceptor2}, getInterceptorsForPath("/path1"));
assertArrayEquals(new HandlerInterceptor[] {}, getInterceptorsForPath("/path2"));
}
@Test
public void addWebRequestInterceptor() throws Exception {
configurer.addInterceptor(webRequestInterceptor1);
HandlerInterceptor[] interceptors = getInterceptorsForPath(null);
assertEquals(1, interceptors.length);
verifyAdaptedInterceptor(interceptors[0], webRequestInterceptor1);
}
@Test
public void addWebRequestInterceptors() throws Exception {
configurer.addInterceptors(webRequestInterceptor1, webRequestInterceptor2);
HandlerInterceptor[] interceptors = getInterceptorsForPath(null);
assertEquals(2, interceptors.length);
verifyAdaptedInterceptor(interceptors[0], webRequestInterceptor1);
verifyAdaptedInterceptor(interceptors[1], webRequestInterceptor2);
}
@Test
public void mapWebRequestInterceptor() throws Exception {
configurer.mapInterceptor(new String[] {"/path1"}, webRequestInterceptor1);
configurer.mapInterceptor(new String[] {"/path2"}, webRequestInterceptor2);
HandlerInterceptor[] interceptors = getInterceptorsForPath("/path1");
assertEquals(1, interceptors.length);
verifyAdaptedInterceptor(interceptors[0], webRequestInterceptor1);
interceptors = getInterceptorsForPath("/path2");
assertEquals(1, interceptors.length);
verifyAdaptedInterceptor(interceptors[0], webRequestInterceptor2);
}
@Test
public void mapWebRequestInterceptor2() throws Exception {
configurer.mapInterceptors(new String[] {"/path1"}, webRequestInterceptor1, webRequestInterceptor2);
HandlerInterceptor[] interceptors = getInterceptorsForPath("/path1");
assertEquals(2, interceptors.length);
verifyAdaptedInterceptor(interceptors[0], webRequestInterceptor1);
verifyAdaptedInterceptor(interceptors[1], webRequestInterceptor2);
assertEquals(0, getInterceptorsForPath("/path2").length);
}
private HandlerInterceptor[] getInterceptorsForPath(String lookupPath) {
return configurer.getMappedInterceptors().getInterceptors(lookupPath, new AntPathMatcher());
}
private void verifyAdaptedInterceptor(HandlerInterceptor interceptor, TestWebRequestInterceptor webInterceptor)
throws Exception {
assertTrue(interceptor instanceof WebRequestHandlerInterceptorAdapter);
interceptor.preHandle(request, response, null);
assertTrue(webInterceptor.preHandleInvoked);
}
private static class TestWebRequestInterceptor implements WebRequestInterceptor {
private boolean preHandleInvoked = false;
public void preHandle(WebRequest request) throws Exception {
preHandleInvoked = true;
}
public void postHandle(WebRequest request, ModelMap model) throws Exception {
}
public void afterCompletion(WebRequest request, Exception ex) throws Exception {
}
}
}
/*
* Copyright 2002-2011 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 static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.List;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
/**
* A test fixture with an {@link MvcConfiguration} and a mock {@link MvcConfigurer} for verifying delegation.
*
* @author Rossen Stoyanchev
*/
public class MvcConfigurationTests {
private MvcConfiguration mvcConfiguration;
private MvcConfigurer configurer;
@Before
public void setUp() {
configurer = EasyMock.createMock(MvcConfigurer.class);
mvcConfiguration = new MvcConfiguration();
mvcConfiguration.setConfigurers(Arrays.asList(configurer));
}
@Test
public void annotationHandlerAdapter() {
Capture<FormattingConversionService> conversionService = new Capture<FormattingConversionService>();
Capture<List<HandlerMethodArgumentResolver>> resolvers = new Capture<List<HandlerMethodArgumentResolver>>();
Capture<List<HandlerMethodReturnValueHandler>> handlers = new Capture<List<HandlerMethodReturnValueHandler>>();
Capture<List<HttpMessageConverter<?>>> converters = new Capture<List<HttpMessageConverter<?>>>();
expect(configurer.getValidator()).andReturn(null);
configurer.registerFormatters(capture(conversionService));
configurer.addCustomArgumentResolvers(capture(resolvers));
configurer.addCustomReturnValueHandlers(capture(handlers));
configurer.configureMessageConverters(capture(converters));
replay(configurer);
RequestMappingHandlerMethodAdapter adapter = mvcConfiguration.requestMappingHandlerAdapter();
ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer) adapter.getWebBindingInitializer();
assertSame(conversionService.getValue(), initializer.getConversionService());
assertTrue(initializer.getValidator() instanceof LocalValidatorFactoryBean);
assertEquals(0, resolvers.getValue().size());
assertEquals(0, handlers.getValue().size());
assertTrue(converters.getValue().size() > 0);
assertEquals(converters.getValue(), adapter.getMessageConverters());
verify(configurer);
}
@Test
public void getCustomValidator() {
expect(configurer.getValidator()).andReturn(new LocalValidatorFactoryBean());
replay(configurer);
mvcConfiguration.validator();
verify(configurer);
}
@Test
public void configureValidator() {
expect(configurer.getValidator()).andReturn(null);
replay(configurer);
mvcConfiguration.validator();
verify(configurer);
}
@Test
public void handlerExceptionResolver() throws Exception {
Capture<List<HttpMessageConverter<?>>> converters = new Capture<List<HttpMessageConverter<?>>>();
Capture<List<HandlerExceptionResolver>> exceptionResolvers = new Capture<List<HandlerExceptionResolver>>();
configurer.configureMessageConverters(capture(converters));
configurer.configureHandlerExceptionResolvers(capture(exceptionResolvers));
replay(configurer);
mvcConfiguration.handlerExceptionResolver();
assertEquals(3, exceptionResolvers.getValue().size());
assertTrue(exceptionResolvers.getValue().get(0) instanceof ExceptionHandlerExceptionResolver);
assertTrue(exceptionResolvers.getValue().get(1) instanceof ResponseStatusExceptionResolver);
assertTrue(exceptionResolvers.getValue().get(2) instanceof DefaultHandlerExceptionResolver);
assertTrue(converters.getValue().size() > 0);
verify(configurer);
}
}
/*
* Copyright 2002-2011 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
/**
* Test fixture with a {@link ResourceConfigurer}.
*
* @author Rossen Stoyanchev
*/
public class ResourceConfigurerTests {
private ResourceConfigurer configurer;
private MockHttpServletResponse response;
@Before
public void setUp() {
configurer = new ResourceConfigurer(new GenericWebApplicationContext(), new MockServletContext());
configurer.addPathMapping("/resources/**");
configurer.addResourceLocation("classpath:org/springframework/web/servlet/config/annotation/");
response = new MockHttpServletResponse();
}
@Test
public void noMappings() throws Exception {
configurer = new ResourceConfigurer(new GenericWebApplicationContext(), new MockServletContext());
assertTrue(configurer.getHandlerMapping().getUrlMap().isEmpty());
}
@Test
public void mapPathToLocation() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/testStylesheet.css");
ResourceHttpRequestHandler handler = getResourceHandler("/resources/**");
handler.handleRequest(request, response);
assertEquals("test stylesheet content", response.getContentAsString());
}
@Test
public void cachePeriod() {
assertEquals(-1, getResourceHandler("/resources/**").getCacheSeconds());
configurer.setCachePeriod(0);
assertEquals(0, getResourceHandler("/resources/**").getCacheSeconds());
}
@Test
public void order() {
assertEquals(Integer.MAX_VALUE -1, configurer.getHandlerMapping().getOrder());
configurer.setOrder(0);
assertEquals(0, configurer.getHandlerMapping().getOrder());
}
private ResourceHttpRequestHandler getResourceHandler(String pathPattern) {
return (ResourceHttpRequestHandler) configurer.getHandlerMapping().getUrlMap().get(pathPattern);
}
}
/*
* Copyright 2002-2011 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 static org.junit.Assert.*;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.ParameterizableViewController;
/**
* Test fixture with a {@link ViewControllerConfigurer}.
*
* @author Rossen Stoyanchev
*/
public class ViewControllerConfigurerTests {
private ViewControllerConfigurer configurer;
@Before
public void setUp() {
configurer = new ViewControllerConfigurer();
}
@Test
public void noMappings() throws Exception {
Map<String, ?> urlMap = configurer.getHandlerMapping().getUrlMap();
assertTrue(urlMap.isEmpty());
}
@Test
public void mapViewName() {
configurer.mapViewName("/path", "viewName");
Map<String, ?> urlMap = configurer.getHandlerMapping().getUrlMap();
ParameterizableViewController controller = (ParameterizableViewController) urlMap.get("/path");
assertNotNull(controller);
assertEquals("viewName", controller.getViewName());
}
@Test
public void mapViewNameByConvention() {
configurer.mapViewNameByConvention("/path");
Map<String, ?> urlMap = configurer.getHandlerMapping().getUrlMap();
ParameterizableViewController controller = (ParameterizableViewController) urlMap.get("/path");
assertNotNull(controller);
assertNull(controller.getViewName());
}
@Test
public void order() {
SimpleUrlHandlerMapping handlerMapping = configurer.getHandlerMapping();
assertEquals(1, handlerMapping.getOrder());
configurer.setOrder(2);
handlerMapping = configurer.getHandlerMapping();
assertEquals(2, handlerMapping.getOrder());
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册