java - Feign 配置未被使用

标签 java spring-boot feign

我在 Spring Boot API 中使用 Feign,我想使用以下内容对其进行配置:

import feign.RequestInterceptor;
import feign.auth.BasicAuthRequestInterceptor;
import feign.codec.ErrorDecoder;
import feign.okhttp.OkHttpClient;
import org.apache.http.entity.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignClientConfiguration {

    @Bean
    public ErrorDecoder errorDecoder() {
        return new ErrorDecoder.Default();
    }

    @Bean
    public OkHttpClient client() {
        return new OkHttpClient();
    }

    @Bean
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> {
            requestTemplate.header("user", "some user");
            requestTemplate.header("password", "some password");
            requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
        };
    }


}

问题是,如果我在服务中使用以下代码,我会收到 401,似乎没有提供身份验证数据:

        Feign.builder()
        .client(new OkHttpClient())
        .encoder(new GsonEncoder())
        .decoder(new GsonDecoder())
        .logger(new Slf4jLogger(Npa.class))
        .target(AClass.class, "https://some.website");

如果我只添加一行指定用户和密码,它就可以工作:

    Feign.builder()
    .client(new OkHttpClient())
    .encoder(new GsonEncoder())
    .decoder(new GsonDecoder())
    .logger(new Slf4jLogger(Npa.class))
    .requestInterceptor(new BasicAuthRequestInterceptor("some user", "some password"))
    .target(AClass.class, "https://some.website");

我更愿意使用该配置,但我不明白其中有什么问题。

最佳答案

由于您已经创建了一些 Bean,因此您无需在构建器步骤中再次手动实例化它们。

您可以在其中创建假客户端的伪类可能如下所示:

@Component
public class FeignClientFactory {

    @Autowired
    private ErrorDecoder errorDecoder;

    @Autowired
    private OkHttpClient client;

    @Autowired
    private RequestInterceptor requestInterceptor;

    public AClass getFeignClient() {
        return Feign.builder()
                .client(client)
                .encoder(new GsonEncoder())
                .decoder(new GsonDecoder())
                .logger(new Slf4jLogger(Npa.class))
                .requestInterceptor(requestInterceptor)
                .target(AClass.class, "https://some.website");
    }
}

当然,有很多改进的选择。例如,您可以创建其他 bean(用于编码器、记录器等)或使用默认(自动配置)的 bean。

或者,如果您只需要一个假客户端 bean,则可以在 @Configuration 类中执行此操作。

对于请求拦截器 - 还有另一个构建器步骤 .requestInterceptors,您可以在其中传递它们的集合。

编辑:对于基本身份验证,您不需要单独的用户名和密码 header ,而是需要一个 header “授权”。它的值应类似于“Basic username:password”,其中“username:password”部分应使用 Base64 进行编码 ( link )。

因此,在您的 @Configuration 类中,您可以这样编写:

@Bean
public RequestInterceptor requestInterceptor() {
    return requestTemplate -> {
        String encodedCredentials = Base64.getEncoder()
            .encodeToString("some user:some password".getBytes());
        requestTemplate.header("Authorization", "Basic " + encodedCredentials);
        requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
    };
}

然后您可以使用这个 bean 来构建 Feign 客户端,如上所述。

另一个选项:因为创建授权 header 是一项非常常见的任务,所以 Feign 引入了 BasicAuthRequestInterceptor 来执行相同的操作。你可以用它来代替。现在,在 @Configuration 类中,您可以创建两个 bean:

    @Bean
    @Qualifier("basicAuthRequestInterceptor")
    public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
        return new BasicAuthRequestInterceptor("some user","some password");
    }

    @Bean
    @Qualifier("customRequestInterceptor")
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> {
            requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
        };
    }

在这种情况下,您需要修改 feign 客户端构建方法才能应用这两个拦截器:

@Component
public class FeignClientFactory {

    @Autowired
    private ErrorDecoder errorDecoder;

    @Autowired
    private OkHttpClient client;

    @Autowired
    @Qualifier("basicAuthRequestInterceptor")
    private RequestInterceptor basicAuthRequestInterceptor;

    @Autowired
    @Qualifier("customRequestInterceptor")
    private RequestInterceptor requestInterceptor;

    public AClass getFeignClient() {
        List<RequestInterceptor> requestInterceptors = new ArrayList<>();
        requestInterceptors.add(basicAuthRequestInterceptor);
        requestInterceptors.add(requestInterceptor);

        return Feign.builder()
                .client(client)
                .encoder(new GsonEncoder())
                .decoder(new GsonDecoder())
                .logger(new Slf4jLogger(Npa.class))
                .requestInterceptors(requestInterceptors)
                .target(AClass.class, "https://some.website");
    }
}

关于java - Feign 配置未被使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61330274/

相关文章:

java - 带有正斜杠的假客户端 URL

java - 假装日志记录不起作用

java - 无法添加两个标题面板

java - ClassCastException : org. springframework.orm.jpa.EntityManagerHolder 无法转换为 org.springframework.orm.hibernate5.SessionHolder

java - 带有 RESTful Web 应用程序的 JDBC 模板和 AngularJS

spring - @configuration在spring中的实际用法是什么?

spring-cloud-feign - 如何禁用Feign的自动重试逻辑

java - 控制台仅显示文件名和文件内容,而不是仅显示内容

java - 当我尝试使用 java 包 jdde 时 MATLAB 挂起,但只是在系统重新启动后第一次挂起

java - hibernate 不再工作......为什么?