未使用 Feign 配置
Feign configuration not being used
我在 Spring 启动 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,因此您不需要在构建步骤中再次手动实例化它们。
pseudo-class 可以创建假客户端的地方可能是这样的:
@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");
}
}
当然,有很多选项可以改进它。 F.e., 你可以创建其他 bean(用于编码器、记录器等)或使用默认(自动配置)的 bean。
或者如果你只需要一个假客户端 bean,你可以在 @Configuration
class 中完成。
如果是请求拦截器 - 还有另一个构建器步骤 .requestInterceptors
,您可以在其中传递 collection 个。
编辑: 对于基本身份验证,您不需要单独的用户名和密码 header,而是一个 header "Authorization" .它的值应该类似于 "Basic username:password",其中 "username:password" 部分应该使用 Base64 (link) 编码。
所以,在你的 @Configuration
class 你可以这样写:
@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是一个很常见的任务,所以BasicAuthRequestInterceptor
是由Feign引入的,它也做同样的事情。您可以改用它。所以现在,在 @Configuration
class 中你可以创建两个 beans:
@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");
}
}
我在 Spring 启动 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,因此您不需要在构建步骤中再次手动实例化它们。
pseudo-class 可以创建假客户端的地方可能是这样的:
@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");
}
}
当然,有很多选项可以改进它。 F.e., 你可以创建其他 bean(用于编码器、记录器等)或使用默认(自动配置)的 bean。
或者如果你只需要一个假客户端 bean,你可以在 @Configuration
class 中完成。
如果是请求拦截器 - 还有另一个构建器步骤 .requestInterceptors
,您可以在其中传递 collection 个。
编辑: 对于基本身份验证,您不需要单独的用户名和密码 header,而是一个 header "Authorization" .它的值应该类似于 "Basic username:password",其中 "username:password" 部分应该使用 Base64 (link) 编码。
所以,在你的 @Configuration
class 你可以这样写:
@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是一个很常见的任务,所以BasicAuthRequestInterceptor
是由Feign引入的,它也做同样的事情。您可以改用它。所以现在,在 @Configuration
class 中你可以创建两个 beans:
@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");
}
}