我自己用的依赖如下:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>11.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
<version>11.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>11.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>11.0</version>
</dependency>
有两种使用方式,但是不管哪种方式,都需要在启动类上加上注解@EnableFeignClients
。
先说我最常用的配置:
@Configuration
@Slf4j
public class CustomFeignBuilder {
@Bean(name = "custom")
public Feign.Builder getFeignBuilder() {
return Feign.builder()
.logLevel(Level.NONE)
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.logger(new ErrorLogger())
.errorDecoder(errorDecoder())
.retryer(retryer())
.options(getOptions())
.requestInterceptor(new FeignHeaderInterceptor())
.client(apacheHttpClient());
}
@Bean
public Retryer retryer() {
return Retryer.NEVER_RETRY;
}
@Bean
public FeignErrorDecoder errorDecoder() {
return new FeignErrorDecoder();
}
@Bean
public Request.Options getOptions() {
return new Request.Options(2, TimeUnit.SECONDS, 2, TimeUnit.SECONDS, true);
}
@Bean
public ApacheHttpClient apacheHttpClient(){
log.info("init feign httpclient configuration " );
// 生成默认请求配置
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
// 超时时间
requestConfigBuilder.setSocketTimeout(1000);
// 连接时间
requestConfigBuilder.setConnectTimeout(1000);
// 连接池获取的 超时时间
requestConfigBuilder.setConnectionRequestTimeout(1000);
RequestConfig defaultRequestConfig = requestConfigBuilder.build();
// 连接池配置
// 长连接保持30秒
final PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.MILLISECONDS);
// 总连接数
pollingConnectionManager.setMaxTotal(5000);
// 同路由的并发数
pollingConnectionManager.setDefaultMaxPerRoute(1000);
// httpclient 配置
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
// 保持长连接配置,需要在头添加Keep-Alive
httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());
httpClientBuilder.setConnectionManager(pollingConnectionManager);
httpClientBuilder.setDefaultRequestConfig(defaultRequestConfig);
CloseableHttpClient client = httpClientBuilder.build();
// 启动定时器,定时回收过期的连接
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
log.debug("=====closeIdleConnections===");
pollingConnectionManager.closeExpiredConnections();
pollingConnectionManager.closeIdleConnections(5, TimeUnit.SECONDS);
}
}, 10 * 1000, 5 * 1000, TimeUnit.MILLISECONDS);
log.info("===== Apache httpclient 初始化连接池===");
return new ApacheHttpClient(client);
}
}
我使用的是apacheHttpClient,在调用时,先创建工厂,再生成client:
@Configuration
public class FeignFactory {
@Value("${user-center.url}")
private String UC_URL;
//可以定义多个feignBuilder配置不同的拦截器
@Resource(name = "commentFeign")
private Feign.Builder commentFeignBuilder;
@Resource(name = "custom")
private Feign.Builder feignBuilder;
@Bean("ucClient")
public UcClient getUcClient(){
return commentFeignBuilder.target(UcClient.class,UC_URL);
}
}
创建client,调用具体接口:
public interface UcClient {
@RequestLine("GET /*")
JSONObject batchUser(@QueryMap Map<String,Object> params);
@RequestLine("POST /**")
@Headers({"Content-Type: application/json", "Accept: application/json"})
JSONObject batchUserPost(@RequestBody Map<String,Object> params);
}
还有一种使用方式:
@Configuration
public class FeignConfig {
@Bean
public Request.Options options() {
Request.Options options = new Request.Options(
5000, 15000
);
return options;
}
@Bean
public Retryer retryer() {
return new Retryer.Default(100, SECONDS.toMillis(1), 2);
}
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
/**
* new一个form编码器,实现支持form表单提交
*/
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
/**
* 开启Feign的日志
*/
@Bean
public Logger.Level logger() {
return Logger.Level.FULL;
}
}
不需要创建工厂,直接写调用接口:
@FeignClient(name = "baidu-applet-client", url = "${applet.baidu.sohu.url}", configuration = FeignConfig.class)
public interface BaiduAppletClient {
/**
* 获取token
* @param grantType
* @param clientId
* @param clientSecret
* @param scope
* @return
*/
@GetMapping(value = "/*")
BaiduTokenResponseDTO getToken(@RequestParam(value = "grant_type") String grantType,
@RequestParam(value = "client_id") String clientId,
@RequestParam(value = "client_secret") String clientSecret,
@RequestParam(value = "scope") String scope);
}
两种方法都可以~~