MvcUriComponentsBuilder is aware of path prefixes

Issue: SPR-16336
This commit is contained in:
Rossen Stoyanchev
2018-06-14 22:05:53 -04:00
parent e6fef9555d
commit 58cce615f5
3 changed files with 108 additions and 31 deletions

View File

@@ -174,8 +174,15 @@ public class MvcUriComponentsBuilder {
Class<?> controllerType) {
builder = getBaseUrlToUse(builder);
// Externally configured prefix via PathConfigurer..
String prefix = getPathPrefix(controllerType);
builder.path(prefix);
String mapping = getClassMapping(controllerType);
return builder.path(mapping);
builder.path(mapping);
return builder;
}
/**
@@ -526,15 +533,21 @@ public class MvcUriComponentsBuilder {
}
private static UriComponentsBuilder fromMethodInternal(@Nullable UriComponentsBuilder baseUrl,
private static UriComponentsBuilder fromMethodInternal(@Nullable UriComponentsBuilder builder,
Class<?> controllerType, Method method, Object... args) {
baseUrl = getBaseUrlToUse(baseUrl);
builder = getBaseUrlToUse(builder);
// Externally configured prefix via PathConfigurer..
String prefix = getPathPrefix(controllerType);
builder.path(prefix);
String typePath = getClassMapping(controllerType);
String methodPath = getMethodMapping(method);
String path = pathMatcher.combine(typePath, methodPath);
baseUrl.path(path);
UriComponents uriComponents = applyContributors(baseUrl, method, args);
builder.path(path);
UriComponents uriComponents = applyContributors(builder, method, args);
return UriComponentsBuilder.newInstance().uriComponents(uriComponents);
}
@@ -544,6 +557,22 @@ public class MvcUriComponentsBuilder {
baseUrl.cloneBuilder();
}
private static String getPathPrefix(Class<?> controllerType) {
WebApplicationContext wac = getWebApplicationContext();
if (wac != null) {
Map<String, RequestMappingHandlerMapping> map = wac.getBeansOfType(RequestMappingHandlerMapping.class);
for (RequestMappingHandlerMapping mapping : map.values()) {
if (mapping.isHandler(controllerType)) {
String prefix = mapping.getPathPrefix(controllerType);
if (prefix != null) {
return prefix;
}
}
}
}
return "";
}
private static String getClassMapping(Class<?> controllerType) {
Assert.notNull(controllerType, "'controllerType' must not be null");
RequestMapping mapping = AnnotatedElementUtils.findMergedAnnotation(controllerType, RequestMapping.class);

View File

@@ -32,7 +32,6 @@ import org.springframework.lang.Nullable;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.StringValueResolver;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.annotation.CrossOrigin;
@@ -67,7 +66,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
private boolean useTrailingSlashMatch = true;
private final Map<String, Predicate<Class<?>>> pathPrefixes = new LinkedHashMap<>();
private Map<String, Predicate<Class<?>>> pathPrefixes = new LinkedHashMap<>();
private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();
@@ -120,10 +119,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
* @since 5.1
*/
public void setPathPrefixes(Map<String, Predicate<Class<?>>> prefixes) {
this.pathPrefixes.clear();
prefixes.entrySet().stream()
.filter(entry -> StringUtils.hasText(entry.getKey()))
.forEach(entry -> this.pathPrefixes.put(entry.getKey(), entry.getValue()));
this.pathPrefixes = Collections.unmodifiableMap(new LinkedHashMap<>(prefixes));
}
/**
@@ -180,7 +176,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
* @since 5.1
*/
public Map<String, Predicate<Class<?>>> getPathPrefixes() {
return Collections.unmodifiableMap(this.pathPrefixes);
return this.pathPrefixes;
}
/**
@@ -227,20 +223,28 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
if (typeInfo != null) {
info = typeInfo.combine(info);
}
for (Map.Entry<String, Predicate<Class<?>>> entry : this.pathPrefixes.entrySet()) {
if (entry.getValue().test(handlerType)) {
String prefix = entry.getKey();
if (this.embeddedValueResolver != null) {
prefix = this.embeddedValueResolver.resolveStringValue(prefix);
}
info = RequestMappingInfo.paths(prefix).build().combine(info);
break;
}
String prefix = getPathPrefix(handlerType);
if (prefix != null) {
info = RequestMappingInfo.paths(prefix).build().combine(info);
}
}
return info;
}
@Nullable
String getPathPrefix(Class<?> handlerType) {
for (Map.Entry<String, Predicate<Class<?>>> entry : this.pathPrefixes.entrySet()) {
if (entry.getValue().test(handlerType)) {
String prefix = entry.getKey();
if (this.embeddedValueResolver != null) {
prefix = this.embeddedValueResolver.resolveStringValue(prefix);
}
return prefix;
}
}
return null;
}
/**
* Delegates to {@link #createRequestMappingInfo(RequestMapping, RequestCondition)},
* supplying the appropriate custom {@link RequestCondition} depending on whether