詳解SpringCloud-OpenFeign組件的使用
思考: 使用RestTemplate+ribbon已經(jīng)可以完成服務(wù)間的調(diào)用,為什么還要使用feign?
String restTemplateForObject = restTemplate.getForObject("http://服務(wù)名/url?參數(shù)" + name, String.class);
存在問題:
1.每次調(diào)用服務(wù)都需要寫這些代碼,存在大量的代碼冗余
2.服務(wù)地址如果修改,維護(hù)成本增高
3.使用時不夠靈活
說明
https://cloud.spring.io/spring-cloud-openfeign/reference/html/
Feign是一個聲明式的偽Http客戶端,它使得寫Http客戶端變得更簡單。使用Feign,只需要創(chuàng)建一個接口并注解。它具有可插拔的注解特性(可以使用springmvc的注解),可使用Feign 注解和JAX-RS注解。Feign支持可插拔的編碼器和解碼器。Feign默認(rèn)集成了Ribbon,默認(rèn)實(shí)現(xiàn)了負(fù)載均衡的效果并且springcloud為feign添加了springmvc注解的支持。
1.openFeign 服務(wù)調(diào)用
還是在上一個項(xiàng)目的基礎(chǔ)之上,在users項(xiàng)目中
1.服務(wù)調(diào)用方法引入依賴OpenFeign依賴
<!--Open Feign依賴--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
2.入口類加入注解開啟OpenFeign支持
@SpringBootApplication @EnableFeignClients //開啟openfeign支持 public class Users9999Application { public static void main(String[] args) { SpringApplication.run(Users9999Application.class, args); } }
3.創(chuàng)建一個客戶端調(diào)用接口
// 此時的product項(xiàng)目中的方法 @RestController @Slf4j public class ProductController { @Value("${server.port}") private int port; @GetMapping("/product/findAll") public Map<String, Object> findAll(){ log.info("商品服務(wù)調(diào)用成功,當(dāng)前的服務(wù)端口:[{}]",port); HashMap<String, Object> map = new HashMap<>(); map.put("msg","服務(wù)調(diào)用成功,服務(wù)提供的端口為:"+port); map.put("status",true); return map; } } //-------------------------------------------------------------------- package com.md.clients; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; /** * @author md * @Desc 調(diào)用商品服務(wù)的組件 * @date 2020/12/9 15:30 */ // 指定當(dāng)前的接口是openfeign組件,value是調(diào)用的服務(wù)名 @FeignClient("products") public interface ProductClient { @GetMapping("/product/findAll") String findAll(); }
4.使用feignClient客戶端對象調(diào)用服務(wù)
@RestController @Slf4j public class UserController { //注入客戶端對象 @Autowired private ProductClient productClient; @GetMapping("/user/findAllFeignClient") public String findAllFeignClient(){ log.info("通過使用OpenFeign組件調(diào)用商品服務(wù)..."); String msg = productClient.findAll(); return msg; } }
5.訪問并測試服務(wù)http://localhost:9999/user/findAllFeignClient
2.調(diào)用服務(wù)并傳參
服務(wù)和服務(wù)之間通信,不僅僅是調(diào)用,往往在調(diào)用過程中還伴隨著參數(shù)傳遞,接下來重點(diǎn)來看看OpenFeign在調(diào)用服務(wù)時如何傳遞參數(shù)
3.GET方式調(diào)用服務(wù)傳遞參數(shù)
- 在商品服務(wù)中加入需要傳遞參數(shù)的服務(wù)方法來進(jìn)行測試
- 在用戶服務(wù)中進(jìn)行調(diào)用商品服務(wù)中需要傳遞參數(shù)的服務(wù)方法進(jìn)行測試
1.商品服務(wù)中添加如下方法
@GetMapping("/product/findOne") public Map<String,Object> findOne(String productId){ log.info("商品服務(wù)查詢商品信息調(diào)用成功,當(dāng)前服務(wù)端口:[{}]",port); log.info("當(dāng)前接收商品信息的id:[{}]",productId); Map<String, Object> map = new HashMap<String,Object>(); map.put("msg","商品服務(wù)查詢商品信息調(diào)用成功,當(dāng)前服務(wù)端口: "+port); map.put("status",true); map.put("productId",productId); return map; }
2.用戶服務(wù)中在product客戶端中聲明方法
// @FeignClient("products") public interface ProductClient { @GetMapping("/product/findOne") Map<String, Object> findOne(@RequestParam("productId") String productId); }
注意:使用openfeign的get方式傳遞參數(shù),參數(shù)變量必須通過@RequestParam注解進(jìn)行修飾
3.用戶服務(wù)中調(diào)用并傳遞參數(shù)
// //注入客戶端對象 @RestController @Slf4j public class UserController { @Autowired private ProductClient productClient; @GetMapping("/user/findOne") public Map<String, Object> findOne(String productId){ log.info("用來測試Openfiegn的GET方式參數(shù)傳遞"); Map<String, Object> msg = productClient.findOne(productId); log.info("調(diào)用返回信息:[{}]",msg); return msg; } }
4.測試訪問
4.post方式調(diào)用服務(wù)傳遞參數(shù)
- 在商品服務(wù)中加入需要傳遞參數(shù)的服務(wù)方法來進(jìn)行測試
- 在用戶服務(wù)中進(jìn)行調(diào)用商品服務(wù)中需要傳遞參數(shù)的服務(wù)方法進(jìn)行測試
1.商品服務(wù)加入post方式請求并接受name
@PostMapping("/product/save") public Map<String,Object> save(String name){ log.info("商品服務(wù)保存商品調(diào)用成功,當(dāng)前服務(wù)端口:[{}]",port); log.info("當(dāng)前接收商品名稱:[{}]",name); Map<String, Object> map = new HashMap<String,Object>(); map.put("msg","商品查詢服務(wù)完成當(dāng)前服務(wù)端口: "+port); map.put("status",true); map.put("name",name); return map; }
2.用戶服務(wù)中在product客戶端中聲明方法
//value屬性用來指定:調(diào)用服務(wù)名稱 @FeignClient("products") public interface ProductClient { @PostMapping("/product/save") String save(@RequestParam("name") String name); }
3.用戶服務(wù)中調(diào)用并傳遞參數(shù)
@Autowired private ProductClient productClient; @PostMapping("/user/save") public Map<String, Object> save(String productName){ log.info("接收到的商品信息名稱:[{}]",productName); Map<String, Object> map = productClient.save(productName); log.info("調(diào)用成功返回結(jié)果: "+map); return map; }
4.測試訪問
5.傳遞對象類型參數(shù)
- 商品服務(wù)定義對象
- 商品服務(wù)定義對象接收方法
- 用戶服務(wù)調(diào)用商品服務(wù)定義對象參數(shù)方法進(jìn)行參數(shù)傳遞
//1.商品服務(wù)定義對象 @Data public class Product { private Integer id; private String name; private Date bir; }
//2.商品服務(wù)定義接收對象的方法 @PostMapping("/product/saveProduct") public Map<String,Object> saveProduct(@RequestBody Product product){ log.info("商品服務(wù)保存商品信息調(diào)用成功,當(dāng)前服務(wù)端口:[{}]",port); log.info("當(dāng)前接收商品名稱:[{}]",product); Map<String, Object> map = new HashMap<String,Object>(); map.put("msg","商品服務(wù)查詢商品信息調(diào)用成功,當(dāng)前服務(wù)端口: "+port); map.put("status",true); map.put("product",product); return map; }
//3.將商品對象復(fù)制到用戶服務(wù)中 // 先階段先這樣用著 //4.用戶服務(wù)中在product客戶端中聲明方法 @FeignClient("products") public interface ProductClient { @PostMapping("/product/saveProduct") String saveProduct(@RequestBody Product product); } //注意:服務(wù)提供方和調(diào)用方一定要加入@RequestBody注解
注意:服務(wù)提供方和調(diào)用方一定要加入@RequestBody注解
// 5.在用戶服務(wù)中調(diào)用保存商品信息服務(wù) //注入客戶端對象 @Autowired private ProductClient productClient; @PostMapping("/user/saveProduct") public Map<String, Object> saveProduct(Product product){ log.info("接收到的商品信息:[{}]",product); Map<String, Object> map = productClient.saveProduct(product); log.info("調(diào)用成功返回結(jié)果: "+map); return map; }
測試
5.OpenFeign超時設(shè)置
1.超時說明默認(rèn)情況下,openFiegn在進(jìn)行服務(wù)調(diào)用時,要求服務(wù)提供方處理業(yè)務(wù)邏輯時間必須在1S內(nèi)返回,如果超過1S沒有返回則OpenFeign會直接報(bào)錯,不會等待服務(wù)執(zhí)行,但是往往在處理復(fù)雜業(yè)務(wù)邏輯是可能會超過1S,因此需要修改OpenFeign的默認(rèn)服務(wù)調(diào)用超時時間。
2.模擬超時服務(wù)提供方加入線程等待阻塞
3.進(jìn)行客戶端調(diào)用
4.修改OpenFeign默認(rèn)超時時間
# 這里的PRODUCTS使用的是大寫的方法 feign.client.config.PRODUCTS.connectTimeout=5000 #配置指定服務(wù)連接超時 feign.client.config.PRODUCTS.readTimeout=5000 #配置指定服務(wù)等待超時 #feign.client.config.default.connectTimeout=5000 #配置所有服務(wù)連接超時 #feign.client.config.default.readTimeout=5000 #配置所有服務(wù)等待超時
6.OpenFeign調(diào)用詳細(xì)日志展示
0.說明
- 往往在服務(wù)調(diào)用時我們需要詳細(xì)展示feign的日志,默認(rèn)feign在調(diào)用是并不是最詳細(xì)日志輸出,因此在調(diào)試程序時應(yīng)該開啟feign的詳細(xì)日志展示。feign對日志的處理非常靈活可為每個feign客戶端指定日志記錄策略,每個客戶端都會創(chuàng)建一個logger默認(rèn)情況下logger的名稱是feign的全限定名需要注意的是,feign日志的打印只會DEBUG級別做出響應(yīng)。
- 我們可以為feign客戶端配置各自的logger.level對象,告訴feign記錄那些日志logger.lever有以下的幾種值
NONE 不記錄任何日志
BASIC 僅僅記錄請求方法,url,響應(yīng)狀態(tài)代碼及執(zhí)行時間HEADERS 記錄Basic級別的基礎(chǔ)上,記錄請求和響應(yīng)的header
FULL 記錄請求和響應(yīng)的header,body和元數(shù)據(jù)
1.開啟日志展示
# 這里的PRODUCTS使用的是大寫的方法 feign.client.config.PRODUCTS.loggerLevel=full #開啟指定服務(wù)日志展示 #feign.client.config.default.loggerLevel=full #全局開啟服務(wù)日志展示 logging.level.com.baizhi.feignclients=debug #指定feign調(diào)用客戶端對象所在包,必須是debug級別
2.測試服務(wù)調(diào)用查看日志
到此這篇關(guān)于SpringCloud-OpenFeign組件的使用的文章就介紹到這了,更多相關(guān)SpringCloud-OpenFeign組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java中synchronized Lock(本地同步)鎖的8種情況
本文主要介紹了java中synchronized Lock(本地同步)鎖的8種情況,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09java 并發(fā)編程之共享變量的實(shí)現(xiàn)方法
這篇文章主要介紹了java 并發(fā)編程之共享變量的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09mybatis根據(jù)表逆向自動化生成代碼的實(shí)現(xiàn)
若采用mybatis框架,數(shù)據(jù)庫新建表,手動編寫的話,需要編寫大量的實(shí)體類、mapper文件、mapper.xml文件,都是一些重復(fù)且有規(guī)律的工作。我們可以引用插件,然后做配置,自動生成這些文件,本文就來詳細(xì)的介紹一下2021-08-08Spring Web MVC框架學(xué)習(xí)之配置Spring Web MVC
這一篇文章講的是Spring Web MVC各部分的配置方法,包括Java代碼配置和XML文件配置以及MVC命名空間的使用方法。2017-03-03