|
34 | 34 | import feign.Feign; |
35 | 35 | import feign.MethodMetadata; |
36 | 36 | import feign.Param; |
| 37 | +import feign.QueryMap; |
37 | 38 | import feign.Request; |
38 | 39 | import org.apache.commons.logging.Log; |
39 | 40 | import org.apache.commons.logging.LogFactory; |
40 | 41 |
|
41 | 42 | import org.springframework.cloud.openfeign.AnnotatedParameterProcessor; |
42 | 43 | import org.springframework.cloud.openfeign.CollectionFormat; |
| 44 | +import org.springframework.cloud.openfeign.SpringQueryMap; |
43 | 45 | import org.springframework.cloud.openfeign.annotation.CookieValueParameterProcessor; |
44 | 46 | import org.springframework.cloud.openfeign.annotation.MatrixVariableParameterProcessor; |
45 | 47 | import org.springframework.cloud.openfeign.annotation.PathVariableParameterProcessor; |
|
67 | 69 | import org.springframework.util.StringUtils; |
68 | 70 | import org.springframework.web.bind.annotation.RequestMapping; |
69 | 71 | import org.springframework.web.bind.annotation.RequestMethod; |
| 72 | +import org.springframework.web.bind.annotation.RequestParam; |
70 | 73 |
|
71 | 74 | import static feign.Util.checkState; |
72 | 75 | import static feign.Util.emptyToNull; |
@@ -158,7 +161,7 @@ private static TypeDescriptor createTypeDescriptor(Method method, int paramIndex |
158 | 161 |
|
159 | 162 | private static TypeDescriptor getElementTypeDescriptor(TypeDescriptor typeDescriptor) { |
160 | 163 | TypeDescriptor elementTypeDescriptor = typeDescriptor.getElementTypeDescriptor(); |
161 | | - // that means it's not a collection but it is iterable, gh-135 |
| 164 | + // that means it's not a collection, but it is iterable, gh-135 |
162 | 165 | if (elementTypeDescriptor == null && Iterable.class.isAssignableFrom(typeDescriptor.getType())) { |
163 | 166 | ResolvableType type = typeDescriptor.getResolvableType().as(Iterable.class).getGeneric(0); |
164 | 167 | if (type.resolve() == null) { |
@@ -268,8 +271,12 @@ protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[ |
268 | 271 |
|
269 | 272 | try { |
270 | 273 | if (Pageable.class.isAssignableFrom(data.method().getParameterTypes()[paramIndex])) { |
271 | | - data.queryMapIndex(paramIndex); |
272 | | - return false; |
| 274 | + // do not set a Pageable as QueryMap if there's an actual QueryMap param |
| 275 | + // present |
| 276 | + if (!queryMapParamPresent(data)) { |
| 277 | + data.queryMapIndex(paramIndex); |
| 278 | + return false; |
| 279 | + } |
273 | 280 | } |
274 | 281 | } |
275 | 282 | catch (NoClassDefFoundError ignored) { |
@@ -304,6 +311,20 @@ protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[ |
304 | 311 | return isHttpAnnotation; |
305 | 312 | } |
306 | 313 |
|
| 314 | + private boolean queryMapParamPresent(MethodMetadata data) { |
| 315 | + Annotation[][] paramsAnnotations = data.method().getParameterAnnotations(); |
| 316 | + for (int i = 0; i < paramsAnnotations.length; i++) { |
| 317 | + Annotation[] paramAnnotations = paramsAnnotations[i]; |
| 318 | + Class<?> parameterType = data.method().getParameterTypes()[i]; |
| 319 | + if (Arrays.stream(paramAnnotations).anyMatch( |
| 320 | + annotation -> Map.class.isAssignableFrom(parameterType) && annotation instanceof RequestParam |
| 321 | + || annotation instanceof SpringQueryMap || annotation instanceof QueryMap)) { |
| 322 | + return true; |
| 323 | + } |
| 324 | + } |
| 325 | + return false; |
| 326 | + } |
| 327 | + |
307 | 328 | private void parseProduces(MethodMetadata md, Method method, RequestMapping annotation) { |
308 | 329 | String[] serverProduces = annotation.produces(); |
309 | 330 | String clientAccepts = serverProduces.length == 0 ? null : emptyToNull(serverProduces[0]); |
|
0 commit comments