Refactor HandlerMapping path match configuration

Since the introduction of `PathPatternRegistry`, the various path match
configuration flags are no longer needed in several places and that
configuration can live in the registry itself.

Issue: SPR-14544
This commit is contained in:
Brian Clozel
2017-02-09 15:56:15 +01:00
parent da4af6157e
commit 09d18f2ef5
11 changed files with 163 additions and 294 deletions

View File

@@ -111,11 +111,14 @@ public class PathPatternRegistry {
* <p>The default value is an empty {@code Set}
*/
public void setFileExtensions(Set<String> fileExtensions) {
this.fileExtensions = fileExtensions;
Set<String> fixedFileExtensions = (fileExtensions != null) ? fileExtensions.stream()
.map(ext -> (ext.charAt(0) != '.') ? "." + ext : ext)
.collect(Collectors.toSet()) : Collections.emptySet();
this.fileExtensions = fixedFileExtensions;
}
/**
* Return a (read-only) set of all patterns, sorted according to their specificity.
* Return a (read-only) set of all patterns for matching (including generated pattern variants).
*/
public Set<PathPattern> getPatterns() {
return Collections.unmodifiableSet(this.patterns);
@@ -194,28 +197,38 @@ public class PathPatternRegistry {
* @return the list of {@link PathPattern} that were registered as a result
*/
public List<PathPattern> register(String rawPattern) {
String fixedPattern = prependLeadingSlash(rawPattern);
List<PathPattern> newPatterns = new ArrayList<>();
PathPattern pattern = this.pathPatternParser.parse(rawPattern);
PathPattern pattern = this.pathPatternParser.parse(fixedPattern);
newPatterns.add(pattern);
if (StringUtils.hasLength(rawPattern) && !pattern.isCatchAll()) {
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(rawPattern + "." + extension));
newPatterns.add(this.pathPatternParser.parse(fixedPattern + extension));
}
}
else {
newPatterns.add(this.pathPatternParser.parse(rawPattern + ".*"));
newPatterns.add(this.pathPatternParser.parse(fixedPattern + ".*"));
}
}
if (this.useTrailingSlashMatch && !rawPattern.endsWith("/")) {
newPatterns.add(this.pathPatternParser.parse(rawPattern + "/"));
if (this.useTrailingSlashMatch && !fixedPattern.endsWith("/")) {
newPatterns.add(this.pathPatternParser.parse(fixedPattern + "/"));
}
}
this.patterns.addAll(newPatterns);
return newPatterns;
}
private String prependLeadingSlash(String pattern) {
if (StringUtils.hasLength(pattern) && !pattern.startsWith("/")) {
return "/" + pattern;
}
else {
return pattern;
}
}
/**
* Combine the patterns contained in the current registry
* with the ones in the other, into a new {@code PathPatternRegistry} instance.

View File

@@ -28,12 +28,14 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
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 {
@@ -48,6 +50,21 @@ public class PathPatternRegistryTests {
this.registry = new PathPatternRegistry();
}
@Test
public void shouldFixFileExtensions() {
Set<String> fileExtensions = new HashSet<>();
fileExtensions.add("json");
fileExtensions.add("xml");
this.registry.setFileExtensions(fileExtensions);
assertThat(this.registry.getFileExtensions(), contains(".json", ".xml"));
}
@Test
public void shouldPrependPatternsWithSlash() {
this.registry.register("foo/bar");
assertThat(getPatternList(this.registry.getPatterns()), Matchers.containsInAnyOrder("/foo/bar"));
}
@Test
public void shouldNotRegisterInvalidPatterns() {
this.thrown.expect(PatternParseException.class);
@@ -58,58 +75,59 @@ public class PathPatternRegistryTests {
@Test
public void shouldNotRegisterPatternVariants() {
List<PathPattern> patterns = this.registry.register("/foo/{bar}");
assertPathPatternListContains(patterns, "/foo/{bar}");
assertThat(getPatternList(patterns), Matchers.containsInAnyOrder("/foo/{bar}"));
}
@Test
public void shouldRegisterTrailingSlashVariants() {
this.registry.setUseTrailingSlashMatch(true);
List<PathPattern> patterns = this.registry.register("/foo/{bar}");
assertPathPatternListContains(patterns, "/foo/{bar}", "/foo/{bar}/");
assertThat(getPatternList(patterns), Matchers.containsInAnyOrder("/foo/{bar}", "/foo/{bar}/"));
}
@Test
public void shouldRegisterSuffixVariants() {
this.registry.setUseSuffixPatternMatch(true);
List<PathPattern> patterns = this.registry.register("/foo/{bar}");
assertPathPatternListContains(patterns, "/foo/{bar}", "/foo/{bar}.*");
assertThat(getPatternList(patterns), Matchers.containsInAnyOrder("/foo/{bar}", "/foo/{bar}.*"));
}
@Test
public void shouldRegisterExtensionsVariants() {
Set<String> fileExtensions = new HashSet<>();
fileExtensions.add("json");
fileExtensions.add("xml");
fileExtensions.add(".json");
fileExtensions.add(".xml");
this.registry.setUseSuffixPatternMatch(true);
this.registry.setFileExtensions(fileExtensions);
List<PathPattern> patterns = this.registry.register("/foo/{bar}");
assertPathPatternListContains(patterns, "/foo/{bar}", "/foo/{bar}.xml", "/foo/{bar}.json");
assertThat(getPatternList(patterns),
Matchers.containsInAnyOrder("/foo/{bar}", "/foo/{bar}.xml", "/foo/{bar}.json"));
}
@Test
public void shouldRegisterAllVariants() {
Set<String> fileExtensions = new HashSet<>();
fileExtensions.add("json");
fileExtensions.add("xml");
fileExtensions.add(".json");
fileExtensions.add(".xml");
this.registry.setUseSuffixPatternMatch(true);
this.registry.setUseTrailingSlashMatch(true);
this.registry.setFileExtensions(fileExtensions);
List<PathPattern> patterns = this.registry.register("/foo/{bar}");
assertPathPatternListContains(patterns, "/foo/{bar}",
"/foo/{bar}.xml", "/foo/{bar}.json", "/foo/{bar}/");
assertThat(getPatternList(patterns), Matchers.containsInAnyOrder("/foo/{bar}",
"/foo/{bar}.xml", "/foo/{bar}.json", "/foo/{bar}/"));
}
@Test
public void combineEmptyRegistries() {
PathPatternRegistry result = this.registry.combine(new PathPatternRegistry());
assertPathPatternListContains(result.getPatterns(), "");
assertThat(getPatternList(result.getPatterns()), Matchers.containsInAnyOrder(""));
}
@Test
public void combineWithEmptyRegistry() {
this.registry.register("/foo");
PathPatternRegistry result = this.registry.combine(new PathPatternRegistry());
assertPathPatternListContains(result.getPatterns(), "/foo");
assertThat(getPatternList(result.getPatterns()), Matchers.containsInAnyOrder("/foo"));
}
@Test
@@ -119,7 +137,7 @@ public class PathPatternRegistryTests {
other.register("/bar");
other.register("/baz");
PathPatternRegistry result = this.registry.combine(other);
assertPathPatternListContains(result.getPatterns(), "/foo/bar", "/foo/baz");
assertThat(getPatternList(result.getPatterns()), Matchers.containsInAnyOrder("/foo/bar", "/foo/baz"));
}
@Test
@@ -131,7 +149,7 @@ public class PathPatternRegistryTests {
this.registry.add(fooOne);
this.registry.add(fooTwo);
Set<PathPattern> matches = this.registry.findMatches("/foo");
assertPathPatternListContains(matches, "/f?o", "/fo?");
assertThat(getPatternList(matches), Matchers.contains("/f?o", "/fo?"));
}
@Test
@@ -146,15 +164,14 @@ public class PathPatternRegistryTests {
this.registry.register("/foo/bar/baz");
this.registry.register("/foo/bar/{baz}");
Set<PathPattern> matches = this.registry.findMatches("/foo/bar/baz");
assertPathPatternListContains(matches, "/foo/bar/baz", "/foo/bar/{baz}",
"/foo/{*baz}");
assertThat(getPatternList(matches), Matchers.contains("/foo/bar/baz", "/foo/bar/{baz}",
"/foo/{*baz}"));
}
private void assertPathPatternListContains(Collection<PathPattern> parsedPatterns, String... pathPatterns) {
List<String> patternList = parsedPatterns.
stream().map(pattern -> pattern.getPatternString()).collect(Collectors.toList());
assertThat(patternList, Matchers.contains(pathPatterns));
private List<String> getPatternList(Collection<PathPattern> parsedPatterns) {
return parsedPatterns.stream().map(pattern -> pattern.getPatternString()).collect(Collectors.toList());
}
}