Introduzione a Feign

1. Panoramica

In questo tutorial, introdurremo Feign, un client HTTP dichiarativo sviluppato da Netflix.

Feign mira a semplificare i client API HTTP. In poche parole, lo sviluppatore deve solo dichiarare e annotare un'interfaccia mentre l'implementazione effettiva viene fornita in fase di esecuzione.

2. Esempio

Durante questo tutorial, utilizzeremo un'applicazione libreria di esempio che espone l'endpoint dell'API REST.

Possiamo facilmente clonare il progetto ed eseguirlo localmente:

mvn install spring-boot:run

3. Configurazione

Innanzitutto, aggiungiamo le dipendenze necessarie:

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

Oltre alla dipendenza feign-core (che è anche inserita), utilizzeremo alcuni plugin, in particolare: feign-okhttp per utilizzare internamente il client OkHttp di Square per effettuare richieste, feign-gson per utilizzare GSON di Google come processore JSON e fingere- slf4j per l'utilizzo della facciata di registrazione semplice per registrare le richieste.

Per ottenere effettivamente un output di log, avremo bisogno della nostra implementazione di logger preferita supportata da SLF4J sul classpath.

Prima di procedere alla creazione della nostra interfaccia client, per prima cosa configureremo un modello Book per contenere i dati:

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

NOTA: almeno un "costruttore senza argomenti" è necessario per un processore JSON.

In effetti, il nostro provider REST è un'API basata su hypermedia , quindi avremo anche bisogno di una semplice classe wrapper:

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

Nota: Noi ' ll mantenere la BookResource semplice perché il nostro campione cliente Feign non beneficia di caratteristiche ipermediali!

4. Lato server

Per capire come definire un client Feign, esamineremo prima alcuni dei metodi e delle risposte supportati dal nostro provider REST.

Proviamolo con un semplice comando curl shell per elencare tutti i libri. Dobbiamo ricordarci di anteporre a tutte le chiamate / api , che è il contesto-servlet dell'applicazione:

curl //localhost:8081/api/books

Di conseguenza, otterremo un repository di libri completo rappresentato come 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" } ] } ]

Possiamo anche interrogare una singola risorsa Libro , aggiungendo l'ISBN a una richiesta di ricezione:

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

5. Finto cliente

Infine, definiamo il nostro cliente Feign.

Useremo l' annotazione @RequestLine per specificare il verbo HTTP e una parte del percorso come argomento. I parametri verranno modellati utilizzando l' annotazione @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: i client Feign possono essere utilizzati per utilizzare solo API HTTP basate su testo, il che significa che non possono gestire dati binari, ad esempio caricamenti o download di file.

È tutto! Ora useremo Feign.builder () per configurare il nostro client basato su interfaccia. L'implementazione effettiva verrà fornita in fase di esecuzione:

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 supporta vari plugin come codificatori e decodificatori JSON / XML o un client HTTP sottostante per effettuare le richieste.

6. Test unitario

Let's create three test cases to test our client. Note, we use static imports for org.hamcrest.CoreMatchers.* and 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. Further Reading

If we need some kind of a fallback in case of the service unavailability, we could add HystrixFeign to the classpath and build our client with HystrixFeign.builder().

Check out this dedicated tutorial series to learn more about Hystrix.

Additionally, if we'd like to integrate Spring Cloud Netflix Hystrix with Feign, there's a dedicated article over here.

Moreover, it's also possible to add client-side load-balancing and/or service discovery to our client.

We could achieve this by adding Ribbon to our classpath and use the builder like so:

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

Per la scoperta del servizio, dobbiamo creare il nostro servizio con Spring Cloud Netflix Eureka abilitato. Quindi integra semplicemente con Spring Cloud Netflix Feign. Di conseguenza, otteniamo il bilanciamento del carico della barra multifunzione gratuitamente. Maggiori informazioni su questo possono essere trovate qui.

8. Conclusione

In questo articolo, abbiamo spiegato come creare un client HTTP dichiarativo utilizzando Feign per utilizzare API basate su testo.

Come al solito, tutti gli esempi di codice mostrati in questo tutorial sono disponibili su GitHub.