Introduce base class for WebMvcConfiguration
This commit is contained in:
parent
c60511bf04
commit
00d57907a3
|
|
@ -20,14 +20,13 @@ import java.lang.annotation.Target;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables default Spring MVC configuration and registers Spring MVC infrastructure components expected by the
|
* 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
|
* {@link DispatcherServlet}. Add this annotation to an application @{@link Configuration} class. It will in
|
||||||
* and that will in turn import default Spring MVC configuration including support for annotated methods
|
* turn import the @{@link Configuration} class {@link WebMvcConfiguration}, which provides default Spring MVC
|
||||||
* in @{@link Controller} classes.
|
* configuration.
|
||||||
* <pre>
|
* <pre>
|
||||||
* @Configuration
|
* @Configuration
|
||||||
* @EnableWebMvc
|
* @EnableWebMvc
|
||||||
|
|
@ -39,11 +38,10 @@ import org.springframework.web.servlet.DispatcherServlet;
|
||||||
*
|
*
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
* <p>To customize the imported configuration you simply implement {@link WebMvcConfigurer}, or more likely extend
|
* <p>To customize the imported configuration implement {@link WebMvcConfigurer}, or more conveniently extend
|
||||||
* {@link WebMvcConfigurerAdapter} overriding selected methods only. The most obvious place to do this is
|
* {@link WebMvcConfigurerAdapter} overriding specific methods. Your @{@link Configuration} class and any other
|
||||||
* the @{@link Configuration} class that enabled the Spring MVC configuration via @{@link EnableWebMvc}.
|
* Spring bean that implements {@link WebMvcConfigurer} will be detected and given an opportunity to customize
|
||||||
* However any @{@link Configuration} class and more generally any Spring bean can implement {@link WebMvcConfigurer}
|
* the default Spring MVC configuration through the callback methods on the {@link WebMvcConfigurer} interface.
|
||||||
* to be detected and given an opportunity to customize Spring MVC configuration at startup.
|
|
||||||
* <pre>
|
* <pre>
|
||||||
* @Configuration
|
* @Configuration
|
||||||
* @EnableWebMvc
|
* @EnableWebMvc
|
||||||
|
|
|
||||||
|
|
@ -22,77 +22,74 @@ import java.util.List;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.context.request.WebRequestInterceptor;
|
import org.springframework.web.context.request.WebRequestInterceptor;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
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.MappedInterceptor;
|
||||||
import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
|
import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helps with configuring an ordered set of Spring MVC interceptors of type {@link HandlerInterceptor} or
|
* 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}
|
* {@link WebRequestInterceptor}. Interceptors can be registered with a set of path patterns.
|
||||||
* 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
|
* @author Rossen Stoyanchev
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
public class InterceptorConfigurer {
|
public class InterceptorConfigurer {
|
||||||
|
|
||||||
private final List<MappedInterceptor> mappedInterceptors = new ArrayList<MappedInterceptor>();
|
private final List<Object> interceptors = new ArrayList<Object>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a {@link HandlerInterceptor} that should apply to any request.
|
* Add a {@link HandlerInterceptor} that should apply to any request.
|
||||||
*/
|
*/
|
||||||
public void addInterceptor(HandlerInterceptor interceptor) {
|
public void addInterceptor(HandlerInterceptor interceptor) {
|
||||||
register(null, interceptor);
|
register(interceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a {@link WebRequestInterceptor} that should apply to any request.
|
* Add a {@link WebRequestInterceptor} that should apply to any request.
|
||||||
*/
|
*/
|
||||||
public void addInterceptor(WebRequestInterceptor interceptor) {
|
public void addInterceptor(WebRequestInterceptor interceptor) {
|
||||||
register(null, asHandlerInterceptorArray(interceptor));
|
register(asHandlerInterceptorArray(interceptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add {@link HandlerInterceptor}s that should apply to any request.
|
* Add {@link HandlerInterceptor}s that should apply to any request.
|
||||||
*/
|
*/
|
||||||
public void addInterceptors(HandlerInterceptor... interceptors) {
|
public void addInterceptors(HandlerInterceptor... interceptors) {
|
||||||
register(null, interceptors);
|
register( interceptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add {@link WebRequestInterceptor}s that should apply to any request.
|
* Add {@link WebRequestInterceptor}s that should apply to any request.
|
||||||
*/
|
*/
|
||||||
public void addInterceptors(WebRequestInterceptor... interceptors) {
|
public void addInterceptors(WebRequestInterceptor... interceptors) {
|
||||||
register(null, asHandlerInterceptorArray(interceptors));
|
register(asHandlerInterceptorArray(interceptors));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a {@link HandlerInterceptor} with a set of URL path patterns it should apply to.
|
* Add a {@link HandlerInterceptor} with a set of URL path patterns it should apply to.
|
||||||
*/
|
*/
|
||||||
public void mapInterceptor(String[] pathPatterns, HandlerInterceptor interceptor) {
|
public void mapInterceptor(String[] pathPatterns, HandlerInterceptor interceptor) {
|
||||||
register(pathPatterns, interceptor);
|
registerMappedInterceptors(pathPatterns, interceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a {@link WebRequestInterceptor} with a set of URL path patterns it should apply to.
|
* Add a {@link WebRequestInterceptor} with a set of URL path patterns it should apply to.
|
||||||
*/
|
*/
|
||||||
public void mapInterceptor(String[] pathPatterns, WebRequestInterceptor interceptors) {
|
public void mapInterceptor(String[] pathPatterns, WebRequestInterceptor interceptors) {
|
||||||
register(pathPatterns, asHandlerInterceptorArray(interceptors));
|
registerMappedInterceptors(pathPatterns, asHandlerInterceptorArray(interceptors));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add {@link HandlerInterceptor}s with a set of URL path patterns they should apply to.
|
* Add {@link HandlerInterceptor}s with a set of URL path patterns they should apply to.
|
||||||
*/
|
*/
|
||||||
public void mapInterceptors(String[] pathPatterns, HandlerInterceptor... interceptors) {
|
public void mapInterceptors(String[] pathPatterns, HandlerInterceptor... interceptors) {
|
||||||
register(pathPatterns, interceptors);
|
registerMappedInterceptors(pathPatterns, interceptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add {@link WebRequestInterceptor}s with a set of URL path patterns they should apply to.
|
* Add {@link WebRequestInterceptor}s with a set of URL path patterns they should apply to.
|
||||||
*/
|
*/
|
||||||
public void mapInterceptors(String[] pathPatterns, WebRequestInterceptor... interceptors) {
|
public void mapInterceptors(String[] pathPatterns, WebRequestInterceptor... interceptors) {
|
||||||
register(pathPatterns, asHandlerInterceptorArray(interceptors));
|
registerMappedInterceptors(pathPatterns, asHandlerInterceptorArray(interceptors));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HandlerInterceptor[] asHandlerInterceptorArray(WebRequestInterceptor...interceptors) {
|
private static HandlerInterceptor[] asHandlerInterceptorArray(WebRequestInterceptor...interceptors) {
|
||||||
|
|
@ -103,23 +100,35 @@ public class InterceptorConfigurer {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the given set of {@link HandlerInterceptor}s internally.
|
||||||
|
* @param interceptors one or more interceptors to be stored
|
||||||
|
*/
|
||||||
|
protected void register(HandlerInterceptor...interceptors) {
|
||||||
|
Assert.notEmpty(interceptors, "At least one interceptor must be provided");
|
||||||
|
for (HandlerInterceptor interceptor : interceptors) {
|
||||||
|
this.interceptors.add(interceptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the given set of {@link HandlerInterceptor}s and path patterns internally.
|
* Stores the given set of {@link HandlerInterceptor}s and path patterns internally.
|
||||||
* @param pathPatterns path patterns or {@code null}
|
* @param pathPatterns path patterns or {@code null}
|
||||||
* @param interceptors one or more interceptors to be stored
|
* @param interceptors one or more interceptors to be stored
|
||||||
*/
|
*/
|
||||||
protected void register(String[] pathPatterns, HandlerInterceptor...interceptors) {
|
protected void registerMappedInterceptors(String[] pathPatterns, HandlerInterceptor...interceptors) {
|
||||||
Assert.notEmpty(interceptors, "At least one interceptor must be provided");
|
Assert.notEmpty(interceptors, "At least one interceptor must be provided");
|
||||||
|
Assert.notEmpty(pathPatterns, "Path patterns must be provided");
|
||||||
for (HandlerInterceptor interceptor : interceptors) {
|
for (HandlerInterceptor interceptor : interceptors) {
|
||||||
mappedInterceptors.add(new MappedInterceptor(pathPatterns, interceptor));
|
this.interceptors.add(new MappedInterceptor(pathPatterns, interceptor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all registered interceptors.
|
* Returns all registered interceptors.
|
||||||
*/
|
*/
|
||||||
protected List<MappedInterceptor> getInterceptors() {
|
protected List<Object> getInterceptors() {
|
||||||
return mappedInterceptors;
|
return interceptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,95 +19,31 @@ package org.springframework.web.servlet.config.annotation;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
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.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.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
|
||||||
import org.springframework.format.support.FormattingConversionService;
|
import org.springframework.format.support.FormattingConversionService;
|
||||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
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.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.HandlerMethodArgumentResolver;
|
||||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
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.HandlerExceptionResolverComposite;
|
||||||
import org.springframework.web.servlet.handler.MappedInterceptor;
|
|
||||||
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.RequestMappingHandlerAdapter;
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
|
||||||
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides default configuration for Spring MVC applications. Registers Spring MVC infrastructure components to be
|
* Provides default configuration for Spring MVC applications by registering Spring MVC infrastructure components
|
||||||
* detected by the {@link DispatcherServlet}. Further below is a list of registered instances. This configuration is
|
* to be detected by the {@link DispatcherServlet}. This class is imported whenever @{@link EnableWebMvc} is
|
||||||
* enabled through the {@link EnableWebMvc} annotation.
|
* added to an @{@link Configuration} class.
|
||||||
*
|
*
|
||||||
* <p>A number of options are available for customizing the default configuration provided by this class.
|
* <p>See the base class {@link WebMvcConfigurationSupport} for a list of registered instances. This class is closed
|
||||||
* See {@link EnableWebMvc} and {@link WebMvcConfigurer} for details.
|
* for extension. However, the configuration it provides can be customized by having your @{@link Configuration}
|
||||||
*
|
* class implement {@link WebMvcConfigurer} or more conveniently extend from {@link WebMvcConfigurerAdapter}.
|
||||||
* <p>Registers these handler mappings:
|
*
|
||||||
* <ul>
|
* <p>This class will detect your @{@link Configuration} class and any other @{@link Configuration} classes that
|
||||||
* <li>{@link RequestMappingHandlerMapping} ordered at 0 for mapping requests to annotated controller methods.
|
* implement {@link WebMvcConfigurer} via autowiring and will allow each of them to participate in the process
|
||||||
* <li>{@link SimpleUrlHandlerMapping} ordered at 1 to map URL paths directly to view names.
|
* of configuring Spring MVC through the configuration callbacks defined in {@link WebMvcConfigurer}.
|
||||||
* <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 one of the {@link WebMvcConfigurer} callbacks.
|
|
||||||
*
|
|
||||||
* <p>Registers these handler adapters:
|
|
||||||
* <ul>
|
|
||||||
* <li>{@link RequestMappingHandlerAdapter} 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.
|
|
||||||
* </ul>
|
|
||||||
*
|
*
|
||||||
* @see EnableWebMvc
|
* @see EnableWebMvc
|
||||||
* @see WebMvcConfigurer
|
* @see WebMvcConfigurer
|
||||||
|
|
@ -116,18 +52,10 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
class WebMvcConfiguration implements ApplicationContextAware, ServletContextAware {
|
class WebMvcConfiguration extends WebMvcConfigurationSupport {
|
||||||
|
|
||||||
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
|
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
|
||||||
|
|
||||||
private ServletContext servletContext;
|
|
||||||
|
|
||||||
private ApplicationContext applicationContext;
|
|
||||||
|
|
||||||
private List<MappedInterceptor> mappedInterceptors;
|
|
||||||
|
|
||||||
private List<HttpMessageConverter<?>> messageConverters;
|
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
public void setConfigurers(List<WebMvcConfigurer> configurers) {
|
public void setConfigurers(List<WebMvcConfigurer> configurers) {
|
||||||
if (configurers == null || configurers.isEmpty()) {
|
if (configurers == null || configurers.isEmpty()) {
|
||||||
|
|
@ -136,75 +64,30 @@ class WebMvcConfiguration implements ApplicationContextAware, ServletContextAwar
|
||||||
this.configurers.addWebMvcConfigurers(configurers);
|
this.configurers.addWebMvcConfigurers(configurers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setServletContext(ServletContext servletContext) {
|
@Override
|
||||||
this.servletContext = servletContext;
|
protected void configureInterceptors(InterceptorConfigurer configurer) {
|
||||||
|
configurers.configureInterceptors(configurer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
@Override
|
||||||
this.applicationContext = applicationContext;
|
protected void configureViewControllers(ViewControllerConfigurer configurer) {
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
|
|
||||||
RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping();
|
|
||||||
mapping.setInterceptors(getMappedInterceptors());
|
|
||||||
mapping.setOrder(0);
|
|
||||||
return mapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object[] getMappedInterceptors() {
|
|
||||||
if (mappedInterceptors == null) {
|
|
||||||
InterceptorConfigurer configurer = new InterceptorConfigurer();
|
|
||||||
configurers.configureInterceptors(configurer);
|
|
||||||
configurer.addInterceptor(new ConversionServiceExposingInterceptor(conversionService()));
|
|
||||||
mappedInterceptors = configurer.getInterceptors();
|
|
||||||
}
|
|
||||||
return mappedInterceptors.toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public HandlerMapping viewControllerHandlerMapping() {
|
|
||||||
ViewControllerConfigurer configurer = new ViewControllerConfigurer();
|
|
||||||
configurer.setOrder(1);
|
|
||||||
configurers.configureViewControllers(configurer);
|
configurers.configureViewControllers(configurer);
|
||||||
|
|
||||||
SimpleUrlHandlerMapping handlerMapping = configurer.getHandlerMapping();
|
|
||||||
handlerMapping.setInterceptors(getMappedInterceptors());
|
|
||||||
return handlerMapping;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Override
|
||||||
public BeanNameUrlHandlerMapping beanNameHandlerMapping() {
|
protected void configureResourceHandling(ResourceConfigurer configurer) {
|
||||||
BeanNameUrlHandlerMapping mapping = new BeanNameUrlHandlerMapping();
|
|
||||||
mapping.setOrder(2);
|
|
||||||
mapping.setInterceptors(getMappedInterceptors());
|
|
||||||
return mapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public HandlerMapping resourceHandlerMapping() {
|
|
||||||
ResourceConfigurer configurer = new ResourceConfigurer(applicationContext, servletContext);
|
|
||||||
configurer.setOrder(Integer.MAX_VALUE-1);
|
|
||||||
configurers.configureResourceHandling(configurer);
|
configurers.configureResourceHandling(configurer);
|
||||||
return configurer.getHandlerMapping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Override
|
||||||
public HandlerMapping defaultServletHandlerMapping() {
|
protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
|
||||||
DefaultServletHandlerConfigurer configurer = new DefaultServletHandlerConfigurer(servletContext);
|
|
||||||
configurers.configureDefaultServletHandling(configurer);
|
configurers.configureDefaultServletHandling(configurer);
|
||||||
return configurer.getHandlerMapping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@Bean
|
@Bean
|
||||||
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
|
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
|
||||||
RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
|
RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter();
|
||||||
adapter.setMessageConverters(getMessageConverters());
|
|
||||||
|
|
||||||
ConfigurableWebBindingInitializer bindingInitializer = new ConfigurableWebBindingInitializer();
|
|
||||||
bindingInitializer.setConversionService(conversionService());
|
|
||||||
bindingInitializer.setValidator(validator());
|
|
||||||
adapter.setWebBindingInitializer(bindingInitializer);
|
|
||||||
|
|
||||||
List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<HandlerMethodArgumentResolver>();
|
List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<HandlerMethodArgumentResolver>();
|
||||||
configurers.addArgumentResolvers(argumentResolvers);
|
configurers.addArgumentResolvers(argumentResolvers);
|
||||||
|
|
@ -213,116 +96,40 @@ class WebMvcConfiguration implements ApplicationContextAware, ServletContextAwar
|
||||||
List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
|
List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
|
||||||
configurers.addReturnValueHandlers(returnValueHandlers);
|
configurers.addReturnValueHandlers(returnValueHandlers);
|
||||||
adapter.setCustomReturnValueHandlers(returnValueHandlers);
|
adapter.setCustomReturnValueHandlers(returnValueHandlers);
|
||||||
|
|
||||||
return adapter;
|
return adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<HttpMessageConverter<?>> getMessageConverters() {
|
@Override
|
||||||
if (messageConverters == null) {
|
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||||
messageConverters = new ArrayList<HttpMessageConverter<?>>();
|
configurers.configureMessageConverters(converters);
|
||||||
configurers.configureMessageConverters(messageConverters);
|
|
||||||
if (messageConverters.isEmpty()) {
|
|
||||||
addDefaultHttpMessageConverters(messageConverters);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return messageConverters;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name="webMvcConversionService")
|
@Override
|
||||||
public FormattingConversionService conversionService() {
|
@Bean
|
||||||
FormattingConversionService conversionService = new DefaultFormattingConversionService();
|
public FormattingConversionService mvcConversionService() {
|
||||||
|
FormattingConversionService conversionService = super.mvcConversionService();
|
||||||
configurers.addFormatters(conversionService);
|
configurers.addFormatters(conversionService);
|
||||||
return conversionService;
|
return conversionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name="webMvcValidator")
|
@Override
|
||||||
public Validator validator() {
|
@Bean
|
||||||
|
public Validator mvcValidator() {
|
||||||
Validator validator = configurers.getValidator();
|
Validator validator = configurers.getValidator();
|
||||||
if (validator != null) {
|
return validator != null ? validator : super.mvcValidator();
|
||||||
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, WebMvcConfiguration.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 NOOP_VALIDATOR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
|
|
||||||
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
|
|
||||||
stringConverter.setWriteAcceptCharset(false);
|
|
||||||
|
|
||||||
messageConverters.add(new ByteArrayHttpMessageConverter());
|
|
||||||
messageConverters.add(stringConverter);
|
|
||||||
messageConverters.add(new ResourceHttpMessageConverter());
|
|
||||||
messageConverters.add(new SourceHttpMessageConverter<Source>());
|
|
||||||
messageConverters.add(new XmlAwareFormHttpMessageConverter());
|
|
||||||
|
|
||||||
ClassLoader classLoader = getClass().getClassLoader();
|
|
||||||
if (ClassUtils.isPresent("javax.xml.bind.Binder", classLoader)) {
|
|
||||||
messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
|
|
||||||
}
|
|
||||||
if (ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper", classLoader)) {
|
|
||||||
messageConverters.add(new MappingJacksonHttpMessageConverter());
|
|
||||||
}
|
|
||||||
if (ClassUtils.isPresent("com.sun.syndication.feed.WireFeed", classLoader)) {
|
|
||||||
messageConverters.add(new AtomFeedHttpMessageConverter());
|
|
||||||
messageConverters.add(new RssChannelHttpMessageConverter());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public HttpRequestHandlerAdapter httpRequestHandlerAdapter() {
|
public HandlerExceptionResolverComposite handlerExceptionResolver() throws Exception {
|
||||||
return new HttpRequestHandlerAdapter();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter() {
|
|
||||||
return new SimpleControllerHandlerAdapter();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public HandlerExceptionResolver handlerExceptionResolver() throws Exception {
|
|
||||||
List<HandlerExceptionResolver> resolvers = new ArrayList<HandlerExceptionResolver>();
|
List<HandlerExceptionResolver> resolvers = new ArrayList<HandlerExceptionResolver>();
|
||||||
configurers.configureHandlerExceptionResolvers(resolvers);
|
configurers.configureHandlerExceptionResolvers(resolvers);
|
||||||
|
|
||||||
if (resolvers.size() == 0) {
|
HandlerExceptionResolverComposite composite = super.handlerExceptionResolver();
|
||||||
resolvers.add(createExceptionHandlerExceptionResolver());
|
if (resolvers.size() != 0) {
|
||||||
resolvers.add(new ResponseStatusExceptionResolver());
|
composite.setExceptionResolvers(resolvers);
|
||||||
resolvers.add(new DefaultHandlerExceptionResolver());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
|
|
||||||
composite.setOrder(0);
|
|
||||||
composite.setExceptionResolvers(resolvers);
|
|
||||||
return composite;
|
return composite;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HandlerExceptionResolver createExceptionHandlerExceptionResolver() throws Exception {
|
|
||||||
ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver();
|
|
||||||
resolver.setMessageConverters(getMessageConverters());
|
|
||||||
resolver.afterPropertiesSet();
|
|
||||||
return resolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Validator NOOP_VALIDATOR = new Validator() {
|
|
||||||
|
|
||||||
public boolean supports(Class<?> clazz) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void validate(Object target, Errors errors) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,399 @@
|
||||||
|
/*
|
||||||
|
* 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.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.MessageCodesResolver;
|
||||||
|
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.servlet.DispatcherServlet;
|
||||||
|
import org.springframework.web.servlet.HandlerAdapter;
|
||||||
|
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.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.RequestMappingHandlerAdapter;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
|
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base class that provides default configuration for Spring MVC applications by registering Spring MVC
|
||||||
|
* infrastructure components to be detected by the {@link DispatcherServlet}. Typically applications should not
|
||||||
|
* have to start by extending this class. A much easier place to start is to annotate your @{@link Configuration}
|
||||||
|
* class with @{@link EnableWebMvc}. See @{@link EnableWebMvc} and {@link WebMvcConfigurer}.
|
||||||
|
*
|
||||||
|
* <p>If using @{@link EnableWebMvc} and extending from {@link WebMvcConfigurerAdapter} does not give you the level
|
||||||
|
* of flexibility you need, consider extending directly from this class instead. Remember to add @{@link Configuration}
|
||||||
|
* to you subclass and @{@link Bean} to any @{@link Bean} methods you choose to override. A few example reasons for
|
||||||
|
* extending this class include providing a custom {@link MessageCodesResolver}, changing the order of
|
||||||
|
* {@link HandlerMapping} instances, plugging in a variant of any of the beans provided by this class, and so on.
|
||||||
|
*
|
||||||
|
* <p>This class registers the following {@link HandlerMapping}s:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link RequestMappingHandlerMapping} 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>Registers {@link HandlerAdapter}s:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link RequestMappingHandlerAdapter} 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 other instances:
|
||||||
|
* <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.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @see EnableWebMvc
|
||||||
|
* @see WebMvcConfigurer
|
||||||
|
* @see WebMvcConfigurerAdapter
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
public abstract class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
|
||||||
|
|
||||||
|
private ServletContext servletContext;
|
||||||
|
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
private List<Object> interceptors;
|
||||||
|
|
||||||
|
private List<HttpMessageConverter<?>> messageConverters;
|
||||||
|
|
||||||
|
public void setServletContext(ServletContext servletContext) {
|
||||||
|
this.servletContext = servletContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link RequestMappingHandlerMapping} ordered at 0 for mapping requests to annotated controllers.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
|
||||||
|
RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping();
|
||||||
|
mapping.setInterceptors(getInterceptors());
|
||||||
|
mapping.setOrder(0);
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the shared handler interceptors used to configure {@link HandlerMapping} instances with.
|
||||||
|
* This method cannot be overridden, use {@link #configureInterceptors(InterceptorConfigurer)} instead.
|
||||||
|
*/
|
||||||
|
protected final Object[] getInterceptors() {
|
||||||
|
if (interceptors == null) {
|
||||||
|
InterceptorConfigurer configurer = new InterceptorConfigurer();
|
||||||
|
configureInterceptors(configurer);
|
||||||
|
configurer.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService()));
|
||||||
|
interceptors = configurer.getInterceptors();
|
||||||
|
}
|
||||||
|
return interceptors.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method to configure handler interceptors including interceptors mapped to path patterns.
|
||||||
|
* @see InterceptorConfigurer
|
||||||
|
*/
|
||||||
|
protected void configureInterceptors(InterceptorConfigurer configurer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link SimpleUrlHandlerMapping} ordered at 1 to map URL paths directly to view names.
|
||||||
|
* To configure view controllers see {@link #configureViewControllers(ViewControllerConfigurer)}.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public SimpleUrlHandlerMapping viewControllerHandlerMapping() {
|
||||||
|
ViewControllerConfigurer configurer = new ViewControllerConfigurer();
|
||||||
|
configurer.setOrder(1);
|
||||||
|
configureViewControllers(configurer);
|
||||||
|
|
||||||
|
SimpleUrlHandlerMapping handlerMapping = configurer.getHandlerMapping();
|
||||||
|
handlerMapping.setInterceptors(getInterceptors());
|
||||||
|
return handlerMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method to configure 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.
|
||||||
|
* @see ViewControllerConfigurer
|
||||||
|
*/
|
||||||
|
protected void configureViewControllers(ViewControllerConfigurer configurer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link BeanNameUrlHandlerMapping} ordered at 2 to map URL paths to controller bean names.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public BeanNameUrlHandlerMapping beanNameHandlerMapping() {
|
||||||
|
BeanNameUrlHandlerMapping mapping = new BeanNameUrlHandlerMapping();
|
||||||
|
mapping.setOrder(2);
|
||||||
|
mapping.setInterceptors(getInterceptors());
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link SimpleUrlHandlerMapping} ordered at Integer.MAX_VALUE-1 to serve static resource requests.
|
||||||
|
* To configure resource handling, see {@link #configureResourceHandling(ResourceConfigurer)}.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public SimpleUrlHandlerMapping resourceHandlerMapping() {
|
||||||
|
ResourceConfigurer configurer = new ResourceConfigurer(applicationContext, servletContext);
|
||||||
|
configurer.setOrder(Integer.MAX_VALUE-1);
|
||||||
|
configureResourceHandling(configurer);
|
||||||
|
return configurer.getHandlerMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method to configure serving static resources such as images and css files through Spring MVC.
|
||||||
|
* @see ResourceConfigurer
|
||||||
|
*/
|
||||||
|
protected void configureResourceHandling(ResourceConfigurer configurer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link SimpleUrlHandlerMapping} ordered at Integer.MAX_VALUE to serve static resources by
|
||||||
|
* forwarding to the Servlet container's default servlet. To configure default servlet handling see
|
||||||
|
* {@link #configureDefaultServletHandling(DefaultServletHandlerConfigurer)}.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public SimpleUrlHandlerMapping defaultServletHandlerMapping() {
|
||||||
|
DefaultServletHandlerConfigurer configurer = new DefaultServletHandlerConfigurer(servletContext);
|
||||||
|
configureDefaultServletHandling(configurer);
|
||||||
|
return configurer.getHandlerMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method to configure serving static resources through the Servlet container's default Servlet.
|
||||||
|
* @see DefaultServletHandlerConfigurer
|
||||||
|
*/
|
||||||
|
protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link RequestMappingHandlerAdapter} for processing requests using annotated controller methods.
|
||||||
|
* Also see {@link #initWebBindingInitializer()} for configuring data binding globally.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
|
||||||
|
ConfigurableWebBindingInitializer webBindingInitializer = new ConfigurableWebBindingInitializer();
|
||||||
|
webBindingInitializer.setConversionService(mvcConversionService());
|
||||||
|
webBindingInitializer.setValidator(mvcValidator());
|
||||||
|
extendWebBindingInitializer(webBindingInitializer);
|
||||||
|
|
||||||
|
RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
|
||||||
|
adapter.setMessageConverters(getMessageConverters());
|
||||||
|
adapter.setWebBindingInitializer(webBindingInitializer);
|
||||||
|
return adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method to customize the {@link ConfigurableWebBindingInitializer} the
|
||||||
|
* {@link RequestMappingHandlerAdapter} is configured with.
|
||||||
|
*/
|
||||||
|
protected void extendWebBindingInitializer(ConfigurableWebBindingInitializer webBindingInitializer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the shared {@link HttpMessageConverter}s used by the
|
||||||
|
* {@link RequestMappingHandlerAdapter} and the {@link ExceptionHandlerExceptionResolver}.
|
||||||
|
* This method cannot be extended directly, use {@link #configureMessageConverters(List)} add custom converters.
|
||||||
|
* Also see {@link #addDefaultHttpMessageConverters(List)} to easily add a set of default converters.
|
||||||
|
*/
|
||||||
|
protected final List<HttpMessageConverter<?>> getMessageConverters() {
|
||||||
|
if (messageConverters == null) {
|
||||||
|
messageConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||||
|
configureMessageConverters(messageConverters);
|
||||||
|
if (messageConverters.isEmpty()) {
|
||||||
|
addDefaultHttpMessageConverters(messageConverters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return messageConverters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method to add custom {@link HttpMessageConverter}s to use with
|
||||||
|
* the {@link RequestMappingHandlerAdapter} and the {@link ExceptionHandlerExceptionResolver}.
|
||||||
|
* If any converters are added, default converters will not be added automatically.
|
||||||
|
* See {@link #addDefaultHttpMessageConverters(List)} for adding default converters to the list.
|
||||||
|
* @param messageConverters the list to add converters to
|
||||||
|
*/
|
||||||
|
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A method available to subclasses for adding default {@link HttpMessageConverter}s.
|
||||||
|
* @param messageConverters the list to add converters to
|
||||||
|
*/
|
||||||
|
protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
|
||||||
|
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
|
||||||
|
stringConverter.setWriteAcceptCharset(false);
|
||||||
|
|
||||||
|
messageConverters.add(new ByteArrayHttpMessageConverter());
|
||||||
|
messageConverters.add(stringConverter);
|
||||||
|
messageConverters.add(new ResourceHttpMessageConverter());
|
||||||
|
messageConverters.add(new SourceHttpMessageConverter<Source>());
|
||||||
|
messageConverters.add(new XmlAwareFormHttpMessageConverter());
|
||||||
|
|
||||||
|
ClassLoader classLoader = getClass().getClassLoader();
|
||||||
|
if (ClassUtils.isPresent("javax.xml.bind.Binder", classLoader)) {
|
||||||
|
messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||||
|
}
|
||||||
|
if (ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper", classLoader)) {
|
||||||
|
messageConverters.add(new MappingJacksonHttpMessageConverter());
|
||||||
|
}
|
||||||
|
if (ClassUtils.isPresent("com.sun.syndication.feed.WireFeed", classLoader)) {
|
||||||
|
messageConverters.add(new AtomFeedHttpMessageConverter());
|
||||||
|
messageConverters.add(new RssChannelHttpMessageConverter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link FormattingConversionService} for use with annotated controller methods and the
|
||||||
|
* {@code spring:eval} JSP tag.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public FormattingConversionService mvcConversionService() {
|
||||||
|
return new DefaultFormattingConversionService();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@link Validator} for validating {@code @ModelAttribute} and {@code @RequestBody} arguments of
|
||||||
|
* annotated controller methods. If a JSR-303 implementation is available on the classpath, the returned
|
||||||
|
* instance is LocalValidatorFactoryBean. Otherwise a no-op validator is returned.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Validator mvcValidator() {
|
||||||
|
if (ClassUtils.isPresent("javax.validation.Validator", getClass().getClassLoader())) {
|
||||||
|
Class<?> clazz;
|
||||||
|
try {
|
||||||
|
String className = "org.springframework.validation.beanvalidation.LocalValidatorFactoryBean";
|
||||||
|
clazz = ClassUtils.forName(className, WebMvcConfigurationSupport.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 boolean supports(Class<?> clazz) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public void validate(Object target, Errors errors) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link HttpRequestHandlerAdapter} for processing requests with {@link HttpRequestHandler}s.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public HttpRequestHandlerAdapter httpRequestHandlerAdapter() {
|
||||||
|
return new HttpRequestHandlerAdapter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link SimpleControllerHandlerAdapter} for processing requests with interface-based controllers.
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter() {
|
||||||
|
return new SimpleControllerHandlerAdapter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns 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>
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public HandlerExceptionResolverComposite handlerExceptionResolver() throws Exception {
|
||||||
|
ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new ExceptionHandlerExceptionResolver();
|
||||||
|
exceptionHandlerExceptionResolver.setMessageConverters(getMessageConverters());
|
||||||
|
exceptionHandlerExceptionResolver.afterPropertiesSet();
|
||||||
|
|
||||||
|
List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<HandlerExceptionResolver>();
|
||||||
|
exceptionResolvers.add(exceptionHandlerExceptionResolver);
|
||||||
|
exceptionResolvers.add(new ResponseStatusExceptionResolver());
|
||||||
|
exceptionResolvers.add(new DefaultHandlerExceptionResolver());
|
||||||
|
|
||||||
|
HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
|
||||||
|
composite.setOrder(0);
|
||||||
|
composite.setExceptionResolvers(exceptionResolvers);
|
||||||
|
return composite;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -18,7 +18,6 @@ package org.springframework.web.servlet.config.annotation;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.format.Formatter;
|
import org.springframework.format.Formatter;
|
||||||
import org.springframework.format.FormatterRegistry;
|
import org.springframework.format.FormatterRegistry;
|
||||||
|
|
@ -35,14 +34,13 @@ import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
import com.sun.corba.se.impl.presentation.rmi.ExceptionHandler;
|
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
|
* Defines configuration callback methods for customizing the default Spring MVC configuration enabled through the
|
||||||
* of @{@link EnableWebMvc}. The @{@link Configuration} class annotated with @{@link EnableWebMvc}
|
* use of @{@link EnableWebMvc}.
|
||||||
* 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
|
* <p>Classes annotated with @{@link EnableWebMvc} can implement this interface in order to be called back and
|
||||||
* MVC configuration provided it is enabled through @{@link EnableWebMvc}.
|
* given a chance to customize the default configuration. The most convenient way to implement this interface is
|
||||||
*
|
* by extending from {@link WebMvcConfigurerAdapter}, which provides empty method implementations and allows
|
||||||
* <p>Implementations of this interface will find it convenient to extend {@link WebMvcConfigurerAdapter} that
|
* overriding only the callback methods you're interested in.
|
||||||
* provides default method implementations and allows overriding only methods of interest.
|
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package org.springframework.web.servlet.config.annotation;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -146,9 +147,18 @@ public class InterceptorConfigurerTests {
|
||||||
private List<HandlerInterceptor> getInterceptorsForPath(String lookupPath) {
|
private List<HandlerInterceptor> getInterceptorsForPath(String lookupPath) {
|
||||||
PathMatcher pathMatcher = new AntPathMatcher();
|
PathMatcher pathMatcher = new AntPathMatcher();
|
||||||
List<HandlerInterceptor> result = new ArrayList<HandlerInterceptor>();
|
List<HandlerInterceptor> result = new ArrayList<HandlerInterceptor>();
|
||||||
for (MappedInterceptor interceptor : configurer.getInterceptors()) {
|
for (Object i : configurer.getInterceptors()) {
|
||||||
if (interceptor.matches(lookupPath, pathMatcher)) {
|
if (i instanceof MappedInterceptor) {
|
||||||
result.add(interceptor.getInterceptor());
|
MappedInterceptor mappedInterceptor = (MappedInterceptor) i;
|
||||||
|
if (mappedInterceptor.matches(lookupPath, pathMatcher)) {
|
||||||
|
result.add(mappedInterceptor.getInterceptor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (i instanceof HandlerInterceptor){
|
||||||
|
result.add((HandlerInterceptor) i);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail("Unexpected interceptor type: " + i.getClass().getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package org.springframework.web.servlet.config.annotation;
|
||||||
|
|
||||||
import static org.easymock.EasyMock.capture;
|
import static org.easymock.EasyMock.capture;
|
||||||
import static org.easymock.EasyMock.expect;
|
import static org.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.EasyMock.isA;
|
||||||
import static org.easymock.EasyMock.replay;
|
import static org.easymock.EasyMock.replay;
|
||||||
import static org.easymock.EasyMock.verify;
|
import static org.easymock.EasyMock.verify;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
@ -126,7 +127,7 @@ public class WebMvcConfigurationTests {
|
||||||
replay(configurer);
|
replay(configurer);
|
||||||
|
|
||||||
mvcConfiguration.setConfigurers(Arrays.asList(configurer));
|
mvcConfiguration.setConfigurers(Arrays.asList(configurer));
|
||||||
mvcConfiguration.validator();
|
mvcConfiguration.mvcValidator();
|
||||||
|
|
||||||
verify(configurer);
|
verify(configurer);
|
||||||
}
|
}
|
||||||
|
|
@ -137,28 +138,25 @@ public class WebMvcConfigurationTests {
|
||||||
replay(configurer);
|
replay(configurer);
|
||||||
|
|
||||||
mvcConfiguration.setConfigurers(Arrays.asList(configurer));
|
mvcConfiguration.setConfigurers(Arrays.asList(configurer));
|
||||||
mvcConfiguration.validator();
|
mvcConfiguration.mvcValidator();
|
||||||
|
|
||||||
verify(configurer);
|
verify(configurer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void handlerExceptionResolver() throws Exception {
|
public void handlerExceptionResolver() throws Exception {
|
||||||
Capture<List<HttpMessageConverter<?>>> converters = new Capture<List<HttpMessageConverter<?>>>();
|
configurer.configureMessageConverters(isA(List.class));
|
||||||
Capture<List<HandlerExceptionResolver>> exceptionResolvers = new Capture<List<HandlerExceptionResolver>>();
|
configurer.configureHandlerExceptionResolvers(isA(List.class));
|
||||||
|
|
||||||
configurer.configureMessageConverters(capture(converters));
|
|
||||||
configurer.configureHandlerExceptionResolvers(capture(exceptionResolvers));
|
|
||||||
replay(configurer);
|
replay(configurer);
|
||||||
|
|
||||||
mvcConfiguration.setConfigurers(Arrays.asList(configurer));
|
mvcConfiguration.setConfigurers(Arrays.asList(configurer));
|
||||||
mvcConfiguration.handlerExceptionResolver();
|
List<HandlerExceptionResolver> actual = mvcConfiguration.handlerExceptionResolver().getExceptionResolvers();
|
||||||
|
|
||||||
assertEquals(3, exceptionResolvers.getValue().size());
|
assertEquals(3, actual.size());
|
||||||
assertTrue(exceptionResolvers.getValue().get(0) instanceof ExceptionHandlerExceptionResolver);
|
assertTrue(actual.get(0) instanceof ExceptionHandlerExceptionResolver);
|
||||||
assertTrue(exceptionResolvers.getValue().get(1) instanceof ResponseStatusExceptionResolver);
|
assertTrue(actual.get(1) instanceof ResponseStatusExceptionResolver);
|
||||||
assertTrue(exceptionResolvers.getValue().get(2) instanceof DefaultHandlerExceptionResolver);
|
assertTrue(actual.get(2) instanceof DefaultHandlerExceptionResolver);
|
||||||
assertTrue(converters.getValue().size() > 0);
|
|
||||||
|
|
||||||
verify(configurer);
|
verify(configurer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue