From 6e03b4dd64245238856b28c156b0d27b79398627 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 12 Apr 2011 13:23:14 +0000 Subject: [PATCH] SWF-8214 javadoc updates --- .../handler/AbstractHandlerMethodMapping.java | 19 ++++- .../mvc/method/annotation/RequestKey.java | 66 ++++++++++----- .../RequestMappingHandlerMethodMapping.java | 80 +++++++++++++------ 3 files changed, 119 insertions(+), 46 deletions(-) diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java index ac0ad59445..09819b692c 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java @@ -36,8 +36,22 @@ import org.springframework.web.method.HandlerMethodSelector; /** * Abstract base class for {@link org.springframework.web.servlet.HandlerMapping HandlerMapping} implementations that - * support {@link HandlerMethod}s. + * support mapping requests to {@link HandlerMethod}s rather than to handlers. + * + *

Each {@link HandlerMethod} is registered with a unique key. Subclasses define the key type and how to create it + * for a given handler method. Keys represent conditions for matching a handler method to a request. * + *

Subclasses must also define how to create a key for an incoming request. The resulting key is used to perform + * a {@link HandlerMethod} lookup possibly resulting in a direct match. However, when a map lookup is insufficient, + * the keys of all handler methods are iterated and subclasses are allowed to make an exhaustive check of key + * conditions against the request. + * + *

Since there can be more than one matching key for a request, subclasses must define a comparator for sorting + * the keys of matching handler methods in order to find the most specific match. + * + * @param A unique key for the registration of mapped {@link HandlerMethod}s representing the conditions to + * match a handler method to a request. + * * @author Arjen Poutsma * @author Rossen Stoyanchev * @since 3.1 @@ -80,6 +94,9 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap */ protected abstract boolean isHandler(String beanName); + /** + * Detect and register handler methods for the specified handler. + */ private void detectHandlerMethods(final String handlerName) { Class handlerType = getApplicationContext().getType(handlerName); diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestKey.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestKey.java index e4918d748d..7e45971829 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestKey.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestKey.java @@ -33,10 +33,18 @@ import org.springframework.web.servlet.mvc.method.condition.RequestConditionFact import org.springframework.web.util.UrlPathHelper; /** - * TODO + * Contains a set of conditions to match to a given request such as URL patterns, HTTP methods, request + * parameters and headers. + * + *

A {@link RequestKey} can be combined with another {@link RequestKey} resulting in a new {@link RequestKey} + * with conditions from both (see {@link #combine(RequestKey, PathMatcher)}). + * + *

A {@link RequestKey} can be matched to a request resulting in a new {@link RequestKey} with the subset of + * conditions relevant to the request (see {@link #getMatchingKey(HttpServletRequest, PathMatcher, UrlPathHelper)}). * * @author Arjen Poutsma * @author Rossen Stoyanchev + * @since 3.1 */ public final class RequestKey { @@ -52,14 +60,19 @@ public final class RequestKey { private int hash; + /** + * Creates a new {@code RequestKey} instance with the given URL patterns and HTTP methods. + * + *

Package protected for testing purposes. + */ RequestKey(Collection patterns, Collection methods) { this(patterns, methods, null, null, null); } /** - * Creates a new {@code RequestKey} instance with the given parameters. - * - *

Package protected for testing purposes. + * Creates a new {@code RequestKey} instance with a full set of conditions. + * + *

Package protected for testing purposes. */ RequestKey(Collection patterns, Collection methods, @@ -152,12 +165,22 @@ public final class RequestKey { } /** - * Combines this {@code RequestKey} with another. The typical use case for this is combining type - * and method-level {@link RequestMapping @RequestMapping} annotations. - * - * @param methodKey the method-level RequestKey + * Combines this {@code RequestKey} with another as follows: + *

+ * @param methodKey the key to combine with * @param pathMatcher to {@linkplain PathMatcher#combine(String, String) combine} the patterns - * @return the combined request key + * @return a new request key containing conditions from both keys */ public RequestKey combine(RequestKey methodKey, PathMatcher pathMatcher) { Set patterns = combinePatterns(this.patterns, methodKey.patterns, pathMatcher); @@ -199,15 +222,18 @@ public final class RequestKey { } /** - * Returns a new {@code RequestKey} that contains all matching attributes of this key, given the {@link - * HttpServletRequest}. Matching patterns in the returned RequestKey are sorted according to {@link - * PathMatcher#getPatternComparator(String)} with the best matching pattern at the top. - * - * @param request the servlet request - * @param pathMatcher to {@linkplain PathMatcher#match(String, String) match} patterns - * @param urlPathHelper to create the {@linkplain UrlPathHelper#getLookupPathForRequest(HttpServletRequest) lookup - * path} - * @return a new request key that contains all matching attributes + * Returns a new {@code RequestKey} that contains all conditions of this key that are relevant to the request. + * + * @param request the current request + * @param pathMatcher to check for matching patterns + * @param urlPathHelper to derive the lookup path for the request + * @return a new request key that contains all matching attributes, or {@code null} if not all conditions match */ public RequestKey getMatchingKey(HttpServletRequest request, PathMatcher pathMatcher, UrlPathHelper urlPathHelper) { if (!checkMethod(request) || !paramsCondition.match(request) || !headersCondition.match(request) || @@ -217,7 +243,7 @@ public final class RequestKey { else { List matchingPatterns = getMatchingPatterns(request, pathMatcher, urlPathHelper); if (!matchingPatterns.isEmpty()) { - Set matchingMethods = getMatchingMethods(request); + Set matchingMethods = getMatchingMethod(request); return new RequestKey(matchingPatterns, matchingMethods, this.paramsCondition, this.headersCondition, this.consumesCondition); } @@ -245,7 +271,7 @@ public final class RequestKey { return matchingPatterns; } - private Set getMatchingMethods(HttpServletRequest request) { + private Set getMatchingMethod(HttpServletRequest request) { if (this.methods.isEmpty()) { return this.methods; } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodMapping.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodMapping.java index e6c0f30d8a..c602fd87ae 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodMapping.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodMapping.java @@ -23,6 +23,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; @@ -44,7 +45,22 @@ import org.springframework.web.servlet.handler.MappedInterceptors; import org.springframework.web.util.UrlPathHelper; /** - * TODO + * An {@link AbstractHandlerMethodMapping} variant that uses {@link RequestKey}s for the registration and the lookup + * of {@link HandlerMethod}s. + * + *

A {@link RequestKey} for an incoming request contains the URL and the HTTP method of the request. + * A {@link RequestKey} for a handler method contains all conditions found in the method @{@link RequestMapping} + * annotation combined with all conditions found in the type @{@link RequestMapping} annotation, if present. + * + *

An incoming request matches to a handler method directly when a @{@link RequestMapping} annotation contains + * a single, non-pattern URL and a single HTTP method. When a {@link RequestKey} contains additional conditions + * (e.g. more URL patterns, request parameters, headers, etc) those conditions must be checked against the + * request rather than against the key that represents it. This results in the creation of a new handler method + * {@link RequestKey} with the subset of conditions relevant to the current request (see + * {@link RequestKey#getMatchingKey(HttpServletRequest, PathMatcher, UrlPathHelper)}). + * Such keys can then be compared against each other, in the context of the current request, making it possible + * to select to the best matching {@link RequestKey} in case of multiple matches and also the best matching + * pattern within the selected key. * * @author Arjen Poutsma * @author Rossen Stoyanchev @@ -168,6 +184,18 @@ public class RequestMappingHandlerMethodMapping extends AbstractHandlerMethodMap } } + /** + * Returns a new {@link RequestKey} with attributes matching to the current request or {@code null}. + * @see RequestKey#getMatchingKey(HttpServletRequest, PathMatcher, UrlPathHelper) + */ + @Override + protected RequestKey getMatchingKey(RequestKey key, HttpServletRequest request) { + return key.getMatchingKey(request, pathMatcher, urlPathHelper); + } + + /** + * Returns a {@link Comparator} that can be used to sort and select the best matching {@link RequestKey}. + */ @Override protected Comparator getKeyComparator(HttpServletRequest request) { return new RequestKeyComparator(request); @@ -181,24 +209,10 @@ public class RequestMappingHandlerMethodMapping extends AbstractHandlerMethodMap request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables); } - @Override - protected RequestKey getMatchingKey(RequestKey key, HttpServletRequest request) { - return key.getMatchingKey(request, pathMatcher, urlPathHelper); - } - - @Override - protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { - HandlerExecutionChain chain = super.getHandlerExecutionChain(handler, request); - if (this.mappedInterceptors != null) { - String lookupPath = urlPathHelper.getLookupPathForRequest(request); - HandlerInterceptor[] handlerInterceptors = mappedInterceptors.getInterceptors(lookupPath, pathMatcher); - if (handlerInterceptors.length > 0) { - chain.addInterceptors(handlerInterceptors); - } - } - return chain; - } - + /** + * Iterates all {@link RequestKey}s looking for keys that match by URL but not by HTTP method. + * @exception HttpRequestMethodNotSupportedException if there are matches by URL but not by HTTP method + */ @Override protected HandlerMethod handleNoMatch(Set requestKeys, HttpServletRequest request) throws HttpRequestMethodNotSupportedException { @@ -223,13 +237,29 @@ public class RequestMappingHandlerMethodMapping extends AbstractHandlerMethodMap } /** - * A comparator for RequestKey types. Effective comparison can only be done in the context of a specific request. For - * example not all configured patterns may apply to the current request. Therefore an HttpServletRequest is required as - * input. + * Adds mapped interceptors to the handler execution chain. + */ + @Override + protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { + HandlerExecutionChain chain = super.getHandlerExecutionChain(handler, request); + if (this.mappedInterceptors != null) { + String lookupPath = urlPathHelper.getLookupPathForRequest(request); + HandlerInterceptor[] handlerInterceptors = mappedInterceptors.getInterceptors(lookupPath, pathMatcher); + if (handlerInterceptors.length > 0) { + chain.addInterceptors(handlerInterceptors); + } + } + return chain; + } + + /** + * A comparator for {@link RequestKey}s. Effective comparison can only be done in the context of a + * specific request. For example not all {@link RequestKey} patterns may apply to the current request. + * Therefore an HttpServletRequest is required as input. * - * Furthermore, the following assumptions are made about the input RequestKeys:

  • Each RequestKey has been fully - * matched to the request
  • The RequestKey contains matched patterns only
  • Patterns are ordered with the best - * matching pattern at the top
+ *

Furthermore, the following assumptions are made about the input RequestKeys: + *

  • Each RequestKey has been fully matched to the request
  • The RequestKey contains matched + * patterns only
  • Patterns are ordered with the best matching pattern at the top
* * @see RequestMappingHandlerMethodMapping#getMatchingKey(RequestKey, HttpServletRequest) */