Feign客户端无法解析查询参数

15
这是我的接口:
public interface SCIMServiceStub {
    @RequestLine("GET /Users/{id}")
    SCIMUser getUser(@Param("id") String id);

    @RequestLine("GET /Groups?filter=displayName+Eq+{roleName}")
    SCIMGroup isValidRole(@Param("roleName") String roleName);
}

这里getUser的调用正常工作。

但是isValidRole由于请求最终被发送成这样,所以无法正常工作。

/Groups?filter=displayName+Eq+{roleName}

这里未解析 {roleName}

我错过了什么?在这一点上,我一无所知,非常感谢您的帮助。

编辑:还有一个问题:有没有办法避免查询参数的自动 URL 编码?

5个回答

27

根据最近(2019.04)的open feign issuespring文档中所述:

OpenFeign的@QueryMap注解提供了支持将POJO用作GET参数映射的功能。

Spring Cloud OpenFeign提供了一个等效的@SpringQueryMap注解,用于将POJO或Map参数注释为查询参数映射,自2.1.0起可以使用。

您可以像这样使用它:

    @GetMapping("user")
    String getUser(@SpringQueryMap User user);
public class User {
    private String name;
    private int age;
    ...
}

2
如果我在User#name的顶部添加了@JsonProperty("na-me"),那么是否期望Feign将使用编码后的"na-me"参数而不是"name"发出请求?因为我认为它应该这样做,但它并没有这样做,我不确定是否应该就此提出单独的问题,或者这只是Feign的工作方式。 - Filip Kowalski
@FilipKowalski 你找到解决问题的方法了吗? - PraBhu
@FilipKowalski - 在这种情况下,你能解决使用@JsonProperty("na-me")的问题吗? - Andrew Niken

12

使用@QueryMap正常工作。

网址:/api/v1/task/search?status=PENDING&size=20&page=0

Map<String, String> parameters = new LinkedHashMap<>()
        parameters.put("status", "PENDING")
        parameters.put("size", "20")
        parameters.put("page", "0")
        def tasks = restClientFactory.taskApiClient.searchTasks(parameters)

客户端界面内部

@RequestLine("GET /api/v1/task/search?{parameters}")
List<Task> searchTasks(@QueryMap Map<String, String> parameters)

2
我非常喜欢这种方法。@QueryMap 对我来说不起作用,但是将其替换为 @SpringQueryMap 就可以了。在使用 @QueryMap 时,Spring 存在一些限制,更多信息请参考:https://cloud.spring.io/spring-cloud-openfeign/reference/html/#feign-querymap-support - Dipen

12

看起来这是由一个已经开启的错误引起的 - https://github.com/OpenFeign/feign/issues/424

就像评论中所述,您可以定义自己的Param.Expander,类似于以下解决方法。

@RequestLine("GET /Groups?filter={roleName}")
String isValidRole(@Param(value = "roleName", expander = PrefixExpander.class) String roleName);

static final class PrefixExpander implements Param.Expander {
    @Override
    public String expand(Object value) {
        return "displayName+Eq+" + value;
    }
}

2

使用Spring Feign客户端以下代码可以正常工作:

@GetMapping("/Groups?filter=displayName+Eq+{roleName}")
SCIMGroup isValidRole(@PathVariable(value = "roleName") String roleName);

1
嗯,正如@Frank.Chang建议的那样,你可以使用@SpringQueryMap来实现这个功能。
@GetMapping("user")
String getUser(@SpringQueryMap User user);

public class User {
    @JsonProperty("na-me")  // json property won't work
    private String name;
    private int age;
    ...
}

但是请记住,在这种情况下,@JsonProperty("na-me")对你来说不起作用。为此,您需要为字段创建一个getter,并在getter上添加来自feign包的@Param注解,就像这样。
public class User {
    private String name;
    private int age;
    ...
    @Param("na-me")
    public String getName() {
        return this.name;
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接