Introduction à Spring Cloud OpenFeign

1. Vue d'ensemble

Dans ce didacticiel, nous allons décrire Spring Cloud OpenFeign - un client REST déclaratif pour les applications Spring Boot.

Feign facilite l'écriture de clients de service Web avec la prise en charge d'annotations enfichables, qui comprend les annotations Feign et les annotations JAX-RS.

En outre, Spring Cloud ajoute la prise en charge des annotations Spring MVC et de l'utilisation des mêmes HttpMessageConverters que ceux utilisés dans Spring Web.

Une grande chose à propos de l'utilisation de Feign est que nous n'avons pas besoin d'écrire de code pour appeler le service, autre qu'une définition d'interface.

2. Dépendances

Tout d'abord, nous allons commencer par créer un projet Web Spring Boot et ajouter la dépendance spring-cloud-starter-openfeign à notre fichier pom.xml :

 org.springframework.cloud spring-cloud-starter-openfeign 

De plus, nous devrons ajouter les dépendances spring-cloud :

    org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import   

Nous pouvons trouver les dernières versions des dépendances spring-cloud-starter-openfeign et spring-cloud sur Maven Central.

3. Feignez le client

Ensuite, nous devons ajouter @EnableFeignClients à notre classe principale:

@SpringBootApplication @EnableFeignClients public class ExampleApplication { public static void main(String[] args) { SpringApplication.run(ExampleApplication.class, args); } }

Avec cette annotation, nous activons l'analyse des composants pour les interfaces qui déclarent être des clients Feign.

Ensuite, nous déclarons un client Feign à l'aide de l' annotation @FeignClient :

@FeignClient(value = "jplaceholder", url = "//jsonplaceholder.typicode.com/") public interface JSONPlaceHolderClient { @RequestMapping(method = RequestMethod.GET, value = "/posts") List getPosts(); @RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json") Post getPostById(@PathVariable("postId") Long postId); }

Dans cet exemple, nous avons configuré un client pour lire à partir des API JSONPlaceHolder.

L' argument value passé dans l' annotation @FeignClient est un nom de client arbitraire obligatoire, tandis qu'avec l' argument url , nous spécifions l'URL de base de l'API.

De plus, comme cette interface est un client Feign, nous pouvons utiliser les annotations Spring Web pour déclarer les API que nous voulons atteindre.

4. Configuration

Maintenant, il est très important de comprendre que chaque client Feign est composé d'un ensemble de composants personnalisables.

Spring Cloud crée un nouvel ensemble par défaut à la demande pour chaque client nommé à l'aide de la classe FeignClientsConfiguration que nous pouvons personnaliser comme expliqué dans la section suivante.

La classe ci-dessus contient ces beans:

  • Decoder - ResponseEntityDecoder , qui enveloppe SpringDecoder, utilisé pour décoder la réponse
  • Encoder - SpringEncoder , utilisé pour encoder le RequestBody
  • Logger - Slf4jLogger est le logger par défaut utilisé par Feign
  • Contrat - SpringMvcContract , qui fournit le traitement des annotations
  • Feign-Builder - HystrixFeign.Builder utilisé pour construire les composants
  • Client - LoadBalancerFeignClient ou client Feign par défaut

4.1. Configuration des beans personnalisés

Si nous voulons personnaliser un ou plusieurs de ces beans, nous pouvons les remplacer à l'aide d'une classe @Configuration , que nous ajoutons ensuite à l' annotation FeignClient :

@FeignClient(value = "jplaceholder", url = "//jsonplaceholder.typicode.com/", configuration = MyClientConfiguration.class)
@Configuration public class MyClientConfiguration { @Bean public OkHttpClient client() { return new OkHttpClient(); } }

Dans cet exemple, nous disons à Feign d'utiliser OkHttpClient au lieu de celui par défaut pour prendre en charge HTTP / 2.

Feign prend en charge plusieurs clients pour différents cas d'utilisation, y compris ApacheHttpClient , qui envoie plus d'en-têtes avec la requête - par exemple, Content-Length, ce que certains serveurs attendent.

Pour utiliser ces clients, n'oublions pas d'ajouter les dépendances requises à notre fichier pom.xml , par exemple:

 io.github.openfeign feign-okhttp   io.github.openfeign feign-httpclient 

Nous pouvons trouver les dernières versions de feign-okhttp et feign-httpclient sur Maven Central.

4.2. Configuration à l'aide des propriétés

Plutôt que d'utiliser une classe @Configuration , nous pouvons utiliser les propriétés de l'application pour configurer les clients Feign , comme indiqué dans cet exemple application.yaml :

feign: client: config: default: connectTimeout: 5000 readTimeout: 5000 loggerLevel: basic

Avec cette configuration, nous définissons les délais d'expiration à 5 secondes et le niveau de journalisation à basique pour chaque client déclaré dans l'application.

Enfin, nous pouvons créer la configuration avec default comme nom de client pour configurer tous les objets @FeignClient , ou nous pouvons déclarer le faux nom de client pour une configuration:

feign: client: config: jplaceholder:

Si nous avons à la fois le bean @Configuration et les propriétés de configuration, les propriétés de configuration remplaceront les valeurs @Configuration .

5. Intercepteurs

L'ajout d'intercepteurs est une autre fonctionnalité utile fournie par Feign.

Les intercepteurs peuvent effectuer une variété de tâches implicites, de l'authentification à la journalisation, pour chaque requête / réponse HTTP.

Dans cette section, nous implémenterons notre propre intercepteur, ainsi que celui fourni par Spring Cloud OpenFeign prêt à l'emploi. Les deux ajouteront un en-tête d'authentification de base à chaque demande .

5.1. Implémentation de RequestInterceptor

Donc, dans l'extrait ci-dessous, implémentons notre intercepteur de demande personnalisé:

@Bean public RequestInterceptor requestInterceptor() { return requestTemplate -> { requestTemplate.header("user", username); requestTemplate.header("password", password); requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType()); }; }

Also, to add the interceptor to the request chain, we just need to add this bean to our @Configuration class, or as we saw previously, declare it in the properties file:

feign: client: config: default: requestInterceptors: com.baeldung.cloud.openfeign.JSONPlaceHolderInterceptor

5.2. Using BasicAuthRequestInterceptor

Alternatively, we can use the BasicAuthRequestInterceptor class that the Spring Cloud OpenFeign provides:

@Bean public BasicAuthRequestInterceptor basicAuthRequestInterceptor() { return new BasicAuthRequestInterceptor("username", "password"); }

It's simple as that! Now all the requests will contain the basic authentication header.

6. Hystrix Support

Feign supports Hystrix, so if we have enabled it, we can implement the fallback pattern.

With the fallback pattern, when a remote service call fails, rather than generating an exception, the service consumer will execute an alternative code path to try to carry out the action through another means.

To achieve the goal, we need to enable Hystrix adding feign.hystrix.enabled=true in the properties file.

This allows us to implement fallback methods that are called when the service fails:

@Component public class JSONPlaceHolderFallback implements JSONPlaceHolderClient { @Override public List getPosts() { return Collections.emptyList(); } @Override public Post getPostById(Long postId) { return null; } }

To let Feign know that fallback methods have been provided, we also need to set our fallback class in the @FeignClient annotation:

@FeignClient(value = "jplaceholder", url = "//jsonplaceholder.typicode.com/", fallback = JSONPlaceHolderFallback.class) public interface JSONPlaceHolderClient { // APIs }

7. Logging

For each Feign client, a logger is created by default.

To enable logging, we should declare it in the application.properties file using the package name of the client interfaces:

logging.level.com.baeldung.cloud.openfeign.client: DEBUG

Or, if we want to enable logging only for one particular client in a package, we can use the full class name:

logging.level.com.baeldung.cloud.openfeign.client.JSONPlaceHolderClient: DEBUG

Note that Feign logging responds only to the DEBUG level.

The Logger.Level that we may configure per client indicates how much to log:

@Configuration public class ClientConfiguration { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.BASIC; } }

There are four logging levels to choose from:

  • NONE – no logging, which is the default
  • BASIC – log only the request method, URL, and response status
  • HEADERS – log the basic information together with request and response headers
  • FULL – log the body, headers, and metadata for both request and response

8. Error Handling

Feign's default error handler, ErrorDecoder.default, always throws a FeignException.

Now, this behavior isn't always the most useful. So, to customize the Exception thrown, we can use a CustomErrorDecoder:

public class CustomErrorDecoder implements ErrorDecoder { @Override public Exception decode(String methodKey, Response response) { switch (response.status()){ case 400: return new BadRequestException(); case 404: return new NotFoundException(); default: return new Exception("Generic error"); } } }

Ensuite, comme nous l'avons fait précédemment, nous devons remplacer le ErrorDecoder par défaut en ajoutant un bean à la classe @Configuration :

@Configuration public class ClientConfiguration { @Bean public ErrorDecoder errorDecoder() { return new CustomErrorDecoder(); } }

9. Conclusion

Dans cet article, nous avons discuté de Spring Cloud OpenFeign et de son implémentation dans un exemple d'application simple.

De plus, nous avons vu comment configurer un client, comment ajouter des intercepteurs à nos requêtes et comment gérer les erreurs en utilisant Hystrix et ErrorDecoder.

Comme d'habitude, tous les exemples de code présentés dans ce didacticiel sont disponibles à l'adresse over sur GitHub.