diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.java index 968113e8aa..df51b64f25 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/annotation/DefaultAnnotationHandlerMapping.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * 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. @@ -37,37 +37,47 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping; /** - * Implementation of the {@link org.springframework.web.servlet.HandlerMapping} interface that maps handlers based on - * HTTP paths expressed through the {@link RequestMapping} annotation at the type or method level. + * Implementation of the {@link org.springframework.web.servlet.HandlerMapping} + * interface that maps handlers based on HTTP paths expressed through the + * {@link RequestMapping} annotation at the type or method level. * - *
Registered by default in {@link org.springframework.web.servlet.DispatcherServlet} on Java 5+. NOTE: If you - * define custom HandlerMapping beans in your DispatcherServlet context, you need to add a - * DefaultAnnotationHandlerMapping bean explicitly, since custom HandlerMapping beans replace the default mapping - * strategies. Defining a DefaultAnnotationHandlerMapping also allows for registering custom interceptors: + *
Registered by default in {@link org.springframework.web.servlet.DispatcherServlet} + * on Java 5+. NOTE: If you define custom HandlerMapping beans in your + * DispatcherServlet context, you need to add a DefaultAnnotationHandlerMapping bean + * explicitly, since custom HandlerMapping beans replace the default mapping strategies. + * Defining a DefaultAnnotationHandlerMapping also allows for registering custom + * interceptors: * - *
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> - * <property name="interceptors"> ... </property> </bean>+ *
+ * <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> + * <property name="interceptors"> + * ... + * </property> + * </bean>* - * Annotated controllers are usually marked with the {@link Controller} stereotype at the type level. This is not - * strictly necessary when {@link RequestMapping} is applied at the type level (since such a handler usually implements - * the {@link org.springframework.web.servlet.mvc.Controller} interface). However, {@link Controller} is required for - * detecting {@link RequestMapping} annotations at the method level if {@link RequestMapping} is not present at the type - * level. + * Annotated controllers are usually marked with the {@link Controller} stereotype + * at the type level. This is not strictly necessary when {@link RequestMapping} is + * applied at the type level (since such a handler usually implements the + * {@link org.springframework.web.servlet.mvc.Controller} interface). However, + * {@link Controller} is required for detecting {@link RequestMapping} annotations + * at the method level if {@link RequestMapping} is not present at the type level. * - *
NOTE: Method-level mappings are only allowed to narrow the mapping expressed at the class level (if any). - * HTTP paths need to uniquely map onto specific handler beans, with any given HTTP path only allowed to be mapped onto - * one specific handler bean (not spread across multiple handler beans). It is strongly recommended to co-locate related - * handler methods into the same bean. + *
NOTE: Method-level mappings are only allowed to narrow the mapping + * expressed at the class level (if any). HTTP paths need to uniquely map onto + * specific handler beans, with any given HTTP path only allowed to be mapped + * onto one specific handler bean (not spread across multiple handler beans). + * It is strongly recommended to co-locate related handler methods into the same bean. * - *
The {@link AnnotationMethodHandlerAdapter} is responsible for processing annotated handler methods, as mapped by - * this HandlerMapping. For {@link RequestMapping} at the type level, specific HandlerAdapters such as {@link - * org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter} apply. + *
The {@link AnnotationMethodHandlerAdapter} is responsible for processing
+ * annotated handler methods, as mapped by this HandlerMapping. For
+ * {@link RequestMapping} at the type level, specific HandlerAdapters such as
+ * {@link org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter} apply.
*
* @author Juergen Hoeller
* @author Arjen Poutsma
+ * @since 2.5
* @see RequestMapping
* @see AnnotationMethodHandlerAdapter
- * @since 2.5
*/
public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandlerMapping {
@@ -75,19 +85,23 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler
private final Map Default is "true". Turn this convention off if you intend to interpret your
- * Note that paths which include a ".xxx" suffix or end with "/"
- * already will not be transformed using the default suffix pattern in any case.
+ * Set whether to register paths using the default suffix pattern as well:
+ * i.e. whether "/users" should be registered as "/users.*" and "/users/" too.
+ * Default is "true". Turn this convention off if you intend to interpret
+ * your Note that paths which include a ".xxx" suffix or end with "/" already will not be
+ * transformed using the default suffix pattern in any case.
*/
public void setUseDefaultSuffixPattern(boolean useDefaultSuffixPattern) {
this.useDefaultSuffixPattern = useDefaultSuffixPattern;
}
+
/**
- * Checks for presence of the {@link org.springframework.web.bind.annotation.RequestMapping} annotation on the handler
- * class and on any of its methods.
+ * Checks for presence of the {@link org.springframework.web.bind.annotation.RequestMapping}
+ * annotation on the handler class and on any of its methods.
*/
@Override
protected String[] determineUrlsForHandler(String beanName) {
@@ -101,7 +115,7 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler
String[] typeLevelPatterns = mapping.value();
if (typeLevelPatterns.length > 0) {
// @RequestMapping specifies paths at type level
- String[] methodLevelPatterns = determineUrlsForHandlerMethods(handlerType);
+ String[] methodLevelPatterns = determineUrlsForHandlerMethods(handlerType, true);
for (String typeLevelPattern : typeLevelPatterns) {
if (!typeLevelPattern.startsWith("/")) {
typeLevelPattern = "/" + typeLevelPattern;
@@ -110,7 +124,8 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler
for (String methodLevelPattern : methodLevelPatterns) {
if (methodLevelPattern == null) {
hasEmptyMethodLevelMappings = true;
- } else {
+ }
+ else {
String combinedPattern = getPathMatcher().combine(typeLevelPattern, methodLevelPattern);
addUrlsForPath(urls, combinedPattern);
}
@@ -124,12 +139,12 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler
}
else {
// actual paths specified by @RequestMapping at method level
- return determineUrlsForHandlerMethods(handlerType);
+ return determineUrlsForHandlerMethods(handlerType, false);
}
}
else if (AnnotationUtils.findAnnotation(handlerType, Controller.class) != null) {
// @RequestMapping to be introspected at method level
- return determineUrlsForHandlerMethods(handlerType);
+ return determineUrlsForHandlerMethods(handlerType, false);
}
else {
return null;
@@ -138,13 +153,17 @@ public class DefaultAnnotationHandlerMapping extends AbstractDetectingUrlHandler
/**
* Derive URL mappings from the handler's method-level mappings.
- *
- * The returned array may contain {@code null}, indicating an empty {@link RequestMapping} value.
- *
* @param handlerType the handler type to introspect
+ * @param indicateEmpty whether the returned array should contain
+ * @RequestMapping paths strictly. @RequestMapping paths strictly.
+ * null in case of an empty {@link RequestMapping} value.
* @return the array of mapped URLs
*/
- protected String[] determineUrlsForHandlerMethods(Class> handlerType) {
+ protected String[] determineUrlsForHandlerMethods(Class> handlerType, final boolean indicateEmpty) {
+ String[] subclassResult = determineUrlsForHandlerMethods(handlerType);
+ if (subclassResult != null) {
+ return subclassResult;
+ }
+
final Set