From b572f7618f01897b611a47376c538b88be4dff80 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 15 Jun 2020 15:53:24 +0100 Subject: [PATCH] HandlerMappings expose usesPathPatterns() method See gh-24945 --- .../web/servlet/DispatcherServlet.java | 25 +++---------------- .../web/servlet/HandlerMapping.java | 16 ++++++++++++ .../handler/AbstractHandlerMapping.java | 15 ++++++++--- .../handler/AbstractUrlHandlerMapping.java | 14 +++++------ .../mvc/method/RequestMappingInfo.java | 6 ++--- 5 files changed, 41 insertions(+), 35 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java index 5dbed6bb2d..b1d9f85242 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/DispatcherServlet.java @@ -40,8 +40,6 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.aop.framework.AopProxyUtils; -import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -65,7 +63,6 @@ import org.springframework.web.context.request.async.WebAsyncUtils; import org.springframework.web.multipart.MultipartException; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartResolver; -import org.springframework.web.servlet.handler.AbstractHandlerMapping; import org.springframework.web.util.NestedServletException; import org.springframework.web.util.ServletRequestPathUtils; import org.springframework.web.util.WebUtils; @@ -630,26 +627,12 @@ public class DispatcherServlet extends FrameworkServlet { } } - this.parseRequestPath = initRequestPathParsing(this.handlerMappings); - } - - private boolean initRequestPathParsing(List mappings) { - for (HandlerMapping mapping : mappings) { - if (mapping instanceof AbstractHandlerMapping) { - if (((AbstractHandlerMapping) mapping).getPatternParser() != null) { - return true; - } - } - if (AopUtils.isAopProxy(mapping)) { - Object target = AopProxyUtils.getSingletonTarget(mapping); - if (target instanceof AbstractHandlerMapping) { - if (((AbstractHandlerMapping) target).getPatternParser() != null) { - return true; - } - } + for (HandlerMapping mapping : this.handlerMappings) { + if (mapping.usesPathPatterns()) { + this.parseRequestPath = true; + break; } } - return false; } /** diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java index 3bcd3761b6..1052508937 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerMapping.java @@ -136,6 +136,22 @@ public interface HandlerMapping { */ String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes"; + + /** + * Whether this {@code HandlerMapping} instance has been enabled to use parsed + * {@link org.springframework.web.util.pattern.PathPattern}s in which case + * the {@link DispatcherServlet} automatically + * {@link org.springframework.web.util.ServletRequestPathUtils#parseAndCache parses} + * the {@code RequestPath} to make it available for + * {@link org.springframework.web.util.ServletRequestPathUtils#getParsedRequestPath + * access} in {@code HandlerMapping}s, {@code HandlerInterceptor}s, and + * other components. + * @since 5.3 + */ + default boolean usesPathPatterns() { + return false; + } + /** * Return a handler and any interceptors for this request. The choice may be made * on request URL, session state, or any factor the implementing class chooses. diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java index adc610606e..07328f1d8c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java @@ -469,6 +469,15 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport } + /** + * Return "true" if this {@code HandlerMapping} has been + * {@link #setPatternParser enabled} to use parsed {@code PathPattern}s. + */ + @Override + public boolean usesPathPatterns() { + return getPatternParser() != null; + } + /** * Look up a handler for the given request, falling back to the default * handler if no specific one is found. @@ -534,8 +543,8 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport /** * Initialize the path to use for request mapping. - *

When parsed patterns are {@link #setPatternParser(PathPatternParser) - * enabled} a parsed {@code RequestPath} is expected to have been + *

When parsed patterns are {@link #usesPathPatterns() enabled} a parsed + * {@code RequestPath} is expected to have been * {@link ServletRequestPathUtils#parseAndCache(HttpServletRequest) parsed} * externally by the {@link org.springframework.web.servlet.DispatcherServlet} * or {@link org.springframework.web.filter.ServletRequestPathFilter}. @@ -545,7 +554,7 @@ public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport * @since 5.3 */ protected String initLookupPath(HttpServletRequest request) { - if (getPatternParser() != null) { + if (usesPathPatterns()) { request.removeAttribute(UrlPathHelper.PATH_ATTRIBUTE); RequestPath requestPath = ServletRequestPathUtils.getParsedRequestPath(request); String lookupPath = requestPath.pathWithinApplication().value(); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java index 83af09e292..c0c1b6030c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java @@ -40,15 +40,14 @@ import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.util.ServletRequestPathUtils; import org.springframework.web.util.UrlPathHelper; import org.springframework.web.util.pattern.PathPattern; -import org.springframework.web.util.pattern.PathPatternParser; /** * Abstract base class for URL-mapped {@link HandlerMapping} implementations. * *

Supports literal matches and pattern matches such as "/test/*", "/test/**", * and others. For details on pattern syntax refer to {@link PathPattern} when - * parsed patterns are {@link #setPatternParser(PathPatternParser) enabled} or - * see {@link AntPathMatcher} otherwise. The syntax is largely the same but the + * parsed patterns are {@link #usesPathPatterns() enabled} or see + * {@link AntPathMatcher} otherwise. The syntax is largely the same but the * {@code PathPattern} syntax is more tailored for web applications, and its * implementation is more efficient. * @@ -135,7 +134,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i protected Object getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = initLookupPath(request); Object handler; - if (getPatternParser() != null) { + if (usesPathPatterns()) { RequestPath path = ServletRequestPathUtils.getParsedRequestPath(request); handler = lookupHandler(path, lookupPath, request); } @@ -167,8 +166,7 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i /** * Look up a handler instance for the given URL path. This method is used - * when parsed {@code PathPattern}s are - * {@link #setPatternParser(PathPatternParser) enabled}. + * when parsed {@code PathPattern}s are {@link #usesPathPatterns() enabled}. * @param path the parsed RequestPath * @param lookupPath the String lookupPath for checking direct hits * @param request current HTTP request @@ -462,8 +460,8 @@ public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping i } /** - * Identical to {@link #getHandlerMap()} but with parsed patterns when - * {@link #setPatternParser(PathPatternParser)} is set, or otherwise empty. + * Identical to {@link #getHandlerMap()} but populated when parsed patterns + * are {@link #usesPathPatterns() enabled}; otherwise empty. * @since 5.3 */ public final Map getPathPatternHandlerMap() { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java index ab9320bfa3..62f517a4c7 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java @@ -187,8 +187,8 @@ public final class RequestMappingInfo implements RequestConditionThis is mutually exclusive with {@link #getPatternsCondition()} such * that when one returns {@code null} the other one returns an instance. * @since 5.3 @@ -750,7 +750,7 @@ public final class RequestMappingInfo implements RequestConditionNote: This property is mutually exclusive with * {@link #setPathMatcher(PathMatcher)}.