Support matrix variable (#260)
* support for matrix variable * support for matrix variable Fixes gh-117 * unit tests for matrix variable * Correct JavaDoc fixes gh-117
This commit is contained in:
committed by
Olga Maciaszek-Sharma
parent
774017db85
commit
8a25b8bd63
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2013-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.openfeign.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import feign.MethodMetadata;
|
||||
|
||||
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
||||
import org.springframework.web.bind.annotation.MatrixVariable;
|
||||
|
||||
import static feign.Util.checkState;
|
||||
import static feign.Util.emptyToNull;
|
||||
|
||||
/**
|
||||
* {@link MatrixVariable} annotation processor.
|
||||
*
|
||||
* Can expand maps or single objects. Values are assigned from the objects {@code toString()}
|
||||
* method.
|
||||
*
|
||||
* @author Matt King
|
||||
* @see AnnotatedParameterProcessor
|
||||
*/
|
||||
public class MatrixVariableParameterProcessor implements AnnotatedParameterProcessor {
|
||||
|
||||
private static final Class<MatrixVariable> ANNOTATION = MatrixVariable.class;
|
||||
|
||||
@Override
|
||||
public Class<? extends Annotation> getAnnotationType() {
|
||||
return ANNOTATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processArgument(AnnotatedParameterContext context,
|
||||
Annotation annotation, Method method) {
|
||||
int parameterIndex = context.getParameterIndex();
|
||||
Class<?> parameterType = method.getParameterTypes()[parameterIndex];
|
||||
MethodMetadata data = context.getMethodMetadata();
|
||||
String name = ANNOTATION.cast(annotation).value();
|
||||
|
||||
checkState(emptyToNull(name) != null,
|
||||
"MatrixVariable annotation was empty on param %s.",
|
||||
context.getParameterIndex());
|
||||
|
||||
context.setParameterName(name);
|
||||
|
||||
if (Map.class.isAssignableFrom(parameterType)) {
|
||||
data.indexToExpander().put(parameterIndex, this::expandMap);
|
||||
}
|
||||
else {
|
||||
data.indexToExpander().put(parameterIndex,
|
||||
object -> ";" + name + "=" + object.toString());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private String expandMap(Object object) {
|
||||
Map<String, Object> paramMap = (Map) object;
|
||||
|
||||
return paramMap.keySet().stream()
|
||||
.map(key -> ";" + key + "=" + paramMap.get(key).toString())
|
||||
.collect(Collectors.joining());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,6 +36,7 @@ import feign.Param;
|
||||
import feign.Request;
|
||||
|
||||
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
|
||||
import org.springframework.cloud.openfeign.annotation.MatrixVariableParameterProcessor;
|
||||
import org.springframework.cloud.openfeign.annotation.PathVariableParameterProcessor;
|
||||
import org.springframework.cloud.openfeign.annotation.QueryMapParameterProcessor;
|
||||
import org.springframework.cloud.openfeign.annotation.RequestHeaderParameterProcessor;
|
||||
@@ -355,6 +356,7 @@ public class SpringMvcContract extends Contract.BaseContract
|
||||
|
||||
List<AnnotatedParameterProcessor> annotatedArgumentResolvers = new ArrayList<>();
|
||||
|
||||
annotatedArgumentResolvers.add(new MatrixVariableParameterProcessor());
|
||||
annotatedArgumentResolvers.add(new PathVariableParameterProcessor());
|
||||
annotatedArgumentResolvers.add(new RequestParamParameterProcessor());
|
||||
annotatedArgumentResolvers.add(new RequestHeaderParameterProcessor());
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -45,6 +46,7 @@ import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.MatrixVariable;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
@@ -523,6 +525,35 @@ public class SpringMvcContractTests {
|
||||
this.contract.parseAndValidateMetadata(method.getDeclaringClass(), method);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatrixVariable_MapParam() throws Exception {
|
||||
Method method = TestTemplate_MatrixVariable.class
|
||||
.getDeclaredMethod("matrixVariable", Map.class);
|
||||
MethodMetadata data = this.contract
|
||||
.parseAndValidateMetadata(method.getDeclaringClass(), method);
|
||||
|
||||
Map<String, String> testMap = new HashMap<>();
|
||||
testMap.put("param", "value");
|
||||
|
||||
assertThat(data.template().method()).isEqualTo("GET");
|
||||
assertThat(data.template().url()).isEqualTo("/matrixVariable/{params}");
|
||||
assertThat(";param=value")
|
||||
.isEqualTo(data.indexToExpander().get(0).expand(testMap));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatrixVariable_ObjectParam() throws Exception {
|
||||
Method method = TestTemplate_MatrixVariable.class
|
||||
.getDeclaredMethod("matrixVariableObject", Object.class);
|
||||
MethodMetadata data = this.contract
|
||||
.parseAndValidateMetadata(method.getDeclaringClass(), method);
|
||||
|
||||
assertThat(data.template().method()).isEqualTo("GET");
|
||||
assertThat(data.template().url()).isEqualTo("/matrixVariableObject/{param}");
|
||||
assertThat(";param=value")
|
||||
.isEqualTo(data.indexToExpander().get(0).expand("value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddingTemplatedParameterWithTheSameKey()
|
||||
throws NoSuchMethodException {
|
||||
@@ -639,6 +670,16 @@ public class SpringMvcContractTests {
|
||||
|
||||
}
|
||||
|
||||
public interface TestTemplate_MatrixVariable {
|
||||
|
||||
@RequestMapping(path = "/matrixVariable/{params}")
|
||||
String matrixVariable(@MatrixVariable("params") Map<String, Object> params);
|
||||
|
||||
@RequestMapping(path = "/matrixVariableObject/{param}")
|
||||
String matrixVariableObject(@MatrixVariable("param") Object object);
|
||||
|
||||
}
|
||||
|
||||
@JsonAutoDetect
|
||||
@RequestMapping("/advanced")
|
||||
public interface TestTemplate_Advanced {
|
||||
|
||||
Reference in New Issue
Block a user