Add support for controller base path on BasePathAwareController / RepositoryRestController.
This commit introduces support for a common base path shared amongst all handler methods of a controller annotated with @BasePathAwareController / @RepositoryRestController. Related ticket: #2087 Original pull request: #2088.
This commit is contained in:
committed by
Oliver Drotbohm
parent
71ae98132c
commit
c73d3816a6
@@ -58,10 +58,10 @@ public class JpaRepositoryConfig extends JpaInfrastructureConfig {
|
||||
void someMethod(@PathVariable String id) {}
|
||||
}
|
||||
|
||||
@RepositoryRestController
|
||||
@RepositoryRestController(path = {"orders", "orders/v2"})
|
||||
static class OrdersJsonController {
|
||||
|
||||
@RequestMapping(value = "/orders/search/sort", method = RequestMethod.POST, produces = "application/hal+json")
|
||||
@RequestMapping(value = {"/search/sort","/search/sorted"}, method = RequestMethod.POST, produces = "application/hal+json")
|
||||
void someMethodWithArgs(Sort sort, Pageable pageable, DefaultedPageable defaultedPageable) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,10 +702,13 @@ public class JpaWebTests extends CommonWebTests {
|
||||
andExpect(client.hasLinkWithRel(IanaLinkRelations.SELF));
|
||||
}
|
||||
|
||||
@Test // DATAREST-910
|
||||
@Test // DATAREST-910 DATAREST-2088
|
||||
void callUnmappedCustomRepositoryController() throws Exception {
|
||||
|
||||
mvc.perform(post("/orders/v3/search/sort")).andExpect(status().isNotFound());
|
||||
mvc.perform(post("/orders/search/sort")).andExpect(status().isOk());
|
||||
mvc.perform(post("/orders/search/sorted")).andExpect(status().isOk());
|
||||
mvc.perform(post("/orders/v2/search/sort")).andExpect(status().isOk());
|
||||
mvc.perform(post("/orders/v2/search/sorted")).andExpect(status().isOk());
|
||||
mvc.perform(post("/orders/search/sort?sort=type&page=1&size=10")).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
@@ -34,4 +35,9 @@ import org.springframework.stereotype.Component;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
|
||||
public @interface BasePathAwareController {
|
||||
@AliasFor("path")
|
||||
String[] value() default {};
|
||||
|
||||
@AliasFor("value")
|
||||
String[] path() default {};
|
||||
}
|
||||
|
||||
@@ -19,11 +19,8 @@ import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
@@ -41,6 +38,8 @@ import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
import static org.springframework.core.annotation.AnnotatedElementUtils.*;
|
||||
|
||||
/**
|
||||
* A {@link RequestMappingHandlerMapping} that augments the request mappings
|
||||
*
|
||||
@@ -51,6 +50,8 @@ public class BasePathAwareHandlerMapping extends RequestMappingHandlerMapping {
|
||||
private static final String AT_REQUEST_MAPPING_ON_TYPE = "Spring Data REST controller %s must not use @RequestMapping on class level as this would cause double registration with Spring MVC!";
|
||||
private final RepositoryRestConfiguration configuration;
|
||||
|
||||
private final String baseUri;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BasePathAwareHandlerMapping} using the given {@link RepositoryRestConfiguration}.
|
||||
*
|
||||
@@ -61,16 +62,7 @@ public class BasePathAwareHandlerMapping extends RequestMappingHandlerMapping {
|
||||
Assert.notNull(configuration, "RepositoryRestConfiguration must not be null!");
|
||||
|
||||
this.configuration = configuration;
|
||||
|
||||
String baseUri = configuration.getBasePath().toString();
|
||||
|
||||
if (StringUtils.hasText(baseUri)) {
|
||||
|
||||
Map<String, Predicate<Class<?>>> prefixes = new HashMap<>();
|
||||
prefixes.put(baseUri, it -> true);
|
||||
|
||||
this.setPathPrefixes(prefixes);
|
||||
}
|
||||
this.baseUri = configuration.getBasePath().toString();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -128,11 +120,24 @@ public class BasePathAwareHandlerMapping extends RequestMappingHandlerMapping {
|
||||
ProducesRequestCondition producesCondition = customize(info.getProducesCondition());
|
||||
Set<MediaType> mediaTypes = producesCondition.getProducibleMediaTypes();
|
||||
|
||||
BasePathAwareController mergedAnnotation = findMergedAnnotation(handlerType, BasePathAwareController.class);
|
||||
if (mergedAnnotation != null) {
|
||||
info = appendPathPrefix(info, mergedAnnotation.value());
|
||||
}
|
||||
info = appendPathPrefix(info, new String[]{this.baseUri});
|
||||
return info.mutate()
|
||||
.produces(mediaTypes.stream().map(MediaType::toString).toArray(String[]::new))
|
||||
.build();
|
||||
}
|
||||
|
||||
private RequestMappingInfo appendPathPrefix(RequestMappingInfo info, String[] pathPrefix) {
|
||||
if (pathPrefix.length > 0) {
|
||||
String[] paths = this.resolveEmbeddedValuesInPatterns(pathPrefix);
|
||||
return info.mutate().paths(paths).build().combine(info);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize the given {@link ProducesRequestCondition}. Default implementation returns the condition as is.
|
||||
*
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
@@ -46,4 +47,9 @@ import org.springframework.web.servlet.HandlerMapping;
|
||||
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
|
||||
@BasePathAwareController
|
||||
public @interface RepositoryRestController {
|
||||
@AliasFor("path")
|
||||
String[] value() default {};
|
||||
|
||||
@AliasFor("value")
|
||||
String[] path() default {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user