Introduce PathPatternParser for optimized path matching
This commit introduces a PathPatternParser which parses request pattern strings into PathPattern objects which can then be used to fast match incoming string paths. The parser and matching supports the syntax as described in SPR-14544. The code is optimized around the common usages of request patterns and is designed to create very little transient garbage when matching. Issue: SPR-14544
This commit is contained in:
committed by
Brian Clozel
parent
6f029392c7
commit
f58ffad939
@@ -31,11 +31,11 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.reactive.function.BodyExtractor;
|
||||
import org.springframework.web.server.WebSession;
|
||||
import org.springframework.web.util.ParsingPathMatcher;
|
||||
|
||||
/**
|
||||
* Implementations of {@link RequestPredicate} that implement various useful request matching operations, such as
|
||||
@@ -46,7 +46,7 @@ import org.springframework.web.server.WebSession;
|
||||
*/
|
||||
public abstract class RequestPredicates {
|
||||
|
||||
private static final PathMatcher DEFAULT_PATH_MATCHER = new AntPathMatcher();
|
||||
private static final PathMatcher DEFAULT_PATH_MATCHER = new ParsingPathMatcher();
|
||||
|
||||
/**
|
||||
* Returns a {@code RequestPredicate} that always matches.
|
||||
|
||||
@@ -22,7 +22,6 @@ import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.context.support.ApplicationObjectSupport;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
@@ -35,6 +34,7 @@ import org.springframework.web.reactive.HandlerMapping;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.support.HttpRequestPathHelper;
|
||||
import org.springframework.web.util.ParsingPathMatcher;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link org.springframework.web.reactive.HandlerMapping}
|
||||
@@ -53,7 +53,7 @@ public abstract class AbstractHandlerMapping extends ApplicationObjectSupport im
|
||||
|
||||
private HttpRequestPathHelper pathHelper = new HttpRequestPathHelper();
|
||||
|
||||
private PathMatcher pathMatcher = new AntPathMatcher();
|
||||
private PathMatcher pathMatcher = new ParsingPathMatcher();
|
||||
|
||||
private final UrlBasedCorsConfigurationSource globalCorsConfigSource = new UrlBasedCorsConfigurationSource();
|
||||
|
||||
|
||||
@@ -33,11 +33,11 @@ import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.support.HttpRequestPathHelper;
|
||||
import org.springframework.web.util.ParsingPathMatcher;
|
||||
|
||||
/**
|
||||
* A central component to use to obtain the public URL path that clients should
|
||||
@@ -56,7 +56,7 @@ public class ResourceUrlProvider implements ApplicationListener<ContextRefreshed
|
||||
|
||||
private HttpRequestPathHelper urlPathHelper = new HttpRequestPathHelper();
|
||||
|
||||
private PathMatcher pathMatcher = new AntPathMatcher();
|
||||
private PathMatcher pathMatcher = new ParsingPathMatcher();
|
||||
|
||||
private final Map<String, ResourceWebHandler> handlerMap = new LinkedHashMap<>();
|
||||
|
||||
|
||||
@@ -27,11 +27,11 @@ import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.support.HttpRequestPathHelper;
|
||||
import org.springframework.web.util.ParsingPathMatcher;
|
||||
|
||||
/**
|
||||
* A logical disjunction (' || ') request condition that matches a request
|
||||
@@ -90,7 +90,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
||||
|
||||
this.patterns = Collections.unmodifiableSet(prependLeadingSlash(patterns));
|
||||
this.pathHelper = (pathHelper != null ? pathHelper : new HttpRequestPathHelper());
|
||||
this.pathMatcher = (pathMatcher != null ? pathMatcher : new AntPathMatcher());
|
||||
this.pathMatcher = (pathMatcher != null ? pathMatcher : new ParsingPathMatcher());
|
||||
this.useSuffixPatternMatch = useSuffixPatternMatch;
|
||||
this.useTrailingSlashMatch = useTrailingSlashMatch;
|
||||
if (fileExtensions != null) {
|
||||
|
||||
@@ -74,7 +74,7 @@ public class SimpleUrlHandlerMappingTests {
|
||||
testUrl("welcome.html", null, handlerMapping, null);
|
||||
testUrl("/pathmatchingAA.html", mainController, handlerMapping, "pathmatchingAA.html");
|
||||
testUrl("/pathmatchingA.html", null, handlerMapping, null);
|
||||
testUrl("/administrator/pathmatching.html", mainController, handlerMapping, "pathmatching.html");
|
||||
testUrl("/administrator/pathmatching.html", mainController, handlerMapping, "/administrator/pathmatching.html");
|
||||
testUrl("/administrator/test/pathmatching.html", mainController, handlerMapping, "test/pathmatching.html");
|
||||
testUrl("/administratort/pathmatching.html", null, handlerMapping, null);
|
||||
testUrl("/administrator/another/bla.xml", mainController, handlerMapping, "/administrator/another/bla.xml");
|
||||
|
||||
@@ -98,9 +98,9 @@ public class PatternsRequestConditionTests {
|
||||
|
||||
@Test
|
||||
public void matchSortPatterns() throws Exception {
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition("/**", "/foo/bar", "/foo/*");
|
||||
PatternsRequestCondition condition = new PatternsRequestCondition("/*/*", "/foo/bar", "/foo/*");
|
||||
PatternsRequestCondition match = condition.getMatchingCondition(createExchange("/foo/bar"));
|
||||
PatternsRequestCondition expected = new PatternsRequestCondition("/foo/bar", "/foo/*", "/**");
|
||||
PatternsRequestCondition expected = new PatternsRequestCondition("/foo/bar", "/foo/*", "/*/*");
|
||||
|
||||
assertEquals(expected, match);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
@@ -41,6 +40,7 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.session.MockWebSessionManager;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
import org.springframework.web.util.ParsingPathMatcher;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -158,7 +158,7 @@ public class HandlerMethodMappingTests {
|
||||
|
||||
private static class MyHandlerMethodMapping extends AbstractHandlerMethodMapping<String> {
|
||||
|
||||
private PathMatcher pathMatcher = new AntPathMatcher();
|
||||
private PathMatcher pathMatcher = new ParsingPathMatcher();
|
||||
|
||||
@Override
|
||||
protected boolean isHandler(Class<?> beanType) {
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="mapping" class="org.springframework.web.reactive.handler.SimpleUrlHandlerMapping">
|
||||
<property name="urlDecode" value="true" />
|
||||
<property name="mappings">
|
||||
<value>
|
||||
welcome.html=mainController
|
||||
/**/pathmatchingTest.html=mainController
|
||||
/**/pathmatching??.html=mainController
|
||||
/**/path??matching.html=mainController
|
||||
/**/??path??matching.html=mainController
|
||||
/**/*.jsp=mainController
|
||||
/administrator/**/pathmatching.html=mainController
|
||||
/administrator/**/testlast*=mainController
|
||||
/*pathmatchingTest.html=mainController
|
||||
/pathmatching??.html=mainController
|
||||
/administrator/pathmatching.html=mainController
|
||||
/administrator/*/pathmatching.html=mainController
|
||||
/administrator/*/testlast*=mainController
|
||||
/administrator/testing/longer/*=mainController
|
||||
/??path??matching.html=mainController
|
||||
/path??matching.html=mainController
|
||||
/administrator/another/bla.xml=mainController
|
||||
/administrator/testing/longer/**/**/**/**/**=mainController
|
||||
/administrator/testing/longer2/**/**/bla/**=mainController
|
||||
/*test*.jpeg=mainController
|
||||
/*/test.jpeg=mainController
|
||||
/outofpattern*yeah=mainController
|
||||
|
||||
Reference in New Issue
Block a user