通過openFeign的實際調用來感受它到底香不香

    最近剛好要和另一個服務進行頻繁的遠程調用,即使對restTemplate也有所封裝,但還是厭倦了restTemplate發送時的各種參數拼接,於是決定嘗試下openFeign;

    feign是一個聲明式的Web服務客戶端,它使得發送web請求變得很容易,而openFign是springcloud對feign的一個升級,可以支持springMvc的註解;

    接下來描述下我是怎麼使用openFeign發送web請求的,首先需要明確,使用openFeign是有一定的代碼侵入的,不過侵入的是consumer的代碼,通過在consumer中添加openFeign的註解來拼裝請求併發送,

一般有兩種方式,一種是consumer端根據provider提供的接口文檔編寫調用用例.另一種是由Prodiver提供一個接口API的jar包供consumer調用;下面上我的測試步驟及代碼,兩種方式都有涉及;

    consumer端

 首先在consumer中引入openFeigin以及HTTPClient的依賴:

     <!-- 引入open-feign的依賴 -->
        <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- 引入open-feign的httpClien依賴 -->
        <dependency>
           <groupId>io.github.openfeign</groupId>
           <artifactId>feign-httpclient</artifactId>
        </dependency>
     <!-- 引入Prodiver提供的接口包(根據實際需要) -->
     <dependency>
        <groupId>com.darling.api</groupId>
        <artifactId>server-apis</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <scope>compile</scope>
     </dependency>

 

  然後在consumer中封裝一個service引入feign,來進行遠程調用,關鍵代碼如下:

package com.darling.eureka.consumer.service;

import com.darling.api.service.UserService;
import com.darling.eureka.consumer.model.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

/**
 * @description:  通過openFeign遠程調用服務提供者
 * @author: dll
 * @date: Created in 2021/9/14 12:29
 * @version: 1.0
 * @modified By:
 */
@FeignClient(name = "EUREKA-PROVIDER")
public interface UserApiService extends UserService{

    @GetMapping("/test/sayHi?name={name}")
    String sayHi(@PathVariable String name);

    /**
     * 測試 插入一條信息
     * @param user
     * @return
     */
    @GetMapping("/test/insertInfo")
    String insertInfo(@RequestBody User user);

}

  說明:

    1、consumer中的啓動類需要加上@EnableFeignClients註解,這裏代碼沒有貼出

    2、FeignClient註解有多種屬性可選,如自定義配置信息的configuration、直接指定訪問鏈接的url等,由於我這裏只是一個測試的demo就直接用name來指定在eureka中註冊的Prodiver的服務名稱了;

    3、代碼中的GetMapping就是上面說的兩種方式之一,consumer根據Prodiver提供的接口文檔進行編碼調用的;

    4、代碼中的UserService就是上面說的另一種方式,由服務提供者提供的一個接口依賴包,我這裏包名叫server-apis,,這樣consumer中就可以像調用本地方法一樣調用遠程服務提供的接口能力,下面貼上UserService的代碼:

package com.darling.api.service;

import com.darling.api.model.UserInfo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @description:
 * @author: dll
 * @date: Created in 2021/9/15 22:02
 * @version:
 * @modified By:
 */
@RequestMapping("/serverApis")
public interface UserService {

    @GetMapping("/test")
    UserInfo test();

    /**
     * 獲取用戶信息
     * @return  用戶姓名、年齡等信息
     */
    @GetMapping("/getInfo")
    UserInfo getInfo();

}

    需要注意的是,無論是通過Prodiver提供的依賴包還是直接編寫調用代碼,以上代碼中所有的類似GetMapping、PostMapping的註解都是由Prodiver暴露出來的接口請求路徑,由feign負責識別、拼裝併發起遠程請求的;

    下面來看看consumer中的Controller的調用代碼:

package com.darling.eureka.consumer.controller;

import com.darling.api.model.UserInfo;
import com.darling.eureka.consumer.model.User;
import com.darling.eureka.consumer.service.UserApiService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @description: 測試openFeign的遠程調用
 * @author: dll
 * @date: Created in 2021/8/25 21:52
 * @version: 1.0
 * @modified By:
 */
@RestController
@RequestMapping("/consumer/test")
public class TestConsumerController {

    @Resource
    private UserApiService userApiService;

    /**
     * 調用UserApiService中自己根據接口文檔編寫的調用代碼
     * @return
     */
    @RequestMapping("/sayHello")
    public String sayHello() {
        String res = userApiService.sayHi("hahaha");
        System.out.println("res = " + res);
        return res;
    }

    /**
     * 調用UserApiService中自己根據接口文檔編寫的調用代碼
     * @param user
     * @return
     */
    @RequestMapping("/insert")
    public String insertInfo(User user) {
        String res = userApiService.insertInfo(user);
        System.out.println("res = " + res);
        return res;
    }

    /**
     * 調用UserApiService中由Prodiver提供的server-apis依賴包中的UserService的接口
     * @return
     */
    @RequestMapping("/getUserInfo")
    public UserInfo getUserInfo() {
        UserInfo res = userApiService.getInfo();
        System.out.println("res = " + res);
        return res;
    }

}

  provider端

  如果沒有采用由Prodiver提供接口依賴包的方式的話,使用openFeign對Prodiver端幾乎無任何侵入,Prodiver只需寫好自己可以提供的服務並提供一份接口文檔即可;

  下面主要聊聊如果通過提供接口依賴包的方式Prodiver應該做哪些調整以及其中可能遇到的坑

  首先,需要定義一個專門用來提供接口能力的api服務(server-apis),就正常的web服務即可,代碼可參見上面的UserService;然後由Prodiver引入這個服務;需要注意的是如果通過這種方式提供服務的話,Prodiver

需要以接口實現類的方式來提供具體服務的實現,不能在controller中定義接口的調用路徑了,否則訪問會直接404;

  總結

  通過以上的調用實例,我們可以得出結論,feign調用雖香但是對代碼的確會有一定的侵入性,主要針對服務的調用者而言,而是通過依賴包調用還是由consumer自己編碼調用,無非是願意接受jar包耦合還是接口文檔耦合了,

所以對於同一個團隊開發的consumer和Prodiver來說,個人更傾向於通過定義統一的接口依賴包,雙方嚴格按照依賴包進行開發,依賴包的變更大家都能實時感知並作出及時響應,調用起來也更方便;而對於跨團隊來開發consumer

和Prodiver來說,個人認爲通過接口文檔會更合理,consumer相對來說能把命運掌握在自己手上,對接的時候只認接口文檔,減少了對接口包的依賴

 

  

    

 

 

 

 

 

 

 

 

 

 

 

 

   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章