Giới thiệu về Feign – Ví dụ về Feign
NỘI DUNG BÀI VIẾT
1. Tổng quan
Feign nhằm mục đích đơn giản hóa các ứng dụng HTTP API. Nói một cách đơn giản, developer chỉ cần khai báo và chú thích một interface trong khi việc triển khai thực tế được cung cấp trong thời gian chạy.
Trong hướng dẫn này, chúng tôi sẽ giới thiệu Feign – một ứng dụng client HTTP khai báo do Netflix phát triển.
2. Ví dụ về Feign
Trong bài này, tôi sẽ sử dụng một ví dụ bookstore application để hiển thị điểm cuối API REST.
Hãy clone về và chạy:
Tổng hợp 200+ tài liệu, sách, bài thực hành, video hướng dẫn lập trình… từ cơ bản đến nâng cao
mvn install spring-boot:run
Code language: CSS (css)
3. Cài đặt
Đầu tiên hãy thêm dependency:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>10.11</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
<version>10.11</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-slf4j</artifactId>
<version>10.11</version>
</dependency>
Code language: HTML, XML (xml)
Ngoài feign-core dependency, tôi sẽ sử dụng một số plugin, đặc biệt là: feign-okhttp cho nội bộ sử dụng Square’s OkHttp client để tạo request, feign-gson cho sử dụng Google’s GSON giống xử lý JSON và feign-slf4j sử dụng cho Simple Logging Facade để log các request.
Để thực sự có được log output, tôi sẽ cần triển khai SLF4J-supported logger trong classpath.
Trước khi tôi tiến hành tạo interface client, tôi sẽ thiết lập model Book để lưu giữ dữ liệu:
public class Book {
private String isbn;
private String author;
private String title;
private String synopsis;
private String language;
// standard constructor, getters and setters
}
Code language: PHP (php)
LƯU Ý: Bộ xử lý JSON cần ít nhất một “no arguments constructor”.
Trên thực tế thì REST cung cấp một API hypermedia-driven, vì vậy chúng ta cần một class simple wrapper:
public class BookResource {
private Book book;
// standard constructor, getters and setters
}
Code language: PHP (php)
Lưu ý: tôi sẽ giữ cho BookResource đơn giản vì ứng dụng Feign mẫu không được hưởng lợi từ các tính năng hypermedia!
4. Server Side
Để hiểu cách define một ứng dụng Feign client, ta sẽ xem xét một số phương pháp được REST hỗ trợ.
Hãy thử nó với một lệnh curl shell đơn giản để liệt kê tất cả các cuốn sách. Chúng ta cần nhớ đặt tiền tố cho tất cả các cuộc gọi bằng /api, là application’s servlet-context:
curl http://localhost:8081/api/books
Code language: JavaScript (javascript)
Kết quả là, chúng ta sẽ nhận được một book repo hoàn chỉnh được biểu thị dưới dạng JSON:
[
{
"book": {
"isbn": "1447264533",
"author": "Margaret Mitchell",
"title": "Gone with the Wind",
"synopsis": null,
"language": null
},
"links": [
{
"rel": "self",
"href": "http://localhost:8081/api/books/1447264533"
}
]
},
...
{
"book": {
"isbn": "0451524934",
"author": "George Orwell",
"title": "1984",
"synopsis": null,
"language": null
},
"links": [
{
"rel": "self",
"href": "http://localhost:8081/api/books/0451524934"
}
]
}
]
Code language: JSON / JSON with Comments (json)
Chúng ta có thể truy vấn Book resource riêng lẻ, cách thêm ISBN vào get request:
curl http://localhost:8081/api/books/1447264533
Code language: JavaScript (javascript)
5. Feign Client
Cuối cùng, hãy xác định ứng dụng Feign client.
Tôi sử dụng annotation @RequestLine để chỉ định động từ HTTP và một phần đường dẫn làm đối số. Các tham số sẽ được tạo mô hình bằng cách sử dụng chú thích @Param:
public interface BookClient {
@RequestLine("GET /{isbn}")
BookResource findByIsbn(@Param("isbn") String isbn);
@RequestLine("GET")
List<BookResource> findAll();
@RequestLine("POST")
@Headers("Content-Type: application/json")
void create(Book book);
}
Code language: PHP (php)
LƯU Ý: Máy khách Feign chỉ có thể được sử dụng để sử dụng các API HTTP dựa trên văn bản, có nghĩa là chúng không thể xử lý dữ liệu nhị phân, ví dụ: tải lên hoặc tải xuống tệp.
Feign hỗ trợ nhiều plugin khác nhau như bộ mã hóa và giải mã JSON/XML hoặc một ứng dụng HTTP client cơ bản để thực hiện các yêu cầu.
6. Unit Test
Hãy tạo ra 3 test case để kiểm tra client. Lưu ý, tôi sử dụng org.hamcrest.CoreMatchers. * Và org.junit.Assert. *:
@Test
public void givenBookClient_shouldRunSuccessfully() throws Exception {
List<Book> books = bookClient.findAll().stream()
.map(BookResource::getBook)
.collect(Collectors.toList());
assertTrue(books.size() > 2);
}
@Test
public void givenBookClient_shouldFindOneBook() throws Exception {
Book book = bookClient.findByIsbn("0151072558").getBook();
assertThat(book.getAuthor(), containsString("Orwell"));
}
@Test
public void givenBookClient_shouldPostBook() throws Exception {
String isbn = UUID.randomUUID().toString();
Book book = new Book(isbn, "Me", "It's me!", null, null);
bookClient.create(book);
book = bookClient.findByIsbn(isbn).getBook();
assertThat(book.getAuthor(), is("Me"));
}
Code language: PHP (php)
7. Đọc thêm
Nếu chúng ta cần dự phòng trong trường hợp service không khả, chúng ta cần thêm HystrixFeign vào classpath và build client với HystrixFeign.builder().
Ngoài ra, nếu chúng tôi muốn tích hợp Spring Cloud Netflix Hystrix với Feign, có một bài viết dành riêng ở đây.
Hơn nữa, cũng có thể thêm tính năng cân bằng tải phía client và / hoặc khám phá dịch vụ cho client.
Chúng ta có thể đạt được điều này bằng cách thêm Ribbon vào classpath của mình và sử dụng trình tạo như sau:
BookClient bookClient = Feign.builder()
.client(RibbonClient.create())
.target(BookClient.class, "http://localhost:8081/api/books");
Code language: JavaScript (javascript)
Để khám phá dịch vụ, tôi phải xây dựng dịch vụ của mình khi bật Spring Cloud Netflix Eureka. Sau đó, chỉ cần tích hợp với Spring Cloud Netflix Feign. Do đó, tôi nhận được tính năng cân bằng tải Ribbon miễn phí.
8. Kết luận
Trong bài viết này, tôi đã giải thích cách tạo một ứng dụng HTTP client khai báo bằng cách sử dụng Feign để sử dụng các API dựa trên văn bản.
Tham khảo bài viét khác:
https://hocspringboot.net/2021/08/22/design-patterns-trong-spring-framework/
Leave a Reply