diff --git a/spring-web/src/main/java/org/springframework/web/cors/reactive/UrlBasedCorsConfigurationSource.java b/spring-web/src/main/java/org/springframework/web/cors/reactive/UrlBasedCorsConfigurationSource.java index eb63921553..a7d9067e66 100644 --- a/spring-web/src/main/java/org/springframework/web/cors/reactive/UrlBasedCorsConfigurationSource.java +++ b/spring-web/src/main/java/org/springframework/web/cors/reactive/UrlBasedCorsConfigurationSource.java @@ -18,6 +18,7 @@ package org.springframework.web.cors.reactive; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.SortedSet; @@ -71,12 +72,14 @@ public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource /** * Set CORS configuration based on URL patterns. */ - public void setCorsConfigurations(Map corsConfigurations) { + public void setCorsConfigurations(Map corsConfigurations) { this.patternRegistry.clear(); this.corsConfigurations.clear(); if (corsConfigurations != null) { - this.patternRegistry.addAll(corsConfigurations.keySet()); - this.corsConfigurations.putAll(corsConfigurations); + corsConfigurations.forEach((pattern, config) -> { + List registered = this.patternRegistry.register(pattern); + registered.forEach(p -> this.corsConfigurations.put(p, config)); + }); } } diff --git a/spring-web/src/main/java/org/springframework/web/util/patterns/PathPatternRegistry.java b/spring-web/src/main/java/org/springframework/web/util/patterns/PathPatternRegistry.java index 0e04f51096..ee4fc95ba4 100644 --- a/spring-web/src/main/java/org/springframework/web/util/patterns/PathPatternRegistry.java +++ b/spring-web/src/main/java/org/springframework/web/util/patterns/PathPatternRegistry.java @@ -17,7 +17,6 @@ package org.springframework.web.util.patterns; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; @@ -63,6 +62,11 @@ public class PathPatternRegistry { this.patterns = new HashSet<>(); } + public PathPatternRegistry(Set patterns) { + this(); + this.patterns.addAll(patterns); + } + /** * Whether to match to paths irrespective of the presence of a trailing slash. */ @@ -150,30 +154,6 @@ public class PathPatternRegistry { return this.pathPatternParser.parse(pathPattern); } - /** - * Add a {@link PathPattern} instance to this registry - * @return true if this registry did not already contain the specified {@code PathPattern} - */ - public boolean add(PathPattern pathPattern) { - return this.patterns.add(pathPattern); - } - - /** - * Add all {@link PathPattern}s instance to this registry - * @return true if this registry did not already contain at least one of the given {@code PathPattern}s - */ - public boolean addAll(Collection pathPatterns) { - return this.patterns.addAll(pathPatterns); - } - - /** - * Remove the given {@link PathPattern} from this registry - * @return true if this registry contained the given {@code PathPattern} - */ - public boolean remove(PathPattern pathPattern) { - return this.patterns.remove(pathPattern); - } - /** * Remove all {@link PathPattern}s from this registry */ @@ -197,25 +177,7 @@ public class PathPatternRegistry { * @return the list of {@link PathPattern} that were registered as a result */ public List register(String rawPattern) { - String fixedPattern = prependLeadingSlash(rawPattern); - List newPatterns = new ArrayList<>(); - PathPattern pattern = this.pathPatternParser.parse(fixedPattern); - newPatterns.add(pattern); - if (StringUtils.hasLength(fixedPattern) && !pattern.isCatchAll()) { - if (this.useSuffixPatternMatch) { - if (this.fileExtensions != null && !this.fileExtensions.isEmpty()) { - for (String extension : this.fileExtensions) { - newPatterns.add(this.pathPatternParser.parse(fixedPattern + extension)); - } - } - else { - newPatterns.add(this.pathPatternParser.parse(fixedPattern + ".*")); - } - } - if (this.useTrailingSlashMatch && !fixedPattern.endsWith("/")) { - newPatterns.add(this.pathPatternParser.parse(fixedPattern + "/")); - } - } + List newPatterns = generatePathPatterns(rawPattern); this.patterns.addAll(newPatterns); return newPatterns; } @@ -229,6 +191,44 @@ public class PathPatternRegistry { } } + private List generatePathPatterns(String rawPattern) { + String fixedPattern = prependLeadingSlash(rawPattern); + List patterns = new ArrayList<>(); + PathPattern pattern = this.pathPatternParser.parse(fixedPattern); + patterns.add(pattern); + if (StringUtils.hasLength(fixedPattern) && !pattern.isCatchAll()) { + if (this.useSuffixPatternMatch) { + if (this.fileExtensions != null && !this.fileExtensions.isEmpty()) { + for (String extension : this.fileExtensions) { + patterns.add(this.pathPatternParser.parse(fixedPattern + extension)); + } + } + else { + patterns.add(this.pathPatternParser.parse(fixedPattern + ".*")); + } + } + if (this.useTrailingSlashMatch && !fixedPattern.endsWith("/")) { + patterns.add(this.pathPatternParser.parse(fixedPattern + "/")); + } + } + return patterns; + } + + /** + * Parse the given {@code rawPattern} and removes it to this registry, + * as well as pattern variants, depending on the given options and + * the nature of the input pattern. + * + * @param rawPattern raw path pattern to parse and unregister + * @return the list of {@link PathPattern} that were unregistered as a result + */ + public List unregister(String rawPattern) { + List unregisteredPatterns = generatePathPatterns(rawPattern); + this.patterns.removeAll(unregisteredPatterns); + return unregisteredPatterns; + } + + /** * Combine the patterns contained in the current registry * with the ones in the other, into a new {@code PathPatternRegistry} instance. diff --git a/spring-web/src/test/java/org/springframework/web/util/patterns/PathPatternRegistryTests.java b/spring-web/src/test/java/org/springframework/web/util/patterns/PathPatternRegistryTests.java index b72b850c88..823a1b52b6 100644 --- a/spring-web/src/test/java/org/springframework/web/util/patterns/PathPatternRegistryTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/patterns/PathPatternRegistryTests.java @@ -146,8 +146,8 @@ public class PathPatternRegistryTests { PathPattern fooTwo = this.registry.parsePattern("/f?o"); assertThat(fooOne.compareTo(fooTwo), is(0)); - this.registry.add(fooOne); - this.registry.add(fooTwo); + this.registry.register("/fo?"); + this.registry.register("/f?o"); Set matches = this.registry.findMatches("/foo"); assertThat(getPatternList(matches), Matchers.contains("/f?o", "/fo?")); } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java index d7d7864a1e..0e104abf96 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceUrlProvider.java @@ -84,12 +84,16 @@ public class ResourceUrlProvider implements ApplicationListener handlerMap) { + public void setHandlerMap(Map handlerMap) { if (handlerMap != null) { this.patternRegistry.clear(); - this.patternRegistry.addAll(handlerMap.keySet()); this.handlerMap.clear(); - this.handlerMap.putAll(handlerMap); + + handlerMap.forEach((pattern, handler) -> { + this.patternRegistry + .register(pattern) + .forEach(pathPattern -> this.handlerMap.put(pathPattern, handler)); + }); this.autodetect = false; } } @@ -143,7 +147,7 @@ public class ResourceUrlProvider implements ApplicationListener 0) { + if (queryIndex > 0) { suffixIndex = queryIndex; } int hashIndex = lookupPath.indexOf("#"); - if(hashIndex > 0) { + if (hashIndex > 0) { suffixIndex = Math.min(suffixIndex, hashIndex); } return suffixIndex; diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/PatternsRequestCondition.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/PatternsRequestCondition.java index 413a48e967..d156852388 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/PatternsRequestCondition.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/condition/PatternsRequestCondition.java @@ -133,8 +133,7 @@ public final class PatternsRequestCondition extends AbstractRequestCondition matches = getMatchingPatterns(lookupPath); if(!matches.isEmpty()) { - PathPatternRegistry registry = new PathPatternRegistry(); - registry.addAll(matches); + PathPatternRegistry registry = new PathPatternRegistry(matches); return new PatternsRequestCondition(registry, this.pathHelper); } return null; diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java index 5dd3a43f1a..e0e90d12b2 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/AbstractHandlerMethodMapping.java @@ -93,7 +93,7 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap private final MultiValueMap mappingLookup = new LinkedMultiValueMap<>(); private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); - + private final MappingRegistry mappingRegistry = new MappingRegistry(); @@ -129,10 +129,10 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap public void registerMapping(T mapping, Object handler, Method method) { this.readWriteLock.writeLock().lock(); try { - Set patterns = getMappingPathPatterns(mapping); - getPatternRegistry().addAll(patterns); - patterns.forEach(pathPattern -> { - this.mappingLookup.add(pathPattern, mapping); + getMappingPathPatterns(mapping).forEach(pattern -> { + getPatternRegistry().register(pattern).forEach( + pathPattern -> this.mappingLookup.add(pathPattern, mapping) + ); }); this.mappingRegistry.register(mapping, handler, method); } @@ -149,8 +149,11 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap public void unregisterMapping(T mapping) { this.readWriteLock.writeLock().lock(); try { - getMappingPathPatterns(mapping) - .forEach(pathPattern -> getPatternRegistry().remove(pathPattern)); + getMappingPathPatterns(mapping).forEach(pattern -> { + getPatternRegistry().unregister(pattern).forEach( + pathPattern -> this.mappingLookup.remove(pathPattern, mapping) + ); + }); this.mappingRegistry.unregister(mapping); } finally { @@ -420,7 +423,7 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap /** * Extract and return the URL paths contained in a mapping. */ - protected abstract Set getMappingPathPatterns(T mapping); + protected abstract Set getMappingPathPatterns(T mapping); /** * Check if a mapping matches the current request and return a (potentially diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMapping.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMapping.java index fdcb3b010e..629772fccb 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMapping.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMapping.java @@ -74,8 +74,10 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe * Get the URL path patterns associated with this {@link RequestMappingInfo}. */ @Override - protected Set getMappingPathPatterns(RequestMappingInfo info) { - return info.getPatternsCondition().getPatterns(); + protected Set getMappingPathPatterns(RequestMappingInfo info) { + return info.getPatternsCondition().getPatterns().stream() + .map(p -> p.getPatternString()) + .collect(Collectors.toSet()); } /** diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/AppCacheManifestTransformerTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/AppCacheManifestTransformerTests.java index 636d302f8a..a75140a5af 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/AppCacheManifestTransformerTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/AppCacheManifestTransformerTests.java @@ -34,7 +34,6 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse import org.springframework.util.FileCopyUtils; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange; -import org.springframework.web.util.patterns.PathPatternParser; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -58,8 +57,7 @@ public class AppCacheManifestTransformerTests { ClassPathResource allowedLocation = new ClassPathResource("test/", getClass()); ResourceWebHandler resourceHandler = new ResourceWebHandler(); ResourceUrlProvider resourceUrlProvider = new ResourceUrlProvider(); - PathPatternParser parser = new PathPatternParser(); - resourceUrlProvider.setHandlerMap(Collections.singletonMap(parser.parse("/static/**"), resourceHandler)); + resourceUrlProvider.setHandlerMap(Collections.singletonMap("/static/**", resourceHandler)); VersionResourceResolver versionResolver = new VersionResourceResolver(); versionResolver.setStrategyMap(Collections.singletonMap("/**", new ContentVersionStrategy())); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/CssLinkResourceTransformerTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/CssLinkResourceTransformerTests.java index 41882253bd..78cdb67e54 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/CssLinkResourceTransformerTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/CssLinkResourceTransformerTests.java @@ -59,8 +59,7 @@ public class CssLinkResourceTransformerTests { ResourceWebHandler resourceHandler = new ResourceWebHandler(); ResourceUrlProvider resourceUrlProvider = new ResourceUrlProvider(); - PathPatternParser parser = new PathPatternParser(); - resourceUrlProvider.setHandlerMap(Collections.singletonMap(parser.parse("/static/**"), resourceHandler)); + resourceUrlProvider.setHandlerMap(Collections.singletonMap("/static/**", resourceHandler)); VersionResourceResolver versionResolver = new VersionResourceResolver(); versionResolver.setStrategyMap(Collections.singletonMap("/**", new ContentVersionStrategy())); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceTransformerSupportTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceTransformerSupportTests.java index 64da5d2330..89300883e7 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceTransformerSupportTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceTransformerSupportTests.java @@ -30,7 +30,6 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange; -import org.springframework.web.util.patterns.PathPatternParser; import static org.junit.Assert.assertEquals; @@ -70,8 +69,7 @@ public class ResourceTransformerSupportTests { handler.setLocations(Collections.singletonList(new ClassPathResource("test/", getClass()))); handler.setResourceResolvers(resolvers); ResourceUrlProvider urlProvider = new ResourceUrlProvider(); - PathPatternParser parser = new PathPatternParser(); - urlProvider.setHandlerMap(Collections.singletonMap(parser.parse("/resources/**"), handler)); + urlProvider.setHandlerMap(Collections.singletonMap("/resources/**", handler)); return urlProvider; } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceUrlProviderTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceUrlProviderTests.java index 219f6c4585..d1063c0531 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceUrlProviderTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceUrlProviderTests.java @@ -36,9 +36,6 @@ import org.springframework.web.context.support.AnnotationConfigWebApplicationCon import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange; -import org.springframework.web.server.session.DefaultWebSessionManager; -import org.springframework.web.server.session.WebSessionManager; -import org.springframework.web.util.patterns.PathPattern; import org.springframework.web.util.patterns.PathPatternParser; import static org.junit.Assert.assertEquals; @@ -57,7 +54,7 @@ public class ResourceUrlProviderTests { private final ResourceWebHandler handler = new ResourceWebHandler(); - private final Map handlerMap = new HashMap<>(); + private final Map handlerMap = new HashMap<>(); private final ResourceUrlProvider urlProvider = new ResourceUrlProvider(); @@ -68,8 +65,7 @@ public class ResourceUrlProviderTests { this.locations.add(new ClassPathResource("testalternatepath/", getClass())); this.handler.setLocations(locations); this.handler.afterPropertiesSet(); - PathPattern staticResources = new PathPatternParser().parse("/resources/**"); - this.handlerMap.put(staticResources, this.handler); + this.handlerMap.put("/resources/**", this.handler); this.urlProvider.setHandlerMap(this.handlerMap); } @@ -125,8 +121,7 @@ public class ResourceUrlProviderTests { resolvers.add(new PathResourceResolver()); otherHandler.setResourceResolvers(resolvers); - PathPattern staticResources = new PathPatternParser().parse("/resources/*.css"); - this.handlerMap.put(staticResources, otherHandler); + this.handlerMap.put("/resources/*.css", otherHandler); this.urlProvider.setHandlerMap(this.handlerMap); String url = this.urlProvider.getForLookupPath("/resources/foo.css").blockMillis(5000); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/HandlerMethodMappingTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/HandlerMethodMappingTests.java index ae87d841ae..2db4cdc2f4 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/HandlerMethodMappingTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/HandlerMethodMappingTests.java @@ -18,7 +18,9 @@ package org.springframework.web.reactive.result.method; import java.lang.reflect.Method; import java.net.URISyntaxException; +import java.util.Collections; import java.util.Comparator; +import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -39,6 +41,7 @@ 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.patterns.PathPattern; +import org.springframework.web.util.patterns.PathPatternComparator; import org.springframework.web.util.patterns.PathPatternParser; import org.springframework.web.util.patterns.PatternComparatorConsideringPath; @@ -54,7 +57,7 @@ public class HandlerMethodMappingTests { private PathPatternParser patternParser = new PathPatternParser(); - private AbstractHandlerMethodMapping mapping; + private AbstractHandlerMethodMapping mapping; private MyHandler handler; @@ -74,14 +77,14 @@ public class HandlerMethodMappingTests { @Test(expected = IllegalStateException.class) public void registerDuplicates() { - this.mapping.registerMapping(this.patternParser.parse("/foo"), this.handler, this.method1); - this.mapping.registerMapping(this.patternParser.parse("/foo"), this.handler, this.method2); + this.mapping.registerMapping("/foo", this.handler, this.method1); + this.mapping.registerMapping("/foo", this.handler, this.method2); } @Test public void directMatch() throws Exception { - String key = "foo"; - this.mapping.registerMapping(this.patternParser.parse(key), this.handler, this.method1); + String key = "/foo"; + this.mapping.registerMapping(key, this.handler, this.method1); Mono result = this.mapping.getHandler(createExchange(HttpMethod.GET, key)); assertEquals(this.method1, ((HandlerMethod) result.block()).getMethod()); @@ -89,8 +92,8 @@ public class HandlerMethodMappingTests { @Test public void patternMatch() throws Exception { - this.mapping.registerMapping(this.patternParser.parse("/fo*"), this.handler, this.method1); - this.mapping.registerMapping(this.patternParser.parse("/f*"), this.handler, this.method2); + this.mapping.registerMapping("/fo*", this.handler, this.method1); + this.mapping.registerMapping("/f*", this.handler, this.method2); Mono result = this.mapping.getHandler(createExchange(HttpMethod.GET, "/foo")); assertEquals(this.method1, ((HandlerMethod) result.block()).getMethod()); @@ -98,8 +101,8 @@ public class HandlerMethodMappingTests { @Test public void ambiguousMatch() throws Exception { - this.mapping.registerMapping(this.patternParser.parse("/f?o"), this.handler, this.method1); - this.mapping.registerMapping(this.patternParser.parse("/fo?"), this.handler, this.method2); + this.mapping.registerMapping("/f?o", this.handler, this.method1); + this.mapping.registerMapping("/fo?", this.handler, this.method2); Mono result = this.mapping.getHandler(createExchange(HttpMethod.GET, "/foo")); StepVerifier.create(result).expectError(IllegalStateException.class).verify(); @@ -107,8 +110,8 @@ public class HandlerMethodMappingTests { @Test public void registerMapping() throws Exception { - PathPattern key1 = this.patternParser.parse("/foo"); - PathPattern key2 = this.patternParser.parse("/foo*"); + String key1 = "/foo"; + String key2 = "/foo*"; this.mapping.registerMapping(key1, this.handler, this.method1); this.mapping.registerMapping(key2, this.handler, this.method2); @@ -118,8 +121,8 @@ public class HandlerMethodMappingTests { @Test public void registerMappingWithSameMethodAndTwoHandlerInstances() throws Exception { - PathPattern key1 = this.patternParser.parse("/foo"); - PathPattern key2 = this.patternParser.parse("/bar"); + String key1 = "/foo"; + String key2 = "/bar"; MyHandler handler1 = new MyHandler(); MyHandler handler2 = new MyHandler(); this.mapping.registerMapping(key1, handler1, this.method1); @@ -131,13 +134,13 @@ public class HandlerMethodMappingTests { @Test public void unregisterMapping() throws Exception { - String key = "foo"; - this.mapping.registerMapping(this.patternParser.parse(key), this.handler, this.method1); + String key = "/foo"; + this.mapping.registerMapping(key, this.handler, this.method1); Mono result = this.mapping.getHandler(createExchange(HttpMethod.GET, key)); assertNotNull(result.block()); - this.mapping.unregisterMapping(this.patternParser.parse(key)); + this.mapping.unregisterMapping(key); result = this.mapping.getHandler(createExchange(HttpMethod.GET, key)); assertNull(result.block()); @@ -152,7 +155,7 @@ public class HandlerMethodMappingTests { } - private static class MyHandlerMethodMapping extends AbstractHandlerMethodMapping { + private static class MyHandlerMethodMapping extends AbstractHandlerMethodMapping { private PathPatternParser patternParser = new PathPatternParser(); @@ -162,28 +165,34 @@ public class HandlerMethodMappingTests { } @Override - protected PathPattern getMappingForMethod(Method method, Class handlerType) { + protected String getMappingForMethod(Method method, Class handlerType) { String methodName = method.getName(); - return methodName.startsWith("handler") ? this.patternParser.parse(methodName) : null; + return methodName.startsWith("handler") ? methodName : null; } @Override - protected SortedSet getMappingPathPatterns(PathPattern key) { - TreeSet patterns = new TreeSet<>(); - patterns.add(key); - return patterns; + protected Set getMappingPathPatterns(String key) { + return Collections.singleton(key); } @Override - protected PathPattern getMatchingMapping(PathPattern pattern, ServerWebExchange exchange) { + protected String getMatchingMapping(String pattern, ServerWebExchange exchange) { String lookupPath = exchange.getRequest().getURI().getPath(); - return (pattern.matches(lookupPath) ? pattern : null); + PathPattern pathPattern = this.patternParser.parse(pattern); + return (pathPattern.matches(lookupPath) ? pattern : null); } @Override - protected Comparator getMappingComparator(ServerWebExchange exchange) { + protected Comparator getMappingComparator(ServerWebExchange exchange) { String lookupPath = exchange.getRequest().getURI().getPath(); - return new PatternComparatorConsideringPath(lookupPath); + PatternComparatorConsideringPath comparator = new PatternComparatorConsideringPath(lookupPath); + return new Comparator() { + @Override + public int compare(String o1, String o2) { + + return comparator.compare(patternParser.parse(o1), patternParser.parse(o2)); + } + }; } } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java index 8fb3294015..0adf6a7a9b 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java @@ -24,9 +24,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.SortedSet; import java.util.function.Consumer; -import java.util.stream.Collectors; import org.hamcrest.Matchers; import org.junit.Before; @@ -98,11 +96,10 @@ public class RequestMappingInfoHandlerMappingTests { public void getMappingPathPatterns() throws Exception { String[] patterns = {"/foo/*", "/foo", "/bar/*", "/bar"}; RequestMappingInfo info = paths(patterns).build(); - Set actual = this.handlerMapping.getMappingPathPatterns(info); + Set actual = this.handlerMapping.getMappingPathPatterns(info); - assertThat(actual.stream().map(PathPattern::getPatternString).collect(Collectors.toList()), - Matchers.containsInAnyOrder(new String[]{"/foo/*", "/foo", "/bar/*", "/bar", - "/foo/*/", "/foo/", "/bar/*/", "/bar/"})); + assertThat(actual, Matchers.containsInAnyOrder("/foo/*", "/foo", "/bar/*", "/bar", + "/foo/*/", "/foo/", "/bar/*/", "/bar/")); } @Test @@ -192,7 +189,7 @@ public class RequestMappingInfoHandlerMappingTests { assertError(mono, UnsupportedMediaTypeStatusException.class, ex -> assertEquals("Request failure [status: 415, " + - "reason: \"Invalid mime type \"bogus\": does not contain '/'\"]", + "reason: \"Invalid mime type \"bogus\": does not contain '/'\"]", ex.getMessage())); } @@ -238,7 +235,8 @@ public class RequestMappingInfoHandlerMappingTests { exchange.getAttributes().get(name)); } - @Test @SuppressWarnings("unchecked") + @Test + @SuppressWarnings("unchecked") public void handleMatchUriTemplateVariables() throws Exception { String lookupPath = "/1/2"; this.request = MockServerHttpRequest.get(lookupPath).build(); @@ -370,7 +368,7 @@ public class RequestMappingInfoHandlerMappingTests { } @SuppressWarnings("unchecked") - private void assertError(Mono mono, final Class exceptionClass, final Consumer consumer) { + private void assertError(Mono mono, final Class exceptionClass, final Consumer consumer) { StepVerifier.create(mono) .consumeErrorWith(error -> { @@ -469,11 +467,11 @@ public class RequestMappingInfoHandlerMappingTests { public void foo() { } - @GetMapping(path = "/foo", params="p") + @GetMapping(path = "/foo", params = "p") public void fooParam() { } - @RequestMapping(path = "/ba*", method = { GET, HEAD }) + @RequestMapping(path = "/ba*", method = {GET, HEAD}) public void bar() { } @@ -481,31 +479,31 @@ public class RequestMappingInfoHandlerMappingTests { public void empty() { } - @PutMapping(path = "/person/{id}", consumes="application/xml") + @PutMapping(path = "/person/{id}", consumes = "application/xml") public void consumes(@RequestBody String text) { } - @RequestMapping(path = "/persons", produces="application/xml") + @RequestMapping(path = "/persons", produces = "application/xml") public String produces() { return ""; } - @RequestMapping(path = "/params", params="foo=bar") + @RequestMapping(path = "/params", params = "foo=bar") public String param() { return ""; } - @RequestMapping(path = "/params", params="bar=baz") + @RequestMapping(path = "/params", params = "bar=baz") public String param2() { return ""; } - @RequestMapping(path = "/content", produces="application/xml") + @RequestMapping(path = "/content", produces = "application/xml") public String xmlContent() { return ""; } - @RequestMapping(path = "/content", produces="!application/xml") + @RequestMapping(path = "/content", produces = "!application/xml") public String nonXmlContent() { return ""; }