HandlerMappings expose usesPathPatterns() method

See gh-24945
This commit is contained in:
Rossen Stoyanchev 2020-06-15 15:53:24 +01:00
parent bb7e5f0172
commit b572f7618f
5 changed files with 41 additions and 35 deletions

View File

@ -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<HandlerMapping> 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;
}
/**

View File

@ -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.

View File

@ -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.
* <p>When parsed patterns are {@link #setPatternParser(PathPatternParser)
* enabled} a parsed {@code RequestPath} is expected to have been
* <p>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();

View File

@ -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.
*
* <p>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<PathPattern, Object> getPathPatternHandlerMap() {

View File

@ -187,8 +187,8 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
}
/**
* Return the patterns condition in use when parsed patterns are enabled via
* {@link org.springframework.web.servlet.handler.AbstractHandlerMapping#setPatternParser(PathPatternParser)}.
* Return the patterns condition in use when parsed patterns are
* {@link AbstractHandlerMapping#usesPathPatterns() enabled}.
* <p>This 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 RequestCondition<RequestMapping
/**
* Enable use of parsed {@link PathPattern} as described in
* Enable use of parsed {@link PathPattern}s as described in
* {@link AbstractHandlerMapping#setPatternParser(PathPatternParser)}.
* <p><strong>Note:</strong> This property is mutually exclusive with
* {@link #setPathMatcher(PathMatcher)}.