Feign簡介
在本教程中,我們將介紹Feign。我們還將談談Spring Boot和Feign。
在本教程中,我們將瞭解如何使用Feign編寫宣告性REST客戶端。它透過抽象出我們通常編寫的樣板程式碼,使編寫Web客戶端變得容易。我們需要做的就是宣告一個介面並註釋它及其方法。實際的實現將由框架在執行時完成,以及呼叫之間的各種訊息轉換。我們首先需要設定一個使用已知端點執行的示例REST API,以便我們可以使用feign客戶端呼叫它們。
1.服務設定
我們的示例服務是一個簡單的spring-boot應用程式,包含一個具有兩個端點的REST控制器:
@RestController public class ProductController { private static List < Product > productList = new ArrayList < > (); static { productList.add(new Product(1, "product-1", 12.0)); productList.add(new Product(2, "product-2", 34.0)); productList.add(new Product(3, "product-3", 9.0)); } @GetMapping("/products") public ResponseEntity << ? > getProsucts() { return ResponseEntity.ok(productList); } @GetMapping("/product/{id}") public ResponseEntity << ? > getProsucts(@PathVariable int id) { Product product = findProduct(id); if (product == null) { return ResponseEntity.badRequest() .body("Invalid product Id"); } return ResponseEntity.ok(product); } private Product findProduct(int id) { return productList.stream() .filter(user -> user.getId() .equals(id)) .findFirst() .orElse(null); } } |
兩個端點是' /products'和' product/{id}',它們返回一個產品列表和一個基於分別傳遞的id的產品。如果未找到產品,則返回HTTP.BAD_REQUEST響應。以下是application.properties:
server.port=8081 spring.application.name=product-service |
Product服務將在埠8081上執行
2.客戶端安裝
建立Spring啟動應用程式的最佳方法是Spring Initializr。選擇Spring Boot版本,並新增“Web”,“Feign”依賴項。將它生成為Maven專案,你就完成了。請注意pom.xml中的以下依賴項:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> |
Feign最初由Netflix贊助,但後來開源。在spring-boot 1.x版本中,feign依賴項來自Netflix但是從spring-boot 2.x開始使用openfeign。透過在主類中新增' @EnableFeignClients' 使專案能夠使用Feign客戶端:
@SpringBootApplication @EnableFeignClients public class FeignClientExampleApplication { public static void main(String[] args) { SpringApplication.run(FeignClientExampleApplication.class, args); } } |
讓我們來定義我們的產品服務Feign客戶端。首先,我們必須建立一個介面ProductServiceClient,並透過@FeignClient指定名稱和產品服務的URL執行來對其進行註釋。至於方法,我們只需要宣告它並註釋就像Spring MVC樣式一樣。我們還需要告訴它可能需要哪些輸入以及轉換所需的響應型別。
@FeignClient(name = "product-service", url = "http://localhost:8081") public interface ProductServiceClient { @RequestMapping(value = "/products", method = RequestMethod.GET) public List < Product > getAllProducts(); @RequestMapping(value = "/product/{id}", method = RequestMethod.GET) public Product getProduct(@PathVariable("id") int productId); } |
Spring將使用openfeign在執行時實現此介面的實現。我們必須在專案中定義Product類,因為我們正在將響應轉換為它:
public class Product { private Integer id; private String name; private double price; public Product(Integer id, String name, double price) { this.id = id; this.name = name; this.price = price; } public Integer getId() { return id; } public String getName() { return name; } public double getPrice() { return price; } } |
現在讓我們在AppController中使用這個ProductServiceClient。為此,我們需要@Autowired將ProductServiceClient放入我們的控制器中。
@RestController public class AppController { @Autowired ProductServiceClient productServiceClient; @GetMapping("/fetchProducts") public ResponseEntity << ? > fetchProducts() { return ResponseEntity.ok(productServiceClient.getAllProducts()); } @GetMapping("/fetchProduct/{id}") public ResponseEntity << ? > fetchProduct(@PathVariable int id) { return ResponseEntity.ok(productServiceClient.getProduct(id)); } } |
這就是我們所要做的。讓我們使用Postman進行測試:
http://localhost:8080/fetchProduct/1
在簡單程式碼的背後,所有樣板程式碼都由spring和openfeign庫處理。這樣可以減少程式碼,減少出錯的機會。
3.處理錯誤的錯誤
預設情況下,Feign僅針對任何錯誤情況(其中響應不是2XX或者存在轉換錯誤等)丟擲FeignException。
但是,如果找不到產品ID,您可能希望捕獲這些錯誤並在最終處理響應,就像產品服務引發的BAD_REQUEST錯誤一樣。我們首先定義我們的自定義ProductNotFound異常:
public class ProductNotFoundException extends RuntimeException { private static final long serialVersionUID = 1 L; public ProductNotFoundException(String msg) { super(msg); } } |
現在讓我們為這個應用定義我們的異常處理程式:
@RestControllerAdvice public class AppExceptionHandler { @ResponseBody @ExceptionHandler(value = ProductNotFoundException.class) public ResponseEntity << ? > handleException(ProductNotFoundException exception) { return ResponseEntity.status(HttpStatus.NOT_FOUND) .body(exception.getMessage()); } } |
現在要捕獲FeignException並提供您自己的實現,您需要實現feign.codec.ErrorDecoder並將其在Spring應用程式上下文中註冊為bean 。
@Component public class AppFeignErrorDecoder implements ErrorDecoder { private final ErrorDecoder defaultErrorDecoder = new Default(); @Override public Exception decode(String methodKey, Response response) { if (response.status() >= 400 && response.status() <= 499) { throw new ProductNotFoundException("Product Not Found"); } return defaultErrorDecoder.decode(methodKey, response); } } |
如您所見,我們捕獲了所有4xx錯誤並丟擲了我們自己的自定義異常。
4. .使用Feign和Eureka和Ribbon
通常在微服務架構中,所有服務都註冊到像Eureka這樣的註冊服務,並且可能存在執行相同服務的多個例項。因此,您可能不希望在Feign客戶端中對URL進行硬編碼,也希望連線到響應更快的服務例項。
我們來設定一個Eureka伺服器。同樣,我們將使用Spring Initializr來建立它。
然後您需要做的就是新增@EnableEurekaServer到主類:
@SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } |
以下是application.properties:server.port=8761。因此,我們的Eureka伺服器將在8761上執行,這是Spring的推薦埠。
現在註冊我們的2項服務。您只需在我們專案中新增以下依賴項pom.xml:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> |
新增@EnableDiscoveryClient到應用程式的主類,如:
@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class FeignClientExampleApplication { public static void main(String[] args) { SpringApplication.run(FeignClientExampleApplication.class, args); } } |
(banq注:Spring2 已經不需要@EnableDiscoveryClient)
啟動這兩個應用程式,您將看到他們在Eureka伺服器中註冊了。
現在讓我們從ProductServiceClient中刪除硬編碼的URL:
@FeignClient(name = "product-service" /*, url = "http://localhost:8081"*/ ) public interface ProductServiceClient { // same as previous } |
現在,幕後,ProductServiceClient將使用name屬性從Eureka伺服器獲取URL (“product-service”)。Ribbon是一個客戶端負載均衡器,它附帶了我們所包含的依賴項。這將自動獲取最佳伺服器以供我們進行其餘呼叫。
相關文章
- nacos、ribbon和feign的簡明教程
- feign
- 簡介
- Jira使用簡介 HP ALM使用簡介
- Feign系列
- BookKeeper 介紹(1)--簡介
- ggml 簡介
- PCIe簡介
- valgrind簡介
- SpringMVC簡介SpringMVC
- HTML 簡介HTML
- 核心簡介
- DPDK簡介
- Docker簡介Docker
- SpotBugs 簡介
- webservice簡介Web
- OME 簡介
- Spring 簡介Spring
- pytorch簡介PyTorch
- 【QCustomPlot】簡介
- DuckDB簡介
- SDL簡介
- swagger簡介Swagger
- MongoDb簡介MongoDB
- RabbitMQ簡介MQ
- JetCache 簡介
- JavaParser 簡介Java
- SSHJ 簡介
- Redpanda簡介
- Swoole 簡介
- jQuery 簡介jQuery
- SQLite簡介SQLite
- NGINX簡介Nginx
- Electron簡介
- cookie 簡介Cookie
- Session 簡介Session
- Selenium - 簡介
- jango簡介Go