欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringCloud  OpenFeign的使用舉例詳解

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

1. OpenFeign

1.1 OpenFeign 的介紹

先來(lái)看看咱們之前寫(xiě)的遠(yuǎn)程方法調(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;
}

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

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

在 SpringCloud 中,默認(rèn)使用的是 HTTP 來(lái)進(jìn)行微服務(wù)的通信,最常用的實(shí)現(xiàn)有兩種:

  • RestTemplate
  • OpenFeign

RestTemplate 咱們已經(jīng)見(jiàn)過(guò)了,接下來(lái)就學(xué)習(xí)下 OpenFeign,這是一種更優(yōu)雅的遠(yuǎn)程方法調(diào)用的形式。

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

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

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

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

由于 Feign 停止維護(hù),咱們的項(xiàng)目中使用的是后者 OpenFeign。

1.2 快速使用 OpenFeign

在 cook-service 引入 OpenFeign 依賴(lài)

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

cook-service 啟動(dòng)類(lèi)添加注解:@EnableFeignClients 開(kāi)啟 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);
    }
}

編寫(xiě) OpenFeign 客戶(hù)端,基于 SpringMVC 注解來(lái)聲明遠(yuǎn)程調(diào)用的信息。

在 cook 目錄下創(chuàng)建 api 目錄,在這個(gè) 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 表示注冊(cè)的服務(wù)名,用于服務(wù)發(fā)現(xiàn),F(xiàn)eign底層會(huì)使用 Spring Cloud Load Balance 進(jìn)行負(fù)載均衡,如果使用了 Nacos 負(fù)載均衡策略則使用的是 Nacos 的負(fù)載均衡。path 表示統(tǒng)一接口前綴,與咱們的 WaiterController 對(duì)應(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 的遠(yuǎn)程方法調(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,再去瀏覽器中訪問(wèn):http://127.0.0.1:8080/cook/up?content=給25桌上紅燒肉

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

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

其實(shí)方法很簡(jiǎn)單,咱們先在 WatierController 新增一個(gè) 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 接口中新增遠(yuǎn)程調(diào)用 waiter-service 提供的 get-info 的接口:

此時(shí)發(fā)現(xiàn)咱們的 cook-service 項(xiàng)目中沒(méi)有 WaiterInfo 這個(gè)類(lèi),這也好辦,去 waiter-service 中把 WaiterInfo 類(lèi)復(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);
}

果然解決了這個(gè)問(wèn)題,再來(lái)到 CookController 中新增接口去遠(yuǎn)程調(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,在瀏覽器中訪問(wèn):http://127.0.0.1:8080/cook/get?name=張三

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

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

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

1.4 OpenFeign 的最佳實(shí)踐

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

簡(jiǎn)單來(lái)說(shuō),將 OpenFeign 的 Client 抽取為?個(gè)獨(dú)?的模塊,并把涉及到的實(shí)體類(lèi)等都放在這個(gè)模塊中,打成?個(gè) jar。消費(fèi)方只需要依賴(lài)該 jar 包即可。

步驟如下:

創(chuàng)建一個(gè) Model

引入依賴(lài)

<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>

編寫(xiě) API

將 cook-service 的 WaiterApi 和 WatierInfo 直接復(fù)制進(jìn)來(lái):

將這個(gè) waiter-service-api 打包成 jar 包,單擊 maven 選項(xiàng)中的 install:

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

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

在啟動(dòng)類(lèi)添加掃描路徑:

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客戶(hù)端:

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

接著重新啟動(dòng) cook-service 項(xiàng)目,然后在瀏覽器中訪問(wèn):http://127.0.0.1:8080/cook/get?name=張三

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

1.5 部署時(shí)需要注意事項(xiàng)

由于當(dāng)前項(xiàng)目中使用到了自己封裝的 jar 包,但是 maven 打包默認(rèn)會(huì)從中央倉(cāng)庫(kù)中去獲取,但是咱們的 waiter-service-api 是在本地,這就比較麻煩,目前有三種解決方案:

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

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

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

<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 配置項(xiàng)換成:

<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 包。

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

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

相關(guān)文章

最新評(píng)論