Feign là một thư viện HTTP client binder, giúp chúng ta có thể viết code để call tới các service khác sử dụng HTTP protocol một cách dễ dàng. Các bạn không cần phải viết code để khởi tạo connection tới HTTP server, chỉ cần khai báo thông tin endpoint của service theo syntax của Feign và địa chỉ của HTTP server thì Feign sẽ giúp chúng ta có thể gọi đến service. Cụ thể như thế nào? Chúng ta hãy cùng nhau tìm hiểu trong bài viết này, các bạn nhé!
Đầu tiên, mình sẽ tạo mới một Maven project với nhiều module để làm ví dụ, như sau:

Service module sẽ expose một số endpoint và feign module sẽ đóng vai trò là HTTP client, gọi đến các endpoint này nha các bạn!
Service module là một ứng dụng Spring Boot với Spring Web dependency.
Ứng dụng này sẽ expose các endpoint như sau:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.huongdanjava.feign; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class ServiceController { @GetMapping("/students/{id}") public String getStudent(@RequestParam("id") String studentId) { return studentId; } @GetMapping("/students") public String searchStudent(@RequestParam String name) { return name; } @PostMapping("/students") public String addNewStudent(@RequestBody AddNewStudentRequest student) { return "Added new student: " + student.name(); } } |
Vì chỉ để làm ví dụ nên mình không thêm nhiều logic xử lý trong mỗi endpoint, như các bạn thấy.
Cho feign module, mình sẽ khai báo Maven dependency của Feign như sau:
|
1 2 3 4 5 6 7 8 9 10 11 |
<dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-core</artifactId> <version>13.12</version> </dependency> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-gson</artifactId> <version>13.12</version> </dependency> |
Mình cũng đã khai báo thêm dependency feign-gson để làm việc với các HTTP POST request sử dụng body data dưới dạng JSON các bạn nhé!
Để sử dụng Feign làm HTTP client binder, đầu tiên, các bạn cần khai báo một interface với các method được annotate sử dụng các annotation của Feign, cho ví dụ của mình như sau:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.huongdanjava.feign; import feign.HeaderMap; import feign.Param; import feign.QueryMap; import feign.RequestLine; import java.util.Map; public interface Service { @RequestLine("GET /students/{id}") String getStudent(@Param("id") String id); @RequestLine("GET /students") String searchStudent(@QueryMap Map<String, String> queryParams); @RequestLine("POST /students") String addNewStudent(@HeaderMap Map<String, String> headerMap, AddNewStudentRequest addNewStudentRequest); } |
Tương ứng cho từng endpoint, các bạn cần khai báo một method và method này sẽ được annotate với annotation @RequestLine. Tên của endpoint cùng với HTTP method của nó cũng sẽ được khai báo cùng annotation @RequestLine các bạn nhé.
Các path parameter sẽ được khai báo sử dụng annotation @Param
Các query parameters sẽ được khai báo sử dụng interface Map và được annotate với annotation @QueryMap
Các thông tin liên quan đến header của request, các bạn cần khai báo chúng sử dụng interface Map và được annotate với annotation @HeaderMap.
Cho request body của endpoint, các bạn chỉ cần khai báo một đối tượng chứa nội dung của request body data là được.
Sau khi đã định nghĩa interface chứa thông tin endpoint, bây giờ chúng ta sẽ sử dụng đối tượng của class Feign để khởi tạo đối tượng cho interface Service. Ví dụ của mình như sau:
|
1 2 |
Service service = Feign.builder().encoder(new GsonEncoder()) .target(Service.class, "http://localhost:8080"); |
Để có thể convert request body từ Java object qua JSON data, các bạn cần khai báo encoder như mình đã làm như trên. Để convert response body dưới dạng JSON qua Java object thì các bạn hãy sử dụng phương thức decoder() với tham số là đối tượng của class GsonDecoder. Trong ví dụ của mình thì response chỉ ở dạng text nên mình không add decoder vào!
Feign sử dụng Java Proxy để từ thông tin của các method trong interface Service, nó có thể bind các method này đến các method handler gọi đến các endpoint của service, đó các bạn.
Giờ thì các bạn có thể gọi đến các endpoint của service sử dụng các method trong interface Service, đơn giản như sau:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.huongdanjava.feign; import feign.Feign; import feign.gson.GsonDecoder; import feign.gson.GsonEncoder; import java.net.http.HttpHeaders; import java.util.HashMap; import java.util.Map; public class Application { public static void main(String[] args) { Service service = Feign.builder().encoder(new GsonEncoder()) .target(Service.class, "http://localhost:8080"); System.out.println(service.getStudent("123")); Map<String, String> queryMap = new HashMap<>(); queryMap.put("name", "Khanh"); System.out.println(service.searchStudent(queryMap)); AddNewStudentRequest addNewStudentRequest = new AddNewStudentRequest("Khanh"); Map<String, String> headerMap = new HashMap<>(); headerMap.put("Content-Type", "application/json"); System.out.println(service.addNewStudent(headerMap, addNewStudentRequest)); } } |
Chạy service sau đó chạy ứng dụng feign, các bạn sẽ thấy kết quả như sau:

Như vậy là chúng ta đã có thể call tới service mà không cần phải viết code nhiều, phức tạp, đó các bạn!
Thông tin thêm cho các bạn là, mặc định Feign sẽ sử dụng class HttpURLConnection của Java để thực hiện việc call HTTP. Nếu thư viện Apache HttpClient trong classpath của ứng dụng thì nó sẽ sử dụng Apache HttpClient, còn nếu là thư viện OkHttp trong classpath thì nó sẽ sử dụng thư viện OkHttp này.
Các bạn có thể xem thêm video ở đây:
