最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringCloud  OpenFeign的使用舉例詳解

 更新時間:2025年09月18日 15:33:26   作者:程序猿教你打籃球  
文章介紹Spring Cloud中使用OpenFeign替代RestTemplate進行微服務(wù)通信,通過聲明式接口和注解簡化調(diào)用,建議將Feign客戶端抽離為獨立模塊,統(tǒng)一實體類,解決代碼冗余問題,部署時需配置本地jar包依賴,確保服務(wù)調(diào)用正常,感興趣的朋友跟隨小編一起看看吧

1. OpenFeign

1.1 OpenFeign 的介紹

先來看看咱們之前寫的遠程方法調(diào)用代碼:

@RequestMapping("/ok")
public String ok(@PathParam("content")String content) {
    String url = "http://waiter-service/waiter/up/{content}";
    String resp = restTemplate.getForObject(url, String.class, content);
    return "調(diào)用成功, 已收到 waiter 的響應(yīng): " + resp;
}

雖然說 RestTemplate 對 http 封裝后,使用起來還算方便,但是需要拼接 url,如果 url 很復(fù)雜呢?而且代碼可讀性很差,風格也不好統(tǒng)一。

在微服務(wù)之間的通信方式通常分為:RPC 和 HTTP,至于 RPC 后期有機會在介紹。

在 SpringCloud 中,默認使用的是 HTTP 來進行微服務(wù)的通信,最常用的實現(xiàn)有兩種:

  • RestTemplate
  • OpenFeign

RestTemplate 咱們已經(jīng)見過了,接下來就學習下 OpenFeign,這是一種更優(yōu)雅的遠程方法調(diào)用的形式。

OpenFeign 是一個聲明式的 Web Service 客戶端,它讓微服務(wù)之間的調(diào)用變得更簡單了。類似于 Controller 調(diào)用 Service,只需要創(chuàng)建一個接口,然后添加注解即可以使用 OpenFeign。

本來是 Feign 是由 Netflix 公司開源的組件,后來呢,在16年7月發(fā)布了最后一個版本,就將捐給了社區(qū),16年7月,OpenFeign 首個版本 9.0.0 發(fā)布后,就一直發(fā)布到現(xiàn)在。

SpringCloud 將 Feign 項目繼承到 SpringCloud 的生態(tài)中,但是受到 Feign 更名的影響,所以 SpringCloudFeign 有兩個 starter。

spring-cloud-starter-feign spring-cloud-starter-openfeign

由于 Feign 停止維護,咱們的項目中使用的是后者 OpenFeign。

1.2 快速使用 OpenFeign

在 cook-service 引入 OpenFeign 依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

cook-service 啟動類添加注解:@EnableFeignClients 開啟 OpenFeign 功能。

package com.zlcode.cook;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class CookServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(CookServiceApplication.class, args);
    }
}

編寫 OpenFeign 客戶端,基于 SpringMVC 注解來聲明遠程調(diào)用的信息。

在 cook 目錄下創(chuàng)建 api 目錄,在這個 api 目錄中創(chuàng)建 WaiterApi 接口。

package com.zlcode.cook.api;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "waiter-service", path = "/waiter")
public interface WaiterApi {
    @RequestMapping("/up/{content}")
    String up(@PathVariable("content") String content);
}

上述 @FeignClient 注解中的 value 表示注冊的服務(wù)名,用于服務(wù)發(fā)現(xiàn),F(xiàn)eign底層會使用 Spring Cloud Load Balance 進行負載均衡,如果使用了 Nacos 負載均衡策略則使用的是 Nacos 的負載均衡。path 表示統(tǒng)一接口前綴,與咱們的 WaiterController 對應(yīng)的。

WaiterController

package com.zlcode.waiter.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/waiter")
@Slf4j
public class WaiterController {
    @RequestMapping("/up/{content}")
    public String up(@PathVariable("content") String content) {
        log.info("正在執(zhí)行: " + content);
        return "執(zhí)行: " + content + "成功!";
    }
}

修改 CookController 的遠程方法調(diào)用代碼:

package com.zlcode.cook.controller;
import com.zlcode.cook.api.WaiterApi;
import jakarta.websocket.server.PathParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/cook")
public class CookController {
    @Autowired
    private WaiterApi waiterApi;
    @RequestMapping("/ok")
    public String ok(@PathParam("content")String content) {
        String resp = waiterApi.up(content);
        return "調(diào)用成功, 已收到 waiter 的響應(yīng): " + resp;
    }
}

重啟 cook-service,再去瀏覽器中訪問:http://127.0.0.1:8080/cook/up?content=給25桌上紅燒肉

1.3 接口返回的是自定義對象該怎么辦?

咱們例子中,waiter-service 的 waiter/up/ 接口返回值是 String,每個 Java 項目都可以用 String 這個對象,如果新增一個接口,獲取服務(wù)員信息呢?返回的是一個 WaiterInfo 對象,那么在 cook-service 調(diào)用方該如何接收呢?

其實方法很簡單,咱們先在 WatierController 新增一個 get-info 接口:

package com.zlcode.waiter.controller;
import com.zlcode.waiter.model.WaiterInfo;
import jakarta.websocket.server.PathParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/waiter")
@Slf4j
public class WaiterController {
    @RequestMapping("/up/{content}")
    public String up(@PathVariable("content") String content) {
        log.info("正在執(zhí)行: " + content);
        return "執(zhí)行: " + content + "成功!";
    }
    @RequestMapping("/get-info")
    public WaiterInfo getInfo(String name) {
        WaiterInfo waiterInfo = new WaiterInfo();
        waiterInfo.setWaiterId(1111);
        waiterInfo.setWaiterName(name);
        return waiterInfo;
    }
}

在 cook-service 的 WatierApi 接口中新增遠程調(diào)用 waiter-service 提供的 get-info 的接口:

此時發(fā)現(xiàn)咱們的 cook-service 項目中沒有 WaiterInfo 這個類,這也好辦,去 waiter-service 中把 WaiterInfo 類復(fù)制到 cook-service 的 model 目錄中。

package com.zlcode.cook.api;
import com.zlcode.cook.model.WaiterInfo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "waiter-service", path = "/waiter")
public interface WaiterApi {
    @RequestMapping("/up/{content}")
    String up(@PathVariable("content") String content);
    @RequestMapping("/get-info")
    WaiterInfo getInfo(@RequestParam("name") String name);
}

果然解決了這個問題,再來到 CookController 中新增接口去遠程調(diào)用 get-info 方法:

package com.zlcode.cook.controller;
import com.zlcode.cook.api.WaiterApi;
import com.zlcode.cook.model.WaiterInfo;
import jakarta.websocket.server.PathParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/cook")
public class CookController {
    @Autowired
    private WaiterApi waiterApi;
    @RequestMapping("/ok")
    public String ok(@PathParam("content")String content) {
        String resp = waiterApi.up(content);
        return "調(diào)用成功, 已收到 waiter 的響應(yīng): " + resp;
    }
    @RequestMapping("/get")
    public String get(@RequestParam("name")String name) {
        WaiterInfo waiterInfo = waiterApi.getInfo(name);
        return "調(diào)用成功, 已收到 waiter 的響應(yīng): " + waiterInfo;
    }
}

重啟 cook-service 和 waiter-service,在瀏覽器中訪問:http://127.0.0.1:8080/cook/get?name=張三

調(diào)用成功,拿到了 waiter-service get-info 接口返回的 WaiterInfo 對象。

但是咱們仔細想想這段代碼,在 cook-service 項目中存在 WaiterInfo 實體類,在 waiter-service 項目中也存在 WaiterInfo 實體類。那隨著業(yè)務(wù)的增多,這樣的冗余代碼也會越來越多。而且咱們的 WaiterAPI 和 WaiterController 的代碼也十分相似。

所以上述這樣的寫法是不行的,不是最佳的寫法,更好的辦法是把把 OpenFeign 抽離出來,作為一個獨立的模塊,服務(wù)方把提供的 API 都封裝到這個獨立的模塊中,供消費方使用。

1.4 OpenFeign 的最佳實踐

官方推薦的方式是繼承,但是企業(yè)中用的不多,咱們此處只介紹抽離的方式,就像 6.3 最后說的,把 OpenFeign 提取出來成為一個獨立的模塊即可,這個模塊由服務(wù)方去提供。

簡單來說,將 OpenFeign 的 Client 抽取為?個獨?的模塊,并把涉及到的實體類等都放在這個模塊中,打成?個 jar。消費方只需要依賴該 jar 包即可。

步驟如下:

創(chuàng)建一個 Model

引入依賴

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-loadbalancer</artifactId>
    </dependency>
</dependencies>

編寫 API

將 cook-service 的 WaiterApi 和 WatierInfo 直接復(fù)制進來:

將這個 waiter-service-api 打包成 jar 包,單擊 maven 選項中的 install:

將 cook-service 的 WaiterApi 和 WatierInfo 刪除掉,然后引入咱們自己打包的 waiter-service-api 依賴

<dependency>
    <groupId>org.example</groupId>
    <artifactId>waiter-service-api</artifactId>
    <version>1.0-SNAPSHOT</version>
    <scope>compile</scope>
</dependency>

在啟動類添加掃描路徑:

package com.zlcode.cook;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients(basePackages = "com.zlcode.api")
public class CookServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(CookServiceApplication.class, args);
    }
}

也可以指定需要加載的 Feign客戶端:

@EnableFeignClients(basePackageClasses = WaiterApi.class)
@EnableFeignClients(basePackages = "com.zlcode.api")

接著重新啟動 cook-service 項目,然后在瀏覽器中訪問:http://127.0.0.1:8080/cook/get?name=張三

這種更優(yōu)雅的遠程方法調(diào)用也就成功了!

1.5 部署時需要注意事項

由于當前項目中使用到了自己封裝的 jar 包,但是 maven 打包默認會從中央倉庫中去獲取,但是咱們的 waiter-service-api 是在本地,這就比較麻煩,目前有三種解決方案:

  • 將 waiter-service-api jar 包上傳到 maven 中央倉庫,但需要注冊申請,比較麻煩。
  • 搭建 maven 私服,上傳 jar 包到私服,也是較麻煩的,企業(yè)中比較推薦。
  • 從本地讀取 jar 包,這是在個人項目階段中比較推薦的。只需要在引入本地 jar 包的項目中修改 pom.xml 文件就 ok 了。

觀先獲取 waiter-service-api 執(zhí)行 install 后的本地 jar 包路徑(通過控制臺查看):

把之前引入的依賴替換成本地目錄(記得將 \ 換成 /):

<dependency>
    <groupId>org.example</groupId>
    <artifactId>waiter-service-api</artifactId>
    <version>1.0-SNAPSHOT</version>
    <scope>system</scope>
    <systemPath>
        C:/xxx/xxx/.m2/repository/org/example/waiter-service-api/1.0-SNAPSHOT/waiter-service-api-1.0-SNAPSHOT.jar
    </systemPath>
</dependency>

把 build 配置項換成:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <includeSystemScope>true</includeSystemScope>
            </configuration>
        </plugin>
    </plugins>
</build>

includeSystemScope 允許包括系統(tǒng)本地的 jar 包。

接下來就可以進行快樂的部署到 Linux 服務(wù)器啦,剩下部署的操作這里就不再贅述了。

到此這篇關(guān)于SpringCloud OpenFeign的使用的文章就介紹到這了,更多相關(guān)SpringCloud OpenFeign使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中實現(xiàn)定時任務(wù)的幾種方式

    SpringBoot中實現(xiàn)定時任務(wù)的幾種方式

    定時任務(wù)在我們項目開發(fā)中也是很重要的,對于某些場景必須要用定時任務(wù)?,如定時發(fā)送郵件啊,定時統(tǒng)計數(shù)據(jù)等,這篇文章主要講講項目中實現(xiàn)定時任務(wù)的幾種方式,需要的朋友可以參考下
    2023-05-05
  • 關(guān)于protected修飾符詳解-源于Cloneable接口

    關(guān)于protected修飾符詳解-源于Cloneable接口

    這篇文章主要介紹了protected修飾符詳解-源于Cloneable接口,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • java shiro實現(xiàn)退出登陸清空緩存

    java shiro實現(xiàn)退出登陸清空緩存

    本篇文章主要介紹了java shiro實現(xiàn)退出登陸清空緩存,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • Java中的StringBuilder()常見方法詳解

    Java中的StringBuilder()常見方法詳解

    StringBuilder是一個可變的字符序列,此類提供一個與 StringBuffer 兼容的 API,但不保證同步,這篇文章主要介紹了StringBuilder()常見方法,需要的朋友可以參考下
    2023-09-09
  • 深度解析Spring Bean生命周期的各個階段

    深度解析Spring Bean生命周期的各個階段

    本文將詳細梳理Spring Bean生命周期的各個階段,并通過代碼示例展示每個關(guān)鍵節(jié)點,本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-09-09
  • Java性能優(yōu)化實戰(zhàn)技巧與最佳實踐分享

    Java性能優(yōu)化實戰(zhàn)技巧與最佳實踐分享

    性能優(yōu)化是 Java 開發(fā)中永恒的話題,無論是高并發(fā)系統(tǒng)、響應(yīng)式服務(wù)、還是數(shù)據(jù)密集型處理程序,都離不開系統(tǒng)性、可驗證的性能調(diào)優(yōu)方法,本文從 JVM、代碼層、集合框架、多線程、IO、數(shù)據(jù)庫及工具鏈等多維度總結(jié) Java 性能優(yōu)化實戰(zhàn)技巧,需要的朋友可以參考下
    2025-12-12
  • java課程設(shè)計做一個多人聊天室(socket+多線程)

    java課程設(shè)計做一個多人聊天室(socket+多線程)

    這篇文章主要介紹了我的java課程設(shè)計一個多人聊天室(socket+多線程)本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08
  • 新手入門學習Spring Freemarker教程解析

    新手入門學習Spring Freemarker教程解析

    這篇文章主要介紹了新手入門學習Freemarker教程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-10-10
  • java中Scanner.next()和Scanner.nextLine的區(qū)別圖文詳解

    java中Scanner.next()和Scanner.nextLine的區(qū)別圖文詳解

    使用java語言編程,最常用的輸入就是使用Scanner了,它的構(gòu)造很簡單,這篇文章主要給大家介紹了關(guān)于java中Scanner.next()和Scanner.nextLine區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2024-02-02
  • Java中的匿名對象定義與用法實例分析

    Java中的匿名對象定義與用法實例分析

    這篇文章主要介紹了Java中的匿名對象定義與用法,結(jié)合實例形式分析了java匿名對象的概念、原理、定義與相關(guān)使用注意事項,需要的朋友可以參考下
    2019-08-08

最新評論

龙井市| 镇远县| 东城区| 双城市| 广州市| 信阳市| 广水市| 安泽县| 慈利县| 永定县| 特克斯县| 石阡县| 松原市| 交口县| 突泉县| 桑植县| 阿合奇县| 共和县| 礼泉县| 安达市| 桂阳县| 永平县| 宣城市| 阿鲁科尔沁旗| 永定县| 乌审旗| 额济纳旗| 如东县| 娄烦县| 金寨县| 银川市| 太白县| 临颍县| 云林县| 泰来县| 当雄县| 兰溪市| 中阳县| 上思县| 巴里| 北安市|