Enable smart suffix pattern match for request mapping
Following the introduction of ContentNegotiationManager that allows,
among other things, to configure the file extensions to use for content
negotiation, this change adds "smart" suffix pattern match that matches
against the configured file extensions only rather than against any
extension.
Given the request mapping "/jobs/{jobName}" and one configured file
extension ("json"), a request for "/jobs/my.job" will select the
pattern "/jobs/{jobName}" while a request for "/jobs/my.job.json" will
select the pattern "/jobs/{jobName}.json". Previously, both requests
would have resulted in the pattern "/jobs/{jobName}.*".
Issue: SPR-7632, SPR-8474
This commit is contained in:
@@ -97,11 +97,23 @@ public class ContentNegotiationManager implements ContentNegotiationStrategy, Me
|
||||
* the list of all file extensions found.
|
||||
*/
|
||||
public List<String> resolveFileExtensions(MediaType mediaType) {
|
||||
Set<String> extensions = new LinkedHashSet<String>();
|
||||
Set<String> result = new LinkedHashSet<String>();
|
||||
for (MediaTypeFileExtensionResolver resolver : this.fileExtensionResolvers) {
|
||||
extensions.addAll(resolver.resolveFileExtensions(mediaType));
|
||||
result.addAll(resolver.resolveFileExtensions(mediaType));
|
||||
}
|
||||
return new ArrayList<String>(extensions);
|
||||
return new ArrayList<String>(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate to all configured MediaTypeFileExtensionResolver instances and aggregate
|
||||
* the list of all known file extensions.
|
||||
*/
|
||||
public List<String> getAllFileExtensions() {
|
||||
Set<String> result = new LinkedHashSet<String>();
|
||||
for (MediaTypeFileExtensionResolver resolver : this.fileExtensionResolvers) {
|
||||
result.addAll(resolver.getAllFileExtensions());
|
||||
}
|
||||
return new ArrayList<String>(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.web.accept;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -40,6 +41,8 @@ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExten
|
||||
|
||||
private final MultiValueMap<MediaType, String> fileExtensions = new LinkedMultiValueMap<MediaType, String>();
|
||||
|
||||
private final List<String> allFileExtensions = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* Create an instance with the given mappings between extensions and media types.
|
||||
* @throws IllegalArgumentException if a media type string cannot be parsed
|
||||
@@ -55,7 +58,7 @@ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExten
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the extensions applicable to the given MediaType.
|
||||
* Find the file extensions mapped to the given MediaType.
|
||||
* @return 0 or more extensions, never {@code null}
|
||||
*/
|
||||
public List<String> resolveFileExtensions(MediaType mediaType) {
|
||||
@@ -63,11 +66,15 @@ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExten
|
||||
return (fileExtensions != null) ? fileExtensions : Collections.<String>emptyList();
|
||||
}
|
||||
|
||||
public List<String> getAllFileExtensions() {
|
||||
return Collections.unmodifiableList(this.allFileExtensions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the MediaType mapped to the given extension.
|
||||
* @return a MediaType for the key or {@code null}
|
||||
*/
|
||||
public MediaType lookupMediaType(String extension) {
|
||||
protected MediaType lookupMediaType(String extension) {
|
||||
return this.mediaTypes.get(extension);
|
||||
}
|
||||
|
||||
@@ -78,6 +85,7 @@ public class MappingMediaTypeFileExtensionResolver implements MediaTypeFileExten
|
||||
MediaType previous = this.mediaTypes.putIfAbsent(extension, mediaType);
|
||||
if (previous == null) {
|
||||
this.fileExtensions.add(mediaType, extension);
|
||||
this.allFileExtensions.add(extension);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,4 +37,10 @@ public interface MediaTypeFileExtensionResolver {
|
||||
*/
|
||||
List<String> resolveFileExtensions(MediaType mediaType);
|
||||
|
||||
/**
|
||||
* Return all known file extensions.
|
||||
* @return a list of extensions or an empty list, never {@code null}
|
||||
*/
|
||||
List<String> getAllFileExtensions();
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user