關(guān)于Feign的覆寫默認(rèn)配置和Feign的日志
Feign的覆寫默認(rèn)配置
A central concept in Spring Cloud’s Feign support is that of the named client. Each feign client is part of an ensemble of components that work together to contact a remote server on demand, and the ensemble has a name that you give it as an application developer using the @FeignClient annotation. Spring Cloud creates a new ensemble as anApplicationContext on demand for each named client using FeignClientsConfiguration. This contains (amongst other things) an feign.Decoder, a feign.Encoder, and a feign.Contract.
上面是官網(wǎng)的API文檔中的說明,如下是我的翻譯:
Spring Cloud的Feign支持的一個(gè)中心概念是命名客戶端。
每個(gè)feign client是整體的一部分,它們一起工作以按需聯(lián)系遠(yuǎn)程服務(wù)器,并且該整體具有一個(gè)名稱,開發(fā)人員可以使用@FeignClient將其命名。
Spring Cloud根據(jù)需要使用FeignClientsConfiguration為每個(gè)命名的客戶端創(chuàng)建一個(gè)新的整體作為ApplicationContext。
這包含(其他)feign.Decoder,feign.Encoder和feign.Contract。
Spring Cloud lets you take full control of the feign client by declaring additional configuration (on top of theFeignClientsConfiguration) using @FeignClient. Example:
@FeignClient(name = “stores”, configuration = FooConfiguration.class) public interface StoreClient { //.. }
上面文檔說,通過使用額外的配置@FeignClient注解,可以使Spring Cloud讓你完全的控制feign客戶端。
并且官網(wǎng)還給出了例子,那么我們也按照它提供的例子來在我們的工程師運(yùn)用起來。
將接口類UserFeignClient進(jìn)行修改,如下修改后的代碼:
@FeignClient(name = "microservice-provider-user", configuration = FooConfiguration.class) public interface UserFeignClient { ? ? /** ? ? ?* 注意:要使用Feign的注解 ? ? ?* <p> ? ? ?* <code>@RequestLine("GET /repos/{owner}/{repo}/contributors")</code> ? ? ?* <br> ? ? ?* <code>List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);</code> ? ? ?*? ? ? ?* @param id ? ? ?* @return ? ? ?*/ ? ? @RequestMapping(method = RequestMethod.GET, value = "/simple/{id}") // ?@RequestLine("GET /simple/{id}") ? ? public User findById(@PathVariable("id") Long id); }
在配置FeignClient的configuration指定的值FooConfiguration,這個(gè)類是不存在的,這里我們需要新建,官網(wǎng)中也給我創(chuàng)建了這個(gè)類的代碼,下面是我根據(jù)官網(wǎng)的代碼和我實(shí)際需求修改后的:
@Configuration public class FooConfiguration { ? ? @Bean ? ? public Contract feignContract() { ? ? ? ? return new feign.Contract.Default(); ? ? } }
完成之后,可以開始啟動(dòng)工程了,當(dāng)我們?cè)趩?dòng)時(shí),會(huì)報(bào)錯(cuò),錯(cuò)誤關(guān)鍵如下:
Caused by: java.lang.IllegalStateException: Method findById not annotated with HTTP method type (ex. GET, POST)
這里錯(cuò)誤是說我們沒有使用Http方法的注解導(dǎo)致的,但我們仔細(xì)檢查下代碼,我們使用的是@RequestMapping的注解方式,這里我也不知道怎么解釋,可能是我沒有深刻的理解吧,看了Feign 的GitHub的相關(guān)代碼后,我發(fā)現(xiàn)了另一種注解方式:
interface GitHub { ? @RequestLine("GET /repos/{owner}/{repo}/contributors") ? List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo); }
好的,現(xiàn)在將@RequestMapping注解改成@RequestLine,以及參數(shù)也修改成@Param,修改后:
@FeignClient(name = "microservice-provider-user", configuration = FooConfiguration.class) public interface UserFeignClient { ? ? /** ? ? ?* 注意:要使用Feign的注解 ? ? ?* <p> ? ? ?* <code>@RequestLine("GET /repos/{owner}/{repo}/contributors")</code> ? ? ?* <br> ? ? ?* <code>List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);</code> ? ? ?*? ? ? ?* @param id ? ? ?* @return ? ? ?*/ ? ? @RequestLine("GET /simple/{id}") ? ? public User findById(@Param("id") Long id); }
修改完成之后,再次重啟服務(wù),發(fā)現(xiàn)啟動(dòng)成功,而且可以訪問接口了。
WARNING Previously, using the url attribute, did not require the name attribute. Using name is now required.
官網(wǎng)中有個(gè)這樣的提醒:以前在使用URL屬性時(shí),不必要使用那么屬性,但是在現(xiàn)在Feign中name屬性就是必要的了。
它也給了例子,如下面代碼:
@FeignClient(name = "${feign.name}", url = "${feign.url}") public interface StoreClient { ? ? //.. }
現(xiàn)在我們也來在我們的工程中實(shí)際運(yùn)用一下。
新建一個(gè)接口FeignClient2,代碼如下:
@FeignClient(name = "xxx", url = "http://localhost:8761/", configuration = BeanConfiguration.class) public interface FeignClient2 { // ?@RequestMapping(value = "/eureka/apps/{serviceName}") ? ? @RequestLine("GET /eureka/apps/{serviceName}") ? ? public String findServiceInfoEurekaByServieName(@Param("serviceName") String serviceName); }
我們通過這個(gè)feign來獲取eureka server下注冊(cè)的實(shí)例信息,通過@FeignClient注解配置了name、url和configuration屬性,這里那么我隨便寫的內(nèi)容,因?yàn)檫@個(gè)僅僅表示這個(gè)feign的名稱而已,url配置的是eureka server的地址,configuration我們這里配的一個(gè)需要新建的類BeanConfiguration。
大家肯定還有疑惑,這個(gè)BeanConfiguration類配置了是起什么作用的了?
好的,這里就為大家答疑解惑,首先貼出該類的代碼:
@Configuration public class BeanConfiguration { ? ? @Bean ? ? public BasicAuthRequestInterceptor basicAuthRequestInterceptor() { ? ? ? ? return new BasicAuthRequestInterceptor("micheal", "123456"); ? ? } }
看到代碼,也許大家可能就明白了,這個(gè)在請(qǐng)求時(shí)不需要輸入用戶名和密碼就可以直接調(diào)用Eureka Server,因?yàn)镕eign通過這個(gè)配置的configuration類為我們做了用戶名和密碼的權(quán)限認(rèn)證了。
完成上面的內(nèi)容了,接下來就是見證奇跡的時(shí)刻了。
啟動(dòng)服務(wù),在Eureka Server中查看到注冊(cè)成功了,我們就可以通過瀏覽器進(jìn)行查看了。
Feign Logging 日志
A logger is created for each Feign client created. By default the name of the logger is the full class name of the interface used to create the Feign client. Feign logging only responds to the DEBUG level.
application.yml
logging.level.project.user.UserClient: DEBUG
官網(wǎng)API說:為每個(gè)Feign 客戶端創(chuàng)建日志,日志的默認(rèn)名稱為所創(chuàng)建的Feign客戶端接口類的整個(gè)類名。Feign的日志僅僅只有在DEBUG級(jí)別時(shí)才會(huì)響應(yīng)。
官網(wǎng)給我們提供了例子,按照官網(wǎng)提供的做法,現(xiàn)在來為我們對(duì)的工程配置Feign Logging。
以我們microservice-consumer-movie-feign-customizing工程為例,在配置文件application.yml進(jìn)行Feign 日志配置,如下配置:
logging: ? level: ? ? com.spring.cloud.feign.UserFeignClient: DEBUG
com.spring.cloud.feign.UserFeignClient 是Feign Client接口類的完成類名。好了,完成了這個(gè)配置,是不是有點(diǎn)超激動(dòng)想要一看是否真的能打印出日志了。
先不著急,我們接著查看官網(wǎng)API文檔中的內(nèi)容:
The Logger.Level object that you may configure per client, tells Feign how much to log. Choices are:
• NONE, No logging (DEFAULT).
• BASIC, Log only the request method and URL and the response status code and execution time.
• HEADERS, Log the basic information along with request and response headers.
• FULL, Log the headers, body, and metadata for both requests and responses.
For example, the following would set the Logger.Level to FULL:
@Configuration public class FooConfiguration { ? ? @Bean ? ? Logger.Level feignLoggerLevel() { ? ? ? ? return Logger.Level.FULL; ? ? } }
官網(wǎng)給我們提供了一些日志級(jí)別的等級(jí),這里就不一一翻譯了。我們的重點(diǎn)是在上面所給的例子,上面例子說為日志設(shè)置為FULL級(jí)別的日志。
好,開始我們的配置,找到我們所配Feign 日志的客戶端接口類,我們發(fā)現(xiàn)我們配值得configuration的類時(shí)FooConfiguration類,好我們將官網(wǎng)中的feignLoggerLevel方法添加到我們的FooConfiguration類中。
完成之后,我們啟動(dòng)工程,并先將日志清掉,再重新請(qǐng)求接口,發(fā)現(xiàn)確實(shí)打印出日志來了。
這里還需要補(bǔ)充一下:在配置文件application.yml中配置了Feign客戶端日志之后,如果不在configuration類中添加日志級(jí)別的話,是不會(huì)打印出日志的。因?yàn)樵诠倬W(wǎng)API中有提到“NONE, no loggin(DEFAULT)”,就是說默認(rèn)日志級(jí)別時(shí)NONE的。
Feign進(jìn)行日志配置
在微服務(wù)項(xiàng)目中項(xiàng)目啟動(dòng)遇到 bug 時(shí),很多方面的錯(cuò)誤都有可能出現(xiàn),比如參數(shù)錯(cuò)誤,接口調(diào)用錯(cuò)誤等,或者是想了解服務(wù)接口的使用量和性能。
首先 Feign 支持自定義日志的配置,配置 Feign 的日志信息是針對(duì)以上情況效率很高的一種解決方案。
Feign有四種類型的日志
NONE
:不記錄任何日志信息,默認(rèn)是 NONE 配置。BASIC
:只記錄發(fā)起請(qǐng)求的方法,請(qǐng)求的 URL 地址,請(qǐng)求狀態(tài)碼和請(qǐng)求的響應(yīng)時(shí)間。HEADERS
:在 BASIC 級(jí)別的基礎(chǔ)上,還多記錄了請(qǐng)求頭和響應(yīng)頭的信息。FULL
:記錄所有的日志信息,包括請(qǐng)求和響應(yīng)的所有具體信息。
列出兩種在項(xiàng)目中配置Feign日志的方法
一:在配置文件中配置 Feign 的日志
feign: ? client: ? ? config: ? ? ? default: # 這里用default就是全局配置,如果是寫服務(wù)名稱,則是針對(duì)某個(gè)微服務(wù)的配置 ? ? ? ? loggerLevel: FULL # ?日志級(jí)別
其中 default 表示全局配置日志,將 default 改為具體的服務(wù)名稱,表示在調(diào)用這個(gè)服務(wù)的時(shí)候才會(huì)記錄日志。
loggerLevel 表示日志的水平,包含 NONE、BASIC、HEADERS、FULL 四種級(jí)別的日志。
二:通過配置類的方式
聲明一個(gè)類,取名為 FeignLoggerConfiguration。在類中聲明一個(gè) Logger.Level 對(duì)象并返回日志級(jí)別,這里設(shè)置級(jí)別為 BASIC ,通過 @Bean 注解將該方法設(shè)置為 IOC 容器的組件。
public class FeignLevelConfiguration { ? ? @Bean ? ? public Logger.Level logLevel(){ ? ? ? ? return Logger.Level.BASIC; ? ? } }
同樣的可以設(shè)置全局配置和局部給某個(gè)服務(wù)配置。
全局配置:
在啟動(dòng)類的 @EnableFeignClients 注解中加上參數(shù)
defaultConfiguration = FeignLoggerConfiguration .class
這里的 FeignLoggerConfiguration.class要和配置的日志類一致。
局部配置:
在配置了 Feign 的服務(wù)接口上的注解 @FeignClient("要調(diào)用的服務(wù)名稱") 加上參數(shù)
configuration = FeignLoggerConfiguration .class
這里設(shè)置調(diào)用的服務(wù)名稱為 testservice ,則注解改為
@FeignClient(value = "testservice", configuration = FeignLoggerConfiguration .class)?
這里的 FeignLoggerConfiguration.class 就是上面的日志配置類。
同時(shí),在優(yōu)化 Feign 時(shí)可以從日志的級(jí)別入手,日志盡量使用 Basic 級(jí)別,因?yàn)榇蛴∪罩咎鄷?huì)消耗 Feign 的性能。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot在服務(wù)器上的幾種啟動(dòng)方式(小結(jié))
這篇文章主要介紹了springboot在服務(wù)器上的幾種啟動(dòng)方式(小結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09Hadoop環(huán)境配置之hive環(huán)境配置詳解
這篇文章主要介紹了Hadoop環(huán)境配置之hive環(huán)境配置,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12SpringBoot詳細(xì)講解視圖整合引擎thymeleaf
這篇文章主要分享了Spring Boot整合使用Thymeleaf,Thymeleaf是新一代的Java模板引擎,類似于Velocity、FreeMarker等傳統(tǒng)引擎,關(guān)于其更多相關(guān)內(nèi)容,需要的小伙伴可以參考一下2022-06-06一文詳解Spring任務(wù)執(zhí)行和調(diào)度(小結(jié))
這篇文章主要介紹了一文詳解Spring任務(wù)執(zhí)行和調(diào)度(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Spring框架實(shí)現(xiàn)AOP添加日志記錄功能過程詳解
這篇文章主要介紹了Spring框架實(shí)現(xiàn)AOP添加日志記錄功能過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12關(guān)于SpringBoot攔截器中Bean無法注入的問題
這兩天遇到SpringBoot攔截器中Bean無法注入問題。下面介紹關(guān)于SpringBoot攔截器中Bean無法注入的問題,感興趣的朋友一起看看吧2021-10-10基于Bigdecimal科學(xué)計(jì)數(shù)問題
這篇文章主要介紹了基于Bigdecimal科學(xué)計(jì)數(shù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06Java編程實(shí)現(xiàn)鄰接矩陣表示稠密圖代碼示例
這篇文章主要介紹了Java編程實(shí)現(xiàn)鄰接矩陣表示稠密圖代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11