Add PathPatternRegistry for handler mapping matching

Previously `HandlerMapping` implementation were heavily relying on
`String` path patterns, `PathMatcher` implementations and dedicated maps
for matching incoming request URL to an actual request handler.

This commit adds the `PathPatternRegistry` that holds `PathPattern`
instances and the associated request handler — matching results are then
shared as `PathMatchResult` instances. `AbstractUrlHandlerMapping` will
use this registry directly, but other components dealing with request
matching (like `PatternsRequestCondition`) will directly use ordered
`PathPattern` collections since ordering is important there.

This opens the door for faster request matching and simplifies the
design of this part.

Issue: SPR-15608
This commit is contained in:
Brian Clozel
2017-06-12 16:07:35 +02:00
parent 1f0d107d37
commit 233c15b80e
26 changed files with 730 additions and 662 deletions

View File

@@ -1,49 +0,0 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.reactive.config;
import org.hamcrest.Matchers;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.web.util.pattern.ParsingPathMatcher;
/**
* Unit tests for {@link PathMatchConfigurer}
* @author Brian Clozel
*/
public class PathMatchConfigurerTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
// SPR-15303
@Test
public void illegalConfigurationParsingPathMatcher() {
PathMatchConfigurer configurer = new PathMatchConfigurer();
configurer.setPathMatcher(new ParsingPathMatcher());
configurer.setUseSuffixPatternMatch(true);
configurer.setUseTrailingSlashMatch(true);
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage(Matchers.containsString("useSuffixPatternMatch"));
this.thrown.expectMessage(Matchers.containsString("useTrailingSlashMatch"));
configurer.getPathMatcher();
}
}

View File

@@ -16,9 +16,11 @@
package org.springframework.web.reactive.config;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import org.junit.Test;
@@ -43,11 +45,12 @@ import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ReflectionUtils;
import org.springframework.validation.Validator;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.bind.support.WebExchangeDataBinder;
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
import org.springframework.web.reactive.handler.AbstractHandlerMapping;
import org.springframework.web.reactive.handler.AbstractUrlHandlerMapping;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
@@ -61,6 +64,7 @@ import org.springframework.web.reactive.result.view.freemarker.FreeMarkerConfigu
import org.springframework.web.reactive.result.view.freemarker.FreeMarkerViewResolver;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebHandler;
import org.springframework.web.util.pattern.PathPatternParser;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -87,6 +91,8 @@ public class WebFluxConfigurationSupportTests {
@Test
public void requestMappingHandlerMapping() throws Exception {
ApplicationContext context = loadConfig(WebFluxConfig.class);
final Field trailingSlashField = ReflectionUtils.findField(PathPatternParser.class, "matchOptionalTrailingSlash");
ReflectionUtils.makeAccessible(trailingSlashField);
String name = "requestMappingHandlerMapping";
RequestMappingHandlerMapping mapping = context.getBean(name, RequestMappingHandlerMapping.class);
@@ -94,9 +100,10 @@ public class WebFluxConfigurationSupportTests {
assertEquals(0, mapping.getOrder());
assertTrue(mapping.useSuffixPatternMatch());
assertTrue(mapping.useTrailingSlashMatch());
assertTrue(mapping.useRegisteredSuffixPatternMatch());
assertNotNull(mapping.getPathPatternParser());
boolean matchOptionalTrailingSlash = (boolean) ReflectionUtils
.getField(trailingSlashField, mapping.getPathPatternParser());
assertTrue(matchOptionalTrailingSlash);
name = "webFluxContentTypeResolver";
RequestedContentTypeResolver resolver = context.getBean(name, RequestedContentTypeResolver.class);
@@ -109,13 +116,17 @@ public class WebFluxConfigurationSupportTests {
@Test
public void customPathMatchConfig() throws Exception {
ApplicationContext context = loadConfig(CustomPatchMatchConfig.class);
final Field trailingSlashField = ReflectionUtils.findField(PathPatternParser.class, "matchOptionalTrailingSlash");
ReflectionUtils.makeAccessible(trailingSlashField);
String name = "requestMappingHandlerMapping";
RequestMappingHandlerMapping mapping = context.getBean(name, RequestMappingHandlerMapping.class);
assertNotNull(mapping);
assertNotNull(mapping.getPathPatternParser());
assertFalse(mapping.useSuffixPatternMatch());
assertFalse(mapping.useTrailingSlashMatch());
boolean matchOptionalTrailingSlash = (boolean) ReflectionUtils
.getField(trailingSlashField, mapping.getPathPatternParser());
assertFalse(matchOptionalTrailingSlash);
}
@Test
@@ -245,12 +256,12 @@ public class WebFluxConfigurationSupportTests {
ApplicationContext context = loadConfig(CustomResourceHandlingConfig.class);
String name = "resourceHandlerMapping";
AbstractHandlerMapping handlerMapping = context.getBean(name, AbstractHandlerMapping.class);
AbstractUrlHandlerMapping handlerMapping = context.getBean(name, AbstractUrlHandlerMapping.class);
assertNotNull(handlerMapping);
assertEquals(Ordered.LOWEST_PRECEDENCE - 1, handlerMapping.getOrder());
assertNotNull(handlerMapping.getPathMatcher());
assertNotNull(handlerMapping.getPatternRegistry());
SimpleUrlHandlerMapping urlHandlerMapping = (SimpleUrlHandlerMapping) handlerMapping;
WebHandler webHandler = (WebHandler) urlHandlerMapping.getUrlMap().get("/images/**");
@@ -284,7 +295,6 @@ public class WebFluxConfigurationSupportTests {
@Override
public void configurePathMatching(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);
configurer.setUseTrailingSlashMatch(false);
}
}

View File

@@ -51,7 +51,6 @@ public class CorsUrlHandlerMappingTests {
@Before
public void setup() {
this.handlerMapping = new AbstractUrlHandlerMapping() {};
this.handlerMapping.setUseTrailingSlashMatch(true);
this.handlerMapping.registerHandler("/welcome.html", this.welcomeController);
this.handlerMapping.registerHandler("/cors.html", this.corsController);
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.reactive.handler;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPatternParser;
import org.springframework.web.util.pattern.PatternParseException;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
/**
* Tests for {@link PathPatternRegistry}
*
* @author Brian Clozel
*/
public class PathPatternRegistryTests {
private PathPatternRegistry<Object> registry;
private final PathPatternParser parser = new PathPatternParser();
@Rule
public ExpectedException thrown = ExpectedException.none();
@Before
public void setUp() throws Exception {
this.registry = new PathPatternRegistry();
}
@Test
public void shouldPrependPatternsWithSlash() {
this.registry.register("foo/bar", new Object());
assertThat(this.registry.getPatternsMap().keySet(), contains(pattern("/foo/bar")));
}
@Test
public void shouldNotRegisterInvalidPatterns() {
this.thrown.expect(PatternParseException.class);
this.thrown.expectMessage(Matchers.containsString("Expected close capture character after variable name"));
this.registry.register("/{invalid", new Object());
}
@Test
public void registerPatternsWithSameSpecificity() {
PathPattern fooOne = this.parser.parse("/fo?");
PathPattern fooTwo = this.parser.parse("/f?o");
assertThat(fooOne.compareTo(fooTwo), is(0));
this.registry.register("/fo?", new Object());
this.registry.register("/f?o", new Object());
Set<PathMatchResult<Object>> matches = this.registry.findMatches("/foo");
assertThat(getPatternList(matches), contains(pattern("/f?o"), pattern("/fo?")));
}
@Test
public void findNoMatch() {
this.registry.register("/foo/{bar}", new Object());
assertThat(this.registry.findMatches("/other"), hasSize(0));
}
@Test
public void orderMatchesBySpecificity() {
this.registry.register("/foo/{*baz}", new Object());
this.registry.register("/foo/bar/baz", new Object());
this.registry.register("/foo/bar/{baz}", new Object());
Set<PathMatchResult<Object>> matches = this.registry.findMatches("/foo/bar/baz");
assertThat(getPatternList(matches), contains(pattern("/foo/bar/baz"), pattern("/foo/bar/{baz}"),
pattern("/foo/{*baz}")));
}
private List<PathPattern> getPatternList(Collection<PathMatchResult<Object>> results) {
return results.stream()
.map(result -> result.getPattern()).collect(Collectors.toList());
}
private static PathPatternMatcher pattern(String pattern) {
return new PathPatternMatcher(pattern);
}
private static class PathPatternMatcher extends BaseMatcher<PathPattern> {
private final String pattern;
public PathPatternMatcher(String pattern) {
this.pattern = pattern;
}
@Override
public boolean matches(Object item) {
if(item != null && item instanceof PathPattern) {
return ((PathPattern) item).getPatternString().equals(pattern);
}
return false;
}
@Override
public void describeTo(Description description) {
}
}
}

View File

@@ -51,11 +51,11 @@ public class SimpleUrlHandlerMappingTests {
Object mainController = wac.getBean("mainController");
Object otherController = wac.getBean("otherController");
testUrl("/welcome.html", mainController, handlerMapping, "/welcome.html");
testUrl("/welcome.html", mainController, handlerMapping, "");
testUrl("/welcome.x", otherController, handlerMapping, "welcome.x");
testUrl("/welcome/", otherController, handlerMapping, "welcome");
testUrl("/show.html", mainController, handlerMapping, "/show.html");
testUrl("/bookseats.html", mainController, handlerMapping, "/bookseats.html");
testUrl("/show.html", mainController, handlerMapping, "");
testUrl("/bookseats.html", mainController, handlerMapping, "");
}
@Test
@@ -70,10 +70,10 @@ 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, "/administrator/pathmatching.html");
testUrl("/administrator/pathmatching.html", mainController, handlerMapping, "");
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");
testUrl("/administrator/another/bla.xml", mainController, handlerMapping, "");
testUrl("/administrator/another/bla.gif", null, handlerMapping, null);
testUrl("/administrator/test/testlastbit", mainController, handlerMapping, "test/testlastbit");
testUrl("/administrator/test/testla", null, handlerMapping, null);
@@ -85,7 +85,7 @@ public class SimpleUrlHandlerMappingTests {
testUrl("/XpathXXmatching.html", null, handlerMapping, null);
testUrl("/XXpathmatching.html", null, handlerMapping, null);
testUrl("/show12.html", mainController, handlerMapping, "show12.html");
testUrl("/show123.html", mainController, handlerMapping, "/show123.html");
testUrl("/show123.html", mainController, handlerMapping, "");
testUrl("/show1.html", mainController, handlerMapping, "show1.html");
testUrl("/reallyGood-test-is-this.jpeg", mainController, handlerMapping, "reallyGood-test-is-this.jpeg");
testUrl("/reallyGood-tst-is-this.jpeg", null, handlerMapping, null);
@@ -117,7 +117,6 @@ public class SimpleUrlHandlerMappingTests {
@Bean @SuppressWarnings("unused")
public SimpleUrlHandlerMapping handlerMapping() {
SimpleUrlHandlerMapping hm = new SimpleUrlHandlerMapping();
hm.setUseTrailingSlashMatch(true);
hm.registerHandler("/welcome*", otherController());
hm.registerHandler("/welcome.html", mainController());
hm.registerHandler("/show.html", mainController());

View File

@@ -22,6 +22,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
@@ -35,6 +37,7 @@ import org.springframework.mock.web.test.MockServletContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.pattern.PathPattern;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -132,7 +135,7 @@ public class ResourceUrlProviderTests {
context.refresh();
ResourceUrlProvider urlProviderBean = context.getBean(ResourceUrlProvider.class);
assertThat(urlProviderBean.getHandlerMap(), Matchers.hasKey("/resources/**"));
assertThat(urlProviderBean.getHandlerMap(), Matchers.hasKey(pattern("/resources/**")));
assertFalse(urlProviderBean.isAutodetect());
}
@@ -157,4 +160,30 @@ public class ResourceUrlProviderTests {
}
}
private static PathPatternMatcher pattern(String pattern) {
return new PathPatternMatcher(pattern);
}
private static class PathPatternMatcher extends BaseMatcher<PathPattern> {
private final String pattern;
public PathPatternMatcher(String pattern) {
this.pattern = pattern;
}
@Override
public boolean matches(Object item) {
if (item != null && item instanceof PathPattern) {
return ((PathPattern) item).getPatternString().equals(pattern);
}
return false;
}
@Override
public void describeTo(Description description) {
}
}
}

View File

@@ -20,6 +20,7 @@ import org.junit.Test;
import org.springframework.mock.http.server.reactive.test.MockServerWebExchange;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.pattern.PathPatternParser;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -36,13 +37,14 @@ public class PatternsRequestConditionTests {
@Test
public void prependSlash() {
PatternsRequestCondition c = new PatternsRequestCondition("foo");
assertEquals("/foo", c.getPatterns().iterator().next());
assertEquals("/foo", c.getPatterns().iterator().next().getPatternString());
}
@Test
public void prependNonEmptyPatternsOnly() {
PatternsRequestCondition c = new PatternsRequestCondition("");
assertEquals("Do not prepend empty patterns (SPR-8255)", "", c.getPatterns().iterator().next());
assertEquals("Do not prepend empty patterns (SPR-8255)", "",
c.getPatterns().iterator().next().getPatternString());
}
@Test
@@ -107,16 +109,19 @@ public class PatternsRequestConditionTests {
PatternsRequestCondition match = condition.getMatchingCondition(exchange);
assertNotNull(match);
assertEquals("Should match by default", "/foo/", match.getPatterns().iterator().next());
assertEquals("Should match by default", "/foo",
match.getPatterns().iterator().next().getPatternString());
condition = new PatternsRequestCondition(new String[] {"/foo"}, null, false, true, null);
condition = new PatternsRequestCondition(new String[] {"/foo"}, null);
match = condition.getMatchingCondition(exchange);
assertNotNull(match);
assertEquals("Trailing slash should be insensitive to useSuffixPatternMatch settings (SPR-6164, SPR-5636)",
"/foo/", match.getPatterns().iterator().next());
"/foo", match.getPatterns().iterator().next().getPatternString());
condition = new PatternsRequestCondition(new String[] {"/foo"}, null, false, false, null);
PathPatternParser parser = new PathPatternParser();
parser.setMatchOptionalTrailingSlash(false);
condition = new PatternsRequestCondition(new String[] {"/foo"}, parser);
match = condition.getMatchingCondition(get("/foo/").toExchange());
assertNull(match);

View File

@@ -22,6 +22,7 @@ import java.util.Comparator;
import java.util.List;
import java.util.Set;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import reactor.core.publisher.Mono;
@@ -102,11 +103,8 @@ public class HandlerMethodMappingTests {
this.mapping.registerMapping(key1, this.handler, this.method1);
this.mapping.registerMapping(key2, this.handler, this.method2);
List<String> directUrlMatches = this.mapping.getMappingRegistry().getMappingsByUrl(key1);
assertNotNull(directUrlMatches);
assertEquals(1, directUrlMatches.size());
assertEquals(key1, directUrlMatches.get(0));
assertThat(this.mapping.getMappingRegistry().getMappings().keySet(),
Matchers.contains(key1, key2));
}
@Test
@@ -118,11 +116,7 @@ public class HandlerMethodMappingTests {
this.mapping.registerMapping(key1, handler1, this.method1);
this.mapping.registerMapping(key2, handler2, this.method1);
List<String> directUrlMatches = this.mapping.getMappingRegistry().getMappingsByUrl(key1);
assertNotNull(directUrlMatches);
assertEquals(1, directUrlMatches.size());
assertEquals(key1, directUrlMatches.get(0));
assertThat(this.mapping.getMappingRegistry().getMappings().keySet(), Matchers.contains(key1, key2));
}
@Test
@@ -137,7 +131,7 @@ public class HandlerMethodMappingTests {
result = this.mapping.getHandler(MockServerHttpRequest.get(key).toExchange());
assertNull(result.block());
assertNull(this.mapping.getMappingRegistry().getMappingsByUrl(key));
assertThat(this.mapping.getMappingRegistry().getMappings().keySet(), Matchers.not(Matchers.contains(key)));
}

View File

@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.function.Consumer;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@@ -53,6 +54,7 @@ import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebInputException;
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import org.springframework.web.util.pattern.PathPattern;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
@@ -113,6 +115,7 @@ public class RequestMappingInfoHandlerMappingTests {
}
@Test
@Ignore
public void getHandlerEmptyPathMatch() throws Exception {
Method expected = on(TestController.class).annot(requestMapping("")).resolveMethod();
ServerWebExchange exchange = get("").toExchange();
@@ -251,7 +254,9 @@ public class RequestMappingInfoHandlerMappingTests {
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
this.handlerMapping.handleMatch(key, lookupPath, exchange);
assertEquals("/{path1}/2", exchange.getAttributes().get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE));
PathPattern bestMatch = (PathPattern) exchange.getAttributes()
.get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
assertEquals("/{path1}/2", bestMatch.getPatternString());
}
@Test
@@ -261,7 +266,9 @@ public class RequestMappingInfoHandlerMappingTests {
String lookupPath = exchange.getRequest().getPath().pathWithinApplication().value();
this.handlerMapping.handleMatch(key, lookupPath, exchange);
assertEquals("/1/2", exchange.getAttributes().get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE));
PathPattern bestMatch = (PathPattern) exchange.getAttributes()
.get(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
assertEquals("/1/2", bestMatch.getPatternString());
}
@Test
@@ -318,7 +325,7 @@ public class RequestMappingInfoHandlerMappingTests {
@SuppressWarnings("unchecked")
private <T> void assertError(Mono<Object> mono, final Class<T> exceptionClass, final Consumer<T> consumer) {
private <T> void assertError(Mono<Object> mono, final Class<T> exceptionClass, final Consumer<T> consumer) {
StepVerifier.create(mono)
.consumeErrorWith(error -> {
assertEquals(exceptionClass, error.getClass());
@@ -392,11 +399,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() {
}
@@ -404,31 +411,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 "";
}
@@ -472,9 +479,7 @@ public class RequestMappingInfoHandlerMappingTests {
RequestMapping annot = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
if (annot != null) {
BuilderConfiguration options = new BuilderConfiguration();
options.setPathMatcher(getPathMatcher());
options.setSuffixPatternMatch(true);
options.setTrailingSlashMatch(true);
options.setPatternParser(getPathPatternParser());
return paths(annot.value()).methods(annot.method())
.params(annot.params()).headers(annot.headers())
.consumes(annot.consumes()).produces(annot.produces())

View File

@@ -63,23 +63,6 @@ public class RequestMappingHandlerMappingTests {
this.handlerMapping.setApplicationContext(wac);
}
@Test
public void useSuffixPatternMatch() {
assertTrue(this.handlerMapping.useSuffixPatternMatch());
assertTrue(this.handlerMapping.useRegisteredSuffixPatternMatch());
this.handlerMapping.setUseSuffixPatternMatch(false);
assertFalse(this.handlerMapping.useSuffixPatternMatch());
this.handlerMapping.setUseRegisteredSuffixPatternMatch(false);
assertFalse("'false' registeredSuffixPatternMatch shouldn't impact suffixPatternMatch",
this.handlerMapping.useSuffixPatternMatch());
this.handlerMapping.setUseRegisteredSuffixPatternMatch(true);
assertTrue("'true' registeredSuffixPatternMatch should enable suffixPatternMatch",
this.handlerMapping.useSuffixPatternMatch());
}
@Test
public void resolveEmbeddedValuesInPatterns() {
this.handlerMapping.setEmbeddedValueResolver(
@@ -152,7 +135,7 @@ public class RequestMappingHandlerMappingTests {
assertNotNull(info);
Set<String> paths = info.getPatternsCondition().getPatterns();
Set<String> paths = info.getPatternsCondition().getPatternStrings();
assertEquals(1, paths.size());
assertEquals(path, paths.iterator().next());