#467 - AnnotationMappingDiscoverer now considers @RequestMapping(params = …)
We now inspect the static request parameters declared in the actual request mapping and apply those values when building URIs pointing to those methods. Original pull request: #1576.
This commit is contained in:
committed by
Oliver Drotbohm
parent
8c4824245e
commit
445d5fd4d8
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.hateoas.server.core;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static org.springframework.core.annotation.AnnotatedElementUtils.*;
|
||||
import static org.springframework.core.annotation.AnnotationUtils.*;
|
||||
|
||||
@@ -40,6 +41,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @author Greg Turnquist
|
||||
* @author Réda Housni Alaoui
|
||||
* @deprecated since 1.2, not for removal but for hiding within the package in 1.3
|
||||
*/
|
||||
@Deprecated
|
||||
@@ -167,6 +169,14 @@ public class AnnotationMappingDiscoverer implements MappingDiscoverer {
|
||||
: Arrays.stream(mediaTypes).map(MediaType::parseMediaType).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParams(Method method) {
|
||||
Annotation annotation = findMergedAnnotation(method, annotationType);
|
||||
String[] params = (String[]) getValue(annotation, "params");
|
||||
|
||||
return ofNullable(params).orElseGet(() -> new String[0]);
|
||||
}
|
||||
|
||||
private String[] getMappingFrom(@Nullable Annotation annotation) {
|
||||
|
||||
if (annotation == null) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Michal Stochmialek
|
||||
* @author Oliver Drotbohm
|
||||
* @author Réda Housni Alaoui
|
||||
*/
|
||||
public class CachingMappingDiscoverer implements MappingDiscoverer {
|
||||
|
||||
@@ -104,6 +105,11 @@ public class CachingMappingDiscoverer implements MappingDiscoverer {
|
||||
return delegate.getConsumes(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParams(Method method) {
|
||||
return delegate.getParams(method);
|
||||
}
|
||||
|
||||
private static String key(Class<?> type, @Nullable Method method) {
|
||||
|
||||
StringBuilder builder = new StringBuilder(type.getName());
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.lang.Nullable;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Greg Turnquist
|
||||
* @author Réda Housni Alaoui
|
||||
*/
|
||||
public interface MappingDiscoverer {
|
||||
|
||||
@@ -79,4 +80,10 @@ public interface MappingDiscoverer {
|
||||
* @since 1.3
|
||||
*/
|
||||
List<MediaType> getConsumes(Method method);
|
||||
|
||||
/**
|
||||
* @param method - must not be null.
|
||||
* @return the parameters of the mapped request, narrowing the primary mapping.
|
||||
*/
|
||||
String[] getParams(Method method);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.web.context.WebApplicationContext;
|
||||
*
|
||||
* @author Lars Michele
|
||||
* @author Oliver Drotbohm
|
||||
* @author Réda Housni Alaoui
|
||||
*/
|
||||
class PropertyResolvingMappingDiscoverer implements MappingDiscoverer {
|
||||
|
||||
@@ -91,6 +92,11 @@ class PropertyResolvingMappingDiscoverer implements MappingDiscoverer {
|
||||
return delegate.getConsumes(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParams(Method method) {
|
||||
return delegate.getParams(method);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String resolveProperties(@Nullable String mapping) {
|
||||
|
||||
|
||||
@@ -24,9 +24,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
@@ -34,12 +32,15 @@ import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.server.MethodLinkBuilderFactory;
|
||||
import org.springframework.hateoas.server.core.LinkBuilderSupport;
|
||||
import org.springframework.hateoas.server.core.MethodParameters;
|
||||
import org.springframework.hateoas.server.core.SpringAffordanceBuilder;
|
||||
import org.springframework.hateoas.server.core.WebHandler;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
import org.springframework.web.servlet.mvc.condition.NameValueExpression;
|
||||
import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
@@ -54,6 +55,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
* @author Kevin Conaway
|
||||
* @author Andrew Naydyonock
|
||||
* @author Greg Turnquist
|
||||
* @author Réda Housni Alaoui
|
||||
*/
|
||||
public class WebMvcLinkBuilderFactory implements MethodLinkBuilderFactory<WebMvcLinkBuilder> {
|
||||
|
||||
@@ -120,6 +122,19 @@ public class WebMvcLinkBuilderFactory implements MethodLinkBuilderFactory<WebMvc
|
||||
|
||||
return WebHandler.linkTo(invocationValue, WebMvcLinkBuilder::new, (builder, invocation) -> {
|
||||
|
||||
String[] primaryParams = SpringAffordanceBuilder.DISCOVERER.getParams(invocation.getMethod());
|
||||
ParamsRequestCondition paramsRequestCondition = new ParamsRequestCondition(primaryParams);
|
||||
for (NameValueExpression<String> expression: paramsRequestCondition.getExpressions()) {
|
||||
if (expression.isNegated()) {
|
||||
continue;
|
||||
}
|
||||
String value = expression.getValue();
|
||||
if (value == null){
|
||||
continue;
|
||||
}
|
||||
builder.queryParam(expression.getName(), value);
|
||||
}
|
||||
|
||||
MethodParameters parameters = MethodParameters.of(invocation.getMethod());
|
||||
Iterator<Object> parameterValues = Arrays.asList(invocation.getArguments()).iterator();
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
* @author Oliver Gierke
|
||||
* @author Kamill Sokol
|
||||
* @author Ross Turner
|
||||
* @author Réda Housni Alaoui
|
||||
*/
|
||||
class WebMvcLinkBuilderFactoryUnitTest extends TestUtils {
|
||||
|
||||
@@ -113,6 +114,13 @@ class WebMvcLinkBuilderFactoryUnitTest extends TestUtils {
|
||||
assertThat(link.getHref()).endsWith("/something/with%20blank/foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksToMethodWithPrimaryParam(){
|
||||
Link link = linkTo(methodOn(ControllerWithMethods.class).methodWithPrimaryParams()).withSelfRel();
|
||||
assertThat(link.getRel()).isEqualTo(IanaLinkRelations.SELF);
|
||||
assertThat(link.getHref()).endsWith("/something/foo?a=1&b=2");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #96
|
||||
*/
|
||||
|
||||
@@ -58,6 +58,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
* @author Kevin Conaway
|
||||
* @author Oliver Trosien
|
||||
* @author Greg Turnquist
|
||||
* @author Réda Housni Alaoui
|
||||
*/
|
||||
class WebMvcLinkBuilderUnitTest extends TestUtils {
|
||||
|
||||
@@ -666,6 +667,11 @@ class WebMvcLinkBuilderUnitTest extends TestUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequestMapping(path = "/foo", params = {"a=1", "b=2", "c!=4", "!d"})
|
||||
HttpEntity<Void> methodWithPrimaryParams(){
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/{id}/foo")
|
||||
HttpEntity<Void> methodForNextPage(@PathVariable String id, @RequestParam(required = false) Integer offset,
|
||||
@RequestParam Integer limit) {
|
||||
|
||||
Reference in New Issue
Block a user