OpenFeign元件
- `微服務間通信的方式??`
-
- 1.基于Http應用層協定
- 2.基于RPC傳輸層協定
- `OpenFeign服務間通信時參數傳遞`
-
- 1.基本資料類型
- 2.傳遞對象類型
- 3.傳遞數組和集合類型
微服務間通信的方式??
微服務間通信的方式??
服務間通信的方式主要有以下兩種:
1.基于Http應用層協定
特點
1.使用http rest方式,使用json作為資料交換的
2.效率較低,但是耦合度低(耦合度低意味着如果不同服務使用不同的技術架構進行開發後,進行通信的成本低)
典型的實作
1.RestTemplate
缺點:
1.服務調用使路徑寫死,耦合度高
2.要想實作負載均衡,必須得結合Ribbon元件,造成備援代碼
2.OpenFeign(推薦)
特點:
1.OpenFeign元件是spring團隊基于netflix的Feign元件進行封裝和擴充形成的自己的一個項目,它是一個僞HttpClient;
OpenFeign是一個僞HTTP用戶端,底層還是RestTemplate,是對RestTemplate的封裝
2.OpenFeign支援可插拔的編碼器和解碼器。
比如幫我們預設實作json和其他資料類型的裝換
3.OpenFeign預設內建了Ribbon
預設實作了負載均衡的效果,不需要我們再像RestTemlate那樣,利用ribbon編寫實作負載均衡的相關代碼;
并且springcloud為feign添加了
的支援。
springmvc注解
4.使用友善,代碼量少
使用時隻需要添加幾個注解,編寫一個接口類即可,耦合度低
2.基于RPC傳輸層協定
特點
1.使用的是傳輸層的協定,以二進制方式傳遞資料
2.效率高,但是耦合度高,如果不同服務使用不同的技術架構進行開發後,進行通信的成本高
典型的RPC架構:Dubbo
總結:`在springcloud中服務間調用方式主要是使用 http restful方式進行服務間調用
OpenFeign服務間通信時參數傳遞
OpenFeign服務間通信時參數傳遞
1.基本資料類型
GoodsClient接口
@FeignClient(value = "GOODS")
public interface GoodsClient {
/*
* 注意:這裡的方法需要保證傳回類型,形參,請求路徑一緻
* 方法名可以與被調用的服務名不同
*
* feign預設給我們實作了負載均衡!!
* */
@GetMapping("/test")
String test(String name,Integer age);
}
商品服務controller
@GetMapping("/test")
public String test(String name,Integer age){
log.info("name:{},age:{}",name,age);
return name + age;
}
CategoryController調用商品服務的test方法
@GetMapping
public String testService(){
String test = goodsClient.test("jw", 20);
return test;
}
啟動報錯顯示太多參數
Caused by: java.lang.IllegalStateException: Method has too many Body parameters: public abstract java.lang.String com.jw.feignclient.GoodsClient.test(java.lang.String,java.lang.Integer)
原因是:
我們知道通過QueryString傳遞有兩種方式,一種是
/test?name=jw&age=20的形式
另一種是rest的方式,直接把參數寫在路徑中
/test/jw/20
由于OpenFeign是僞用戶端,底層在調用服務時還是基于RestTemplate,當我們通過GoodsClient調用test服務是,GoodsClient會把接收的參數傳遞給RestTemplate進行封裝;此時RestTemplate不知道該基于哪種方式進行封裝,是以會報錯;
如果我們隻寫一個參數,那麼預設就是?name=xx的形式
如果有多個參數就需要我們用注解顯示聲明
@RequestParams
如果是想以
/test?name=xxx&age=xxx
的形式傳遞參數,那麼使@RequestParams;
@FeignClient(value = "GOODS")
public interface GoodsClient {
/*
* 注意:這裡的方法需要保證傳回類型,形參,請求路徑一緻
* 方法名可以與被調用的服務名不同
*
* feign預設給我們實作了負載均衡!!
* */
@GetMapping("/test")
String test(@RequestParam String name,@RequestParam Integer age);
}
注意:如果我們@RequestParam指派,被調用方需要一緻
@GetMapping("/test")
String test(@RequestParam("aa") String name,@RequestParam("bb") Integer age);
//商品服務
@GetMapping("/test")
public String test(String aa,Integer bb){
log.info("name:{},age:{}",aa,bb);
return aa + bb;
}
@GetMapping("/test")
public String test(@RequestParam("aa") String name,@RequestParam("bb") Integer age){
log.info("name:{},age:{}",name,age);
return name + age;
}
@PathVariable
如果是想以
/test/jw/20
形式傳遞參數,那麼使用@PathVariable
@FeignClient(value = "GOODS")
public interface GoodsClient {
/*
* 注意:這裡的方法需要保證傳回類型,形參,請求路徑一緻
* 方法名可以與被調用的服務名不同
*
* feign預設給我們實作了負載均衡!!
* */
@GetMapping("/test1/{name}/{age}")
String test1(@PathVariable("name") String name, @PathVariable("age") Integer age);
}
//商品服務controller
@GetMapping("/test1/{name}/{age}")
public String test1(@PathVariable("name")String name,@PathVariable("age") Integer age){
log.info("name:{},age:{}",name,age);
return name+age;
}
//**CategoryController調用商品服務的test1方法**
@GetMapping
public String testService(){
String test = goodsClient.test1("jw", 20);
return test;
}
2.傳遞對象類型
使用
@RequestBody
注解會把對象以aplication/json的形式傳參,被調用的服務也需要加上@RequestBody該注解,把收到的json轉成對應的對象
//categoryController
@GetMapping
public String testService(){
//String test = goodsClient.test1("jw", 20);
goodsClient.save(new Goods(1,"aa",22.12,new Date()));
return null;
}
//接口
@FeignClient(value = "GOODS")
public interface GoodsClient {
/*
* 注意:這裡的方法需要保證傳回類型,形參,請求路徑一緻
* 方法名可以與被調用的服務名不同
*
* feign預設給我們實作了負載均衡!!
* */
@PostMapping("/savegoods")
void save(@RequestBody Goods goods);
}
//GoodsController
@PostMapping("/savegoods")
public void save(@RequestBody Goods goods){
log.info("goods:{}",goods);
}
3.傳遞數組和集合類型
**數組類型使用@RequestParam會把ids數組拼裝成
/test3/?ids=1&ids=2&ids=3
的形式
@FeignClient(value = "GOODS")
public interface GoodsClient {
@GetMapping("/test3")
void test3(@RequestParam("ids") String[] ids);
}
==================================
//goodsController
@GetMapping("/test3")
public void test3( String[] ids){
log.info("ids:{}",ids);
}
集合類型
springMVC中get方式是不能用集合作參數的
比如以
/test4/?ids=1&ids=2&ids=3
,接收不到
//不行
@GetMapping("/test4")
public void test4(ArrayList<String> ids){
}
如果硬要接收集合,那麼需要把集合作為類的屬性
@GetMapping("/test3")
public void test3( GoodsVO vo){
log.info("ids:{}",ids);
}
class ProductVO{
private ArrayList<String> ids;
public ArrayList<String> getIds() {
return ids;
}
public void setIds(ArrayList<String> ids) {
this.ids = ids;
}
}
此時在FeignClient中還是同數組一樣,因為@RequestParam會把接收到的ids拼接成/test4/?ids=1&ids=2&ids=3,在GoodController接收時,就會去Goodvo中找到ids進行指派
@FeignClient(value = "GOODS")
public interface GoodsClient {
@GetMapping("/test4")
void test3(@RequestParam("ids") String[] ids);
}
注意:這裡是GET方式需要接收一個List集合
如果是POST方式直接加上@RequestBody注解以json方式傳遞即可