Introducción a Fingir

1. Información general

En este tutorial, presentaremos Feign, un cliente HTTP declarativo desarrollado por Netflix.

Feign tiene como objetivo simplificar los clientes de API HTTP. En pocas palabras, el desarrollador solo necesita declarar y anotar una interfaz mientras la implementación real se aprovisiona en tiempo de ejecución.

2. Ejemplo

A lo largo de este tutorial, usaremos una aplicación de librería de ejemplo que expone el punto final de la API REST.

Podemos clonar fácilmente el proyecto y ejecutarlo localmente:

mvn install spring-boot:run

3. Configuración

Primero, agreguemos las dependencias necesarias:

 io.github.openfeign feign-okhttp 10.11   io.github.openfeign feign-gson 10.11   io.github.openfeign feign-slf4j 10.11 

Además de la dependencia fingir-core (que también está incorporada), usaremos algunos complementos, especialmente: fingir-okhttp para usar internamente el cliente OkHttp de Square para realizar solicitudes, fingir-gson para usar GSON de Google como procesador JSON y fingir- slf4j para usar la fachada de registro simple para registrar solicitudes.

Para obtener realmente algunos resultados de registro, necesitaremos nuestra implementación de registrador compatible con SLF4J favorita en la ruta de clases.

Antes de proceder a crear nuestra interfaz de cliente, primero configuraremos un modelo de libro para almacenar los datos:

public class Book { private String isbn; private String author; private String title; private String synopsis; private String language; // standard constructor, getters and setters }

NOTA: Un procesador JSON necesita al menos un "constructor sin argumentos".

De hecho, nuestro proveedor REST es una API impulsada por hipermedia , por lo que, además, necesitaremos una clase contenedora simple:

public class BookResource { private Book book; // standard constructor, getters and setters }

Nota: Nos ' ll mantener la BookResource simple porque nuestra muestra de clientes Fingir no se beneficia de características hipermedia!

4. Lado del servidor

Para entender cómo definir un cliente de Feign, primero veremos algunos de los métodos y respuestas admitidos por nuestro proveedor REST.

Probémoslo con un simple comando curl shell para enumerar todos los libros. Debemos recordar prefijar todas las llamadas con / api , que es el contexto de servlet de la aplicación:

curl //localhost:8081/api/books

Como resultado, obtendremos un repositorio de libros completo representado como JSON:

[ { "book": { "isbn": "1447264533", "author": "Margaret Mitchell", "title": "Gone with the Wind", "synopsis": null, "language": null }, "links": [ { "rel": "self", "href": "//localhost:8081/api/books/1447264533" } ] }, ... { "book": { "isbn": "0451524934", "author": "George Orwell", "title": "1984", "synopsis": null, "language": null }, "links": [ { "rel": "self", "href": "//localhost:8081/api/books/0451524934" } ] } ]

También podemos consultar un recurso de libro individual , agregando el ISBN a una solicitud de obtención:

curl //localhost:8081/api/books/1447264533

5. Cliente fingido

Finalmente, definamos nuestro cliente Fingir.

Usaremos la anotación @RequestLine para especificar el verbo HTTP y una parte de la ruta como argumento. Los parámetros se modelarán usando la anotación @Param :

public interface BookClient { @RequestLine("GET /{isbn}") BookResource findByIsbn(@Param("isbn") String isbn); @RequestLine("GET") List findAll(); @RequestLine("POST") @Headers("Content-Type: application/json") void create(Book book); }

NOTA: Los clientes de Feign se pueden utilizar para consumir API HTTP basadas en texto únicamente, lo que significa que no pueden manejar datos binarios, por ejemplo, cargas o descargas de archivos.

¡Eso es todo! Ahora usaremos Feign.builder () para configurar nuestro cliente basado en interfaz. La implementación real se aprovisionará en tiempo de ejecución:

BookClient bookClient = Feign.builder() .client(new OkHttpClient()) .encoder(new GsonEncoder()) .decoder(new GsonDecoder()) .logger(new Slf4jLogger(BookClient.class)) .logLevel(Logger.Level.FULL) .target(BookClient.class, "//localhost:8081/api/books");

Feign admite varios complementos, como codificadores y decodificadores JSON / XML o un cliente HTTP subyacente para realizar las solicitudes.

6. Prueba unitaria

Creemos tres casos de prueba para probar nuestro cliente. Tenga en cuenta que utilizamos importaciones estáticas para org.hamcrest.CoreMatchers. * Y org.junit.Assert. * :

@Test public void givenBookClient_shouldRunSuccessfully() throws Exception { List 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")); } 

7. Lecturas adicionales

Si necesitamos algún tipo de respaldo en caso de que el servicio no esté disponible, podríamos agregar HystrixFeign al classpath y construir nuestro cliente con HystrixFeign.builder () .

Consulte esta serie de tutoriales dedicados para obtener más información sobre Hystrix.

Además, si quisiéramos integrar Spring Cloud Netflix Hystrix con Feign, hay un artículo dedicado aquí.

Además, también es posible agregar equilibrio de carga del lado del cliente y / o descubrimiento de servicios a nuestro cliente.

Podríamos lograr esto agregando Ribbon a nuestro classpath y usar el constructor así:

BookClient bookClient = Feign.builder() .client(RibbonClient.create()) .target(BookClient.class, "//localhost:8081/api/books");

Para el descubrimiento de servicios, tenemos que desarrollar nuestro servicio con Spring Cloud Netflix Eureka habilitado. Luego, simplemente integre con Spring Cloud Netflix Feign. Como resultado, obtenemos el equilibrio de carga de Ribbon de forma gratuita. Puede encontrar más sobre esto aquí.

8. Conclusión

En este artículo, explicamos cómo construir un cliente HTTP declarativo usando Feign para consumir API basadas en texto.

Como de costumbre, todos los ejemplos de código que se muestran en este tutorial están disponibles en GitHub.