Feign - 为每个方法定义参数值

Feign - define param value for each methods

我需要用多种方法编写客户端,这些方法需要 apiKey 作为查询字符串参数。是否可以允许客户端的用户仅将 api 键传递给方法 withApiKey,这样我就可以避免请求 apiKey 作为每个方法的第一个参数?

public interface Client {
    @RequestLine("GET /search/search?key={apiKey}&query={query}&limit={limit}&offset={offset}")
    SearchResponse search(@Param("apiKey") String apiKey, @Param("query") String query, @Param("limit") Integer limit, @Param("offset") Integer offset);

    @RequestLine("GET /product/attributes?key={apiKey}&products={products}")
    List<Product> getProduct(@Param("apiKey") String apiKey, @Param("products") String products);

    public class Builder {
        private String basePath;
        private String apiKey;

        public Client build() {
            return Feign.builder()
                    .encoder(new JacksonEncoder())
                    .decoder(new JacksonDecoder())
                    .client(new ApacheHttpClient())
                    .logger(new Slf4jLogger())
                    .logLevel(Logger.Level.FULL)
                    .target(Client.class, basePath);

        }

        public Builder withBasePath(String basePath) {
            this.basePath = basePath;
            return this;
        }

        public Builder withApiKey(String apiKey) {
            this.apiKey = apiKey;
            return this;
        }
    }
}

根据设置 request-interceptors 可能有效:https://github.com/OpenFeign/feign#request-interceptors

希望下面的示例对您有所帮助。

您可以将构建器换成接口注释,然后将配置移动到配置 class,如果您使用的是 spring,它可能像:

@FeignClient(
    name = "ClerkClient",
    url = "${clery-client.url}", // instead of the withBasePath method 
    configuration = {ClerkClientConfiguration.class}
)
public interface Client {

然后 ClerkClientConfiguration class 可以定义所需的配置 bean,包括 ClerkClientInterceptor

public class ClerkClientConfiguration {

@Bean
public RequestInterceptor clerkClientInterceptor() {
    return new ClerkClientInterceptor();
}

然后拦截器可以从配置中获取一个值并添加到查询中(或 header 等)

    public class ClerkClientInterceptor implements RequestInterceptor {
    
    @Value("${clerk-client.key}")
    private String apiKey

    @Override public void apply(RequestTemplate template) {
       requestTemplate.query( "key", apiKey); 
    }