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

Spring中OpenFeign的使用方法最佳實(shí)踐

 更新時間:2025年02月13日 08:28:26   作者:LileSily  
這篇文章主要介紹了Spring中OpenFeign使用的相關(guān)資料,OpenFeign是一個聲明式的WebService客戶端,簡化了微服務(wù)之間的調(diào)用,類似于Controller調(diào)用Service,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

1. RestTemplate存在的問題

觀察我們之前遠(yuǎn)程調(diào)用的代碼

public OrderInfo selectOrder(Integer id){
    OrderInfo orderInfo = orderMapper.selectOrderById(id);
    //把獲取到的服務(wù)URL拼接到遠(yuǎn)程調(diào)用的URL中
    String url = "http://product-service/product/select?id=" + orderInfo.getProductId();
    ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
    orderInfo.setProductInfo(productInfo);
    return orderInfo;
}

雖然說RestTemplate對HTTP封裝之后,已經(jīng)比直接使用HTTP Client方便很多,但是還是存在一些問題的.

  • 需要拼接URL,靈活性高,但是封裝臃腫,URL復(fù)雜的時候,容易出錯.
  • 代碼可讀性差,風(fēng)格不統(tǒng)一.

微服務(wù)之間的通行主要有兩種方式,一種是RPC,一種是HTTP.在SpringCloud中,默認(rèn)是使用HTTP進(jìn)行通信的,最常用的實(shí)現(xiàn)形式有兩種:

  • RestTemplate
  • OpenFeign

接下來我們就來詳細(xì)介紹一下OpenFeign.

2. OpenFeign介紹

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

2.1 引入依賴

首先我們需要在服務(wù)調(diào)用方(order-service)中引入依賴

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

2.2 添加注解

在order-service的啟動類添加注解,@EnableFeignClients,開啟OpenFeign的功能.

@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class,args);
    }
}

2.3 編寫OpenFeign客戶端

在調(diào)用其他服務(wù)的客戶端之下,編寫API調(diào)用接口,基于SpringMVC的注解來聲明遠(yuǎn)程調(diào)用的信息.

@FeignClient(name = "product-service")
public interface ProductApi {
    @RequestMapping("/product/select")
    ProductInfo getProductInfo(@RequestParam("id")Integer id);
}

[注意]:在接口的參數(shù)前面必須使用@RequestParam加上所調(diào)用服務(wù)接口的對應(yīng)參數(shù),否則參數(shù)無法傳入,就相當(dāng)于在請求的后面加上了?參數(shù)=xxx.

也可以把該服務(wù)的接口的統(tǒng)一前綴(放在類上的@RequestMapping)統(tǒng)一放到FeignClient注解的Path參數(shù)中.

@FeignClient(name = "product-service",path = "/product")
public interface ProductApi {
    @RequestMapping("/select")
    ProductInfo getProductInfo(@RequestParam("id")Integer id);
}

@FeignClient注解作用在接口上,參數(shù)說明:

  • name/value: 指定OpenFeign的名稱,也就是被調(diào)用的微服務(wù)的名稱,用于服務(wù)發(fā)現(xiàn),Feign底層會使用SpringLoadBalance進(jìn)行負(fù)載均衡.
    當(dāng)然也可以使用URL屬性指定一個具體的URL.
  • Path: 定義當(dāng)前FeignClient的統(tǒng)一前綴,一般是被調(diào)用方Controller層的類注解.

2.4 遠(yuǎn)程調(diào)用

修改遠(yuǎn)程調(diào)用方法

@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private ProductApi api;
    //設(shè)置原子類
    public OrderInfo selectOrder(Integer id){
        OrderInfo orderInfo = orderMapper.selectOrderById(id);
        //把獲取到的服務(wù)URL拼接到遠(yuǎn)程調(diào)用的URL中
        Integer productId = orderInfo.getProductId();
        ProductInfo productInfo = api.getProductInfo(productId);
        orderInfo.setProductInfo(productInfo);
        return orderInfo;
    }
}

2.5 測試

啟動服務(wù).訪問接口,測試遠(yuǎn)程調(diào)用.

3. OpenFeign參數(shù)傳遞

3.1 傳遞單個參數(shù)

我們上面2.4的例子就是單個參數(shù)的調(diào)用.下面我們再來舉一個例子

  • 服務(wù)提供方product-service
@RestController
@RequestMapping("/product")
public class ProductController {
    @RequestMapping("/p1")
    public String p1(Integer id){
        return "接收到參數(shù)"+id;
    }
}
  • FeginClient
@FeignClient(value = "product-service")
public interface ProductApi {
    @RequestMapping("/product/p1")
    String p1(@RequestParam("id") Integer id);
}

和我們上面提到的一樣,@RequestParam是用來做參數(shù)綁定的,不能省略.

3. order-service

@RequestMapping("/order")
@RestController
public class OrderController {
    @Autowired
    private ProductApi api;
    @RequestMapping("/p1")
    public String p1(Integer id){
        return api.p1(id);
    }
}

遠(yuǎn)程測試調(diào)用:GET http://127.0.0.1:8080/order/p1?id=1

3.2 傳遞多個參數(shù)

使用多個@RequestParam進(jìn)行參數(shù)綁定即可

  • 服務(wù)提供方product-service
@RestController
@RequestMapping("/product")
public class ProductController {
    @RequestMapping("/p2")
    public String p2(Integer id1,Integer id2){
        return "接收到參數(shù)1:" + id1 + ",接收到參數(shù)2:" + id2;
    }
}
  • FeignClient
@FeignClient(value = "product-service")
public interface ProductApi {
    @RequestMapping("/product/p2")
    String p2(@RequestParam("id1") Integer p1,@RequestParam("id2") Integer p2);
}
  • 服務(wù)消費(fèi)方order-service
@RequestMapping("/order")
@RestController
public class OrderController {
    @Autowired
    private ProductApi api;
    @RequestMapping("/p2")
    public String p2(Integer p1,Integer p2){
        return api.p2(p1,p2);
    }
}

調(diào)用接口進(jìn)行測試:GET http://127.0.0.1:8080/order/p2?p1=1&p2=2

4.3 傳遞對象

  • 服務(wù)提供方product-service
@RequestMapping("/p3")
public String p3(ProductInfo productInfo){
    return "接收到對象:" + productInfo;
}
  • Feign
@RequestMapping("/product/p3")
String p3(@SpringQueryMap ProductInfo productInfo);

其中@SpringQueryMap注解表示的是:可以方便地將一個對象的屬性作為請求的查詢參數(shù)添加到請求的 URL中,避免了手動構(gòu)建查詢參數(shù)字符串(如json)的繁瑣過程.

3. order-service

@RequestMapping("/p3")
public String p3(ProductInfo productInfo){
    return api.p3(productInfo);
}

測試遠(yuǎn)程調(diào)用:GET http://127.0.0.1:8080/order/p3?id=5&productName=zhangsan

3.4 傳遞Json

和我們之前學(xué)習(xí)SpringBoot的時候一樣,同樣是使用@RequestBody注解進(jìn)行綁定.

注意由于數(shù)據(jù)在服務(wù)之間一直是按照J(rèn)son格式傳遞的,所以服務(wù)方,服務(wù)調(diào)用方,FeignClient的參數(shù)上都需要加上注解.

  • 服務(wù)提供方product-service
@RequestMapping("/p4")
public String p4(@RequestBody ProductInfo productInfo){
    return "接收到對象:" + productInfo;
}
  • FeignClient
@RequestMapping("/product/p4")
String p4(@RequestBody ProductInfo productInfo);
  • 服務(wù)消費(fèi)方order-service
@RequestMapping("/p4")
public String p4(@RequestBody ProductInfo productInfo){
    return api.p4(productInfo);
}

測試遠(yuǎn)程調(diào)用:http://127.0.0.1:8080/order/p4

4. 最佳實(shí)踐

通過觀察,我們也能看出來,Feign的客戶端與服務(wù)提供者的controller代碼非常相似.
Feign客戶端:

@FeignClient(value = "product-service")
public interface ProductApi {
    @RequestMapping("/product/p1")
    String p1(@RequestParam("id") Integer id);
}

服務(wù)提供方Controller

@RestController
@RequestMapping("/product")
public class ProductController {
    @RequestMapping("/p1")
    public String p1(Integer id){
        return "接收到參數(shù)"+id;
    }
}

有沒有一種方法可以簡化這種寫法呢?

4.1 Feign繼承方式

Feign支持繼承的方式,我們可以把一些常見的操作封裝到接口里.

我可以定義好一個接口,服務(wù)提供方實(shí)現(xiàn)這個接口,服務(wù)消費(fèi)方編寫Feign接口的時候,直接繼承這個接口.

接口可以放在一個公共的jar包中,供服務(wù)提供方和服務(wù)消費(fèi)方使用.

  • 新建一個模塊

  • 引入依賴
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>
  • 編寫接口
    復(fù)制ProductInfo類和ProductApi到product-api模塊中.把ProductApi改名為ProductInterface

  • 打jar包,并安裝到本地Maven倉庫


    點(diǎn)擊install.該模塊就會被安裝到本地的Maven倉庫.


    由于jar包中已經(jīng)有了ProductInfo類,所以我們就可以把product-service和order-service的ProductInfo類注掉了.
  • 服務(wù)提供方
    需要先在服務(wù)方中引入對應(yīng)模塊的依賴.
<dependency>
    <groupId>org.example</groupId>
    <artifactId>product-api</artifactId>
    <version>1.0-SNAPSHOT</version>
    <scope>compile</scope>
</dependency>

服務(wù)方product-service直接實(shí)現(xiàn)接口ProductInterface.

@RestController
@RequestMapping("/product")
public class ProductController implements ProductInterface {
    @Autowired
    private ProductService productService;
    @RequestMapping("/select")
    public ProductInfo getProductInfo(Integer id){
        return productService.selectById(id);
    }
    @RequestMapping("/p1")
    public String p1(Integer id){
        return "接收到參數(shù)"+id;
    }
    @RequestMapping("/p2")
    public String p2(Integer id1,Integer id2){
        return "接收到參數(shù)1:" + id1 + ",接收到參數(shù)2:" + id2;
    }
    @RequestMapping("/p3")
    public String p3(ProductInfo productInfo){
        return "接收到對象:" + productInfo;
    }
    @RequestMapping("/p4")
    public String p4(@RequestBody ProductInfo productInfo){
        return "接收到對象:" + productInfo;
    }
}
  • 服務(wù)消費(fèi)方
    同樣,首先先添加依賴.
    之后讓FeignClient繼承ProductInterface
@FeignClient(value = "product-service")
public interface ProductApi extends ProductInterface {

}

注意在上述步驟中,把ProductInfo類引入包的路徑全部改為之前打包的product-api模塊下ProductInfo類的路徑.

  • 測試接口
    http://127.0.0.1:8080/order/select?id=1

4.2 Feign抽取方式

官方推薦Feign的使用方式為繼承的方式,但是企業(yè)開發(fā)中,更多是把Feign接口抽取為?個獨(dú)立的模塊(做法和繼承相似,但理念不同).
操作方法:
將Feign的Client抽取為?個獨(dú)立的模塊,并把涉及到的實(shí)體類等都放在這個模塊中,打成?個Jar.服務(wù)消費(fèi)方只需要依賴該Jar包即可.這種方式在企業(yè)中比較常見,Jar包通常由服務(wù)提供方來實(shí)現(xiàn).
前4步和前面繼承的方式一樣.只不過接口ProductApi在復(fù)制到新模塊的時候不用修改名字

  • 服務(wù)消費(fèi)方使用product-api
    首先引入依賴,之后把該模塊中原有的ProductApi接口注掉.
<dependency>
	<groupId>org.example</groupId>
	<artifactId>product-api</artifactId>
	<version>1.0-SNAPSHOT</version>
</dependency>

之后指定掃描類
在啟動類中添加需要加載的Feign客戶端.

@SpringBootApplication
@EnableFeignClients(clients = ProductApi.class)
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class,args);
    }
}
  • 測試
    遠(yuǎn)程調(diào)用接口http://127.0.0.1:8080/order/select?id=1

總結(jié) 

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

相關(guān)文章

最新評論

靖江市| 马山县| 玉山县| 河间市| 永福县| 文登市| 七台河市| 丹棱县| 龙里县| 东辽县| 贵州省| 庆云县| 岑巩县| 融水| 莱州市| 牙克石市| 汶川县| 大同市| 博野县| 潢川县| 和平县| 双辽市| 军事| 朝阳市| 上犹县| 巢湖市| 建平县| 武城县| 准格尔旗| 肥西县| 聊城市| 桃源县| 襄城县| 武强县| 余庆县| 崇左市| 漠河县| 田东县| 丰宁| 广宗县| 蒲江县|