Add method to allow further validation of request mapping infos at startup + other minor javadoc updates.

This commit is contained in:
Rossen Stoyanchev 2011-05-12 15:03:36 +00:00
parent 2afeb08e3c
commit b46598965e
7 changed files with 69 additions and 47 deletions

View File

@ -59,7 +59,6 @@ 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.MappedInterceptor;
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;
@ -88,7 +87,7 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv
* </ul>
*
* <p><strong>Note:</strong> that the SimpleUrlHandlerMapping instances above will have empty URL maps and
* hence no effect until explicitly configured via {@link WebMvcConfigurer}.
* hence no effect until explicitly configured via one of the {@link WebMvcConfigurer} callbacks.
*
* <p>Registers these handler adapters:
* <ul>
@ -108,7 +107,6 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv
* <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 EnableWebMvc
@ -128,7 +126,7 @@ class WebMvcConfiguration implements ApplicationContextAware, ServletContextAwar
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
this.configurers.addConfigurers(configurers);
this.configurers.addWebMvcConfigurers(configurers);
}
public void setServletContext(ServletContext servletContext) {

View File

@ -54,7 +54,7 @@ public interface WebMvcConfigurer {
/**
* Add {@link Converter}s and {@link Formatter}s in addition to the ones registered by default.
*/
void addFormatters(FormatterRegistry formatterRegistry);
void addFormatters(FormatterRegistry registry);
/**
* Configure the list of {@link HttpMessageConverter}s to use when resolving method arguments or handling
@ -102,20 +102,20 @@ public interface WebMvcConfigurer {
* invocation. Interceptors can be registered to apply to all requests or limited to a set of path patterns.
* @see InterceptorConfigurer
*/
void configureInterceptors(InterceptorConfigurer interceptorConfigurer);
void configureInterceptors(InterceptorConfigurer configurer);
/**
* Configure the view controllers to use. A view controller is used to map a URL path directly to a view name.
* This is convenient when a request does not require controller logic.
*/
void configureViewControllers(ViewControllerConfigurer viewControllerConfigurer);
void configureViewControllers(ViewControllerConfigurer configurer);
/**
* 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);
void configureResourceHandling(ResourceConfigurer configurer);
/**
* Configure a handler for delegating unhandled requests by forwarding to the Servlet container's default
@ -123,6 +123,6 @@ public interface WebMvcConfigurer {
* 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);
void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer);
}

View File

@ -38,7 +38,7 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void addFormatters(FormatterRegistry formatterRegistry) {
public void addFormatters(FormatterRegistry registry) {
}
/**
@ -81,28 +81,28 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void configureInterceptors(InterceptorConfigurer interceptorConfigurer) {
public void configureInterceptors(InterceptorConfigurer configurer) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void configureViewControllers(ViewControllerConfigurer viewControllerConfigurer) {
public void configureViewControllers(ViewControllerConfigurer configurer) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void configureResourceHandling(ResourceConfigurer resourceConfigurer) {
public void configureResourceHandling(ResourceConfigurer configurer) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer handlerConfigurer) {
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
}
}

View File

@ -36,74 +36,74 @@ import org.springframework.web.servlet.HandlerExceptionResolver;
*/
class WebMvcConfigurerComposite implements WebMvcConfigurer {
private final List<WebMvcConfigurer> configurers = new ArrayList<WebMvcConfigurer>();
private final List<WebMvcConfigurer> delegates = new ArrayList<WebMvcConfigurer>();
public void addConfigurers(List<WebMvcConfigurer> configurers) {
public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) {
if (configurers != null) {
this.configurers.addAll(configurers);
this.delegates.addAll(configurers);
}
}
public void addFormatters(FormatterRegistry formatterRegistry) {
for (WebMvcConfigurer configurer : configurers) {
configurer.addFormatters(formatterRegistry);
public void addFormatters(FormatterRegistry registry) {
for (WebMvcConfigurer delegate : delegates) {
delegate.addFormatters(registry);
}
}
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
for (WebMvcConfigurer configurer : configurers) {
configurer.configureMessageConverters(converters);
for (WebMvcConfigurer delegate : delegates) {
delegate.configureMessageConverters(converters);
}
}
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
for (WebMvcConfigurer configurer : configurers) {
configurer.addArgumentResolvers(argumentResolvers);
for (WebMvcConfigurer delegate : delegates) {
delegate.addArgumentResolvers(argumentResolvers);
}
}
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
for (WebMvcConfigurer configurer : configurers) {
configurer.addReturnValueHandlers(returnValueHandlers);
for (WebMvcConfigurer delegate : delegates) {
delegate.addReturnValueHandlers(returnValueHandlers);
}
}
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
for (WebMvcConfigurer configurer : configurers) {
configurer.configureHandlerExceptionResolvers(exceptionResolvers);
for (WebMvcConfigurer delegate : delegates) {
delegate.configureHandlerExceptionResolvers(exceptionResolvers);
}
}
public void configureInterceptors(InterceptorConfigurer interceptorRegistry) {
for (WebMvcConfigurer configurer : configurers) {
configurer.configureInterceptors(interceptorRegistry);
public void configureInterceptors(InterceptorConfigurer configurer) {
for (WebMvcConfigurer delegate : delegates) {
delegate.configureInterceptors(configurer);
}
}
public void configureViewControllers(ViewControllerConfigurer viewControllerConfigurer) {
for (WebMvcConfigurer configurer : configurers) {
configurer.configureViewControllers(viewControllerConfigurer);
public void configureViewControllers(ViewControllerConfigurer configurer) {
for (WebMvcConfigurer delegate : delegates) {
delegate.configureViewControllers(configurer);
}
}
public void configureResourceHandling(ResourceConfigurer resourceConfigurer) {
for (WebMvcConfigurer configurer : configurers) {
configurer.configureResourceHandling(resourceConfigurer);
public void configureResourceHandling(ResourceConfigurer configurer) {
for (WebMvcConfigurer delegate : delegates) {
delegate.configureResourceHandling(configurer);
}
}
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer handlerConfigurer) {
for (WebMvcConfigurer configurer : configurers) {
configurer.configureDefaultServletHandling(handlerConfigurer);
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
for (WebMvcConfigurer delegate : delegates) {
delegate.configureDefaultServletHandling(configurer);
}
}
public Validator getValidator() {
Map<WebMvcConfigurer, Validator> validators = new HashMap<WebMvcConfigurer, Validator>();
for (WebMvcConfigurer configurer : configurers) {
Validator validator = configurer.getValidator();
for (WebMvcConfigurer delegate : delegates) {
Validator validator = delegate.getValidator();
if (validator != null) {
validators.put(configurer, validator);
validators.put(delegate, validator);
}
}
if (validators.size() == 0) {

View File

@ -127,6 +127,7 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
detectHandlerMethods(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
/**
@ -136,6 +137,13 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
*/
protected abstract boolean isHandler(Class<?> beanType);
/**
* Invoked after all handler methods found in beans of the current ApplicationContext have been registered.
* @param handlerMethods a read-only map with mapping conditions (generic type {@code <T>}) and HandlerMethods.
*/
protected void handlerMethodsInitialized(Map<T, HandlerMethod> handlerMethods) {
}
/**
* Detect and register handler methods for the specified handler.
* @param handler the bean name of a handler or a handler instance

View File

@ -171,8 +171,10 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
/**
* Set one or more custom argument resolvers to use with {@link RequestMapping}, {@link ModelAttribute}, and
* {@link InitBinder} methods. Custom argument resolvers are given a chance to resolve argument values
* ahead of the standard argument resolvers registered by default.
* {@link InitBinder} methods.
* <p>Generally custom argument resolvers are invoked first. However this excludes
* default argument resolvers that rely on the presence of annotations (e.g. {@code @RequestParameter},
* {@code @PathVariable}, etc.) Those resolvers can only be customized via {@link #setArgumentResolvers(List)}
* <p>An existing {@link WebArgumentResolver} can either adapted with {@link ServletWebArgumentResolverAdapter}
* or preferably converted to a {@link HandlerMethodArgumentResolver} instead.
*/
@ -208,8 +210,9 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
/**
* Set custom return value handlers to use to handle the return values of {@link RequestMapping} methods.
* Custom return value handlers are given a chance to handle a return value before the standard
* return value handlers registered by default.
* <p>Generally custom return value handlers are invoked first. However this excludes default return value
* handlers that rely on the presence of annotations like {@code @ResponseBody}, {@code @ModelAttribute},
* and others. Those handlers can only be customized via {@link #setReturnValueHandlers(List)}.
* @param returnValueHandlers custom return value handlers for {@link RequestMapping} methods
*/
public void setCustomReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {

View File

@ -17,6 +17,7 @@
package org.springframework.web.servlet.mvc.method.annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
@ -24,6 +25,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.springframework.core.annotation.AnnotationUtils;
@ -93,6 +95,17 @@ public class RequestMappingHandlerMapping extends AbstractHandlerMethodMapping<R
return AnnotationUtils.findAnnotation(beanType, Controller.class) != null;
}
@Override
protected void handlerMethodsInitialized(Map<RequestMappingInfo, HandlerMethod> handlerMethods) {
List<RequestMappingInfo> mappings = new ArrayList<RequestMappingInfo>(handlerMethods.keySet());
while (mappings.size() > 1) {
RequestMappingInfo mapping = mappings.remove(0);
for (RequestMappingInfo otherMapping : mappings) {
// further validate mapping conditions
}
}
}
/**
* Provides a {@link RequestMappingInfo} for the given method.
* <p>Only {@link RequestMapping @RequestMapping}-annotated methods are considered.