完美解決SpringCloud-OpenFeign使用okhttp替換不生效問題
事發(fā)地
原默認(rèn)的Feign是使用URLConnector進(jìn)行通信的,當(dāng)換為okhttp時(shí),直接引入包及配置以下內(nèi)容根本不生效,還是走原生的。
feign: okhttp: enable: true
事件還原
創(chuàng)建項(xiàng)目并引入pom相關(guān)的依賴如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <properties> <java.version>1.8</java.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>``
啟動(dòng)類
@SpringBootApplication
@EnableFeignClients
public class Ch21OpenFeignApplication {
public static void main(String[] args) {
SpringApplication.run(Ch21OpenFeignApplication.class, args);
}
}
配置文件
bootstrap.yml,這里只配置是否使用相關(guān)的HTTP
logging: level: springcloud.service.HelloFeignService: debug feign: okhttp: enable: true httpclient: enable: false
測(cè)試類
Controller
.`@RestController
public class HelloFeignController {
@Autowired
private HelloFeignService helloFeignService;
@RequestMapping(value = "/helloFeign",method = RequestMethod.GET)
public Object helloFeign(){
return helloFeignService.helloFeign();
}
}`
service
@FeignClient(name = "feign-client",url = "http://localhost:8761",fallback = FallbackService.class)
public interface HelloFeignService {
@RequestMapping(value = "/query/eureka-server",method = RequestMethod.GET)
String helloFeign();
}
案件還原
寫好上述的配置與類后,開始DEBUG,下圖是Controller的DEBUG入口:

進(jìn)入代理類查看HTTPCLIENT使用的是哪一個(gè)

到下圖時(shí)就要注意了,這才是進(jìn)入使用client的入口


結(jié)果看下圖:

參考
經(jīng)過查找資料,有文章提到是自動(dòng)配置類的問題FeignAutoConfiguration,文章參考:www.dbjr.com.cn/article/206294.htm文章提到,由于@ConditionalOnMissingBean({okhttp3.OkHttpClient.class})導(dǎo)致了無(wú)法注入OkHttpClient

個(gè)人猜測(cè)
在只添加依賴包時(shí),還沒有自行創(chuàng)建okhttp相關(guān)的BEAN時(shí),結(jié)果如下與添加了創(chuàng)建okhttp時(shí)一樣。
啟動(dòng)springboot項(xiàng)目時(shí),BEAN容器化時(shí)機(jī)不同導(dǎo)致得不到想要的client,在啟動(dòng)項(xiàng)目時(shí),org.springframework.cloud.openfeign.FeignAutoConfiguration這個(gè)配置類是執(zhí)行后。在BEAN裝載時(shí)看到BEAN一級(jí)緩存如下圖,并沒有OKHTTP相關(guān)的信息。
在這個(gè)自動(dòng)裝配類最下方有一段代碼根本沒有執(zhí)行,所以從始到終都沒有看到有okHttpClient
@Bean
@ConditionalOnMissingBean(Client.class)
public Client feignClient() {
return new OkHttpClient(this.okHttpClient);
}

當(dāng)我在主類添加以下代碼時(shí),得到的bean如下:
注意:feignClient 這個(gè)bean 是一個(gè)loadBalancerFeignClient
@Bean
public okhttp3.OkHttpClient okHttpClient(){
return new okhttp3.OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool())
// .addInterceptor();
.build();
}

當(dāng)我在主類再追加以下代碼時(shí),得到的bean如下:
注意:feignClient 這個(gè)bean,是我們要找的okhttp了
@Bean
@ConditionalOnMissingBean({Client.class})
public Client feignClient(okhttp3.OkHttpClient client) {
return new feign.okhttp.OkHttpClient(client);
}

真正的真相
這個(gè)要再多看下創(chuàng)建流程,從代碼上分析,這時(shí)在有new feign.okhttp.OkHttpClient(client); 這一段代碼,重新把okhttp注入后,才使得feignClient 名稱對(duì)應(yīng)的bean為okhttp。不防從以下代碼進(jìn)行分析:
LoadBalancerFeignClient 的來源
如下圖,LoadBalancerFeignClient是繼承了Client,進(jìn)入實(shí)現(xiàn)類feign.Client.Default,這個(gè)類全程都只有使用HttpURLConnection,所以無(wú)論怎樣都只能獲取到的是默認(rèn)的JDK里的http的client

所以這個(gè)類創(chuàng)建后要想使用okhttp,那么就只能重新創(chuàng)建把舊的bean沖掉,還好,在主類添加的@Bean創(chuàng)建的類正是在完成bean后再執(zhí)行這里主類增加的@Bean創(chuàng)建的對(duì)象,所以最后加載過程中又會(huì)執(zhí)行bean生命周期的finishBeanFactoryInitialization(beanFactory);
方法所在位置如下:
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
注意事項(xiàng)
在主類添加的方法用來創(chuàng)建okhttp時(shí),方法名一定要寫成下圖的這樣,不然創(chuàng)建不了feignClient這個(gè)bean。
不知道是否有其他方法。這個(gè)估計(jì)是與org.springframework.cloud.openfeign.FeignAutoConfiguration.OkHttpFeignConfiguration#feignClient有關(guān),相當(dāng)于創(chuàng)建的方法是一個(gè)重寫的過程。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
eclipse/intellij idea 查看java源碼和注釋方法
下面小編就為大家?guī)硪黄猠clipse/intellij idea 查看java源碼和注釋方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
SpringBoot實(shí)現(xiàn)郵件任務(wù)的步驟詳解
這篇文章主要介紹了SpringBoot實(shí)現(xiàn)郵件任務(wù)的步驟詳解,使用Spring Boot實(shí)現(xiàn)QQ郵箱發(fā)送郵件具有快速集成、統(tǒng)一的開發(fā)體驗(yàn)、強(qiáng)大的維護(hù)和擴(kuò)展能力、可靠的送達(dá)性和安全性等優(yōu)勢(shì),可以幫助你快速構(gòu)建穩(wěn)定可靠的郵件發(fā)送功能,需要的朋友可以參考下2023-10-10
Java中檢查值是否存在于數(shù)組中的4種詳細(xì)方法
這篇文章主要給大家介紹了關(guān)于Java中檢查值是否存在于數(shù)組中的4種詳細(xì)方法,相信大家在操作Java的時(shí)候經(jīng)常會(huì)要檢查一個(gè)數(shù)組(無(wú)序)是否包含一個(gè)特定的值,需要的朋友可以參考下2023-08-08

