<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          擼了一個(gè) Feign 增強(qiáng)包

          共 3137字,需瀏覽 7分鐘

           ·

          2020-07-31 15:00

          前言

          最近準(zhǔn)備將公司的一個(gè)核心業(yè)務(wù)系統(tǒng)用 Java 進(jìn)行重構(gòu),大半年沒寫 Java ,JDK 都更新到 14 了,考慮到穩(wěn)定性等問題最終還是選擇的 JDK11。

          在整體架構(gòu)選型時(shí),由于是一個(gè)全新的系統(tǒng),所以沒有歷史包袱,同時(shí)團(tuán)隊(duì)中也有多位大牛坐鎮(zhèn),因此我們的選項(xiàng)便大膽起來。

          最終結(jié)果就是直接一把梭,直接上未來的大趨勢:Service Mesh,直接把什么 SpringCloudDubbo 這類分布式框架全部干掉。

          本次的重點(diǎn)不是討論 Service Mesh 是什么、能解決什么問題、為什么選擇它,畢竟我也在學(xué)習(xí)階段,啥時(shí)候整明白線上也穩(wěn)定了再和大家來交流。

          問題

          既然方向定了就開始實(shí)際擼碼了,不過剛一開始就驗(yàn)證了”理想很豐滿、現(xiàn)實(shí)很骨感“;

          由于我們?nèi)サ袅?SpringCloudDubbo 這類框架,服務(wù)的注冊、發(fā)現(xiàn)、負(fù)載均衡等需求全部都下沉到 Service Mesh 中提供了。

          但對于開發(fā)來說依然希望可以調(diào)用本地方法的方式來調(diào)用遠(yuǎn)程服務(wù),這在 SpringCloud 這類框架中是很容易實(shí)現(xiàn)的,框架本身就有很好的支持。

          回到我們這個(gè)場景,需求其實(shí)很簡單,就是想達(dá)到 SpringCloud 中的 Feign 這樣的聲明式+注解的方式調(diào)用。

          ????@Autowired
          ????private?StoreClient?client?;
          ????
          ????Store?store?=?client.update(1,?store)

          使用 spring-cloud-openfeign 這個(gè)包其實(shí)就能實(shí)現(xiàn)上述的需求了,但這樣會引入一些我們根本不會使用的 SpringCloud 的相關(guān)依賴,讓人感覺”不干凈了“;同時(shí)也和 Service Mesh 的理念相反,其中的一大目的就是要降低這類框架的侵入性。


          其實(shí) spring-cloud-openfeign 的核心就是 Feign,本身它也是可以開箱即用的,所以便嘗試看 Feign 自己是否支持這樣的用法。

          通過官方文檔可以得知:是可以定義接口的形式來調(diào)用遠(yuǎn)程接口的,但它本質(zhì)上是不依賴其他庫便可以使用,所以它本身是沒有和 Spring 整合也是合情合理,但也就造成了沒有現(xiàn)成庫可供我們使用。

          我們自然是不想寫上圖紅框處的代碼的,希望所有接口直接注入就可以使用。

          使用

          因此結(jié)合以上的需求便有了這個(gè)庫 feign-plus

          它的使用流程其實(shí)就是翻版的 spring-cloud-openfeign

          @FeignPlusClient(name?=?"github",?url?=?"${github.url}")
          public?interface?Github?{

          ????@RequestLine("GET?/repos/{owner}/{repo}/contributors")
          ????List?contributors(@Param("owner")?String?owner,?@Param("repo")?String?repo);
          }

          SpringBoot 入口進(jìn)行掃描:

          @SpringBootApplication
          @EnableFeignPlusClients(basePackages?=?"top.crossoverjie.feign.test")
          public?class?DemoApplication?{

          ?public?static?void?main(String[]?args)?{
          ??SpringApplication.run(DemoApplication.class,?args);
          ?}

          }

          Spring 上下文中直接注入使用:

          ????@Autowired
          ????private?Github?github?;
          ????
          ????List?contributors?=?github.contributors("crossoverJie",?"feign-plus");
          ????logger.info("contributors={}",?new?Gson().toJson(contributors));????

          所以當(dāng)我們需要調(diào)用一些外部第三方接口時(shí)(比如支付寶、外部 OpenAPI)便可類似于這樣定義一個(gè)接口,把所有 HTTP 請求的細(xì)節(jié)屏蔽掉。

          當(dāng)然也適合公司內(nèi)部之間的服務(wù)調(diào)用,和咱們以前寫 SpringCloudDubbo 時(shí)類似;服務(wù)提供方提供一個(gè) Client 包,消費(fèi)方直接依賴便可以調(diào)用。其他的負(fù)載均衡、容錯(cuò)之類的由 Service Mesh 替我們完成。

          對于內(nèi)部接口,也可以加上 @RequestMapping("/path") 注解:

          在請求時(shí)便會在 url 后拼接上 /order,這樣在配置 feign.order.service.url 時(shí)只需要填入服務(wù)提供方的域名或 IP 即可。


          feign-plus 也支持切換具體的 httpclient,默認(rèn)是 okhttp3,通過以下配置便可更改。

          # default(okhttp3)
          feign.httpclient=http2Client

          當(dāng)然也有其他相關(guān)配置:

          feign.plus.max-idle-connections = 520
          feign.plus.connect-timeout = 11000
          feign.plus.read-timeout = 12000

          實(shí)現(xiàn)

          最后簡單聊聊是如何完成的吧,其實(shí)本質(zhì)上就是 spring-cloud-openfeign 的濃縮版。

          其中最為核心的便是 top.crossoverjie.feign.plus.factory.FeignPlusBeanFactory 類。

          該類實(shí)現(xiàn)了 org.springframework.beans.factory.FactoryBean接口,并重寫了 getObject() 方法返回一個(gè)對象。

          這段代碼是不是似曾相識,其實(shí)就是 Feign 的官方 demo。

          這里所返回的對象其實(shí)就是我們定義的接口的代理對象,而這個(gè)對象本身則是 Feign ,所以再往里說:我們的 http 請求編解碼、發(fā)起請求等邏輯又被這個(gè) feign 對象所代理了。

          這個(gè) HardCodedTarget 則是 Feign 內(nèi)部用于代理最終請求的對象。

          有一個(gè)小難受的地方:這樣的自己定義 Bean 然后注入對象 Idea 是識別不了的,認(rèn)為當(dāng)前上下文沒有該 Bean,但是 spring-cloud-openfeign 卻可以識別。


          由于 Feign 支持多個(gè)客戶端,所以這里的客戶端可以通過配置文件動(dòng)態(tài)指定。

          利用 SpringBoot 提供的 @ConditionalOnExpression 注解可以根據(jù)配置動(dòng)態(tài)的選擇使用哪個(gè) httpclient,也就是動(dòng)態(tài)選擇生成哪個(gè) Bean。

          總結(jié)

          這個(gè)庫的邏輯非常簡單,本質(zhì)上就是封裝了 Feign 并提供了 SpringBoot 的支持,歡迎有類似需求的朋友下載使用。

          feign-plus源碼:https://github.com/crossoverJie/feign-plus


          推薦閱讀:


          喜歡我可以給我設(shè)為星標(biāo)哦

          好文章,我“在看”
          瀏覽 19
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青草无码视频免费播放 | 亚洲视频在线观 | 操你啦人人操 | 欧美性爱91 | 插插插91 |