HttpExchange vs OpenFeign - le match des clients HTTP

Publié le 15/03/2026 Source : sfeir.dev

HttpExchange vs OpenFeign - le match des clients HTTP

Introduction

Quand on consomme des API dans un projet Spring Boot, on veut un client HTTP simple, testable et observable. Deux approches ressortent souvent :

La question n’est pas “qui gagne”, mais dans quel contexte chaque solution brille. Un monolithe moderne n’a pas les mêmes besoins qu’un mesh de microservices, et un POC n’a pas les mêmes contraintes qu’une plateforme en production.

Objectif : comparer fonctionnellement, architecturalement et opérationnellement les deux options, avec du code vérifiable dans le repo.


Présentation d’OpenFeign

OpenFeign est un client HTTP déclaratif intégré à Spring Cloud. Il permet de définir une interface Java annotée et de déléguer le reste à l’infrastructure : sérialisation, erreurs, load-balancing, retries, discovery, configuration centralisée…

Petit point d’histoire

Feign est né dans l’écosystème Netflix OSS pour simplifier la communication entre services. Spring Cloud l’a intégré très tôt, ce qui en a fait un standard de facto dans les architectures microservices Spring.

Cas d’usage typiques

Pièges fréquents


✅ Avantages / ❌ Inconvénients d’OpenFeign

Avantages Inconvénients
Intégration native Spring Cloud Dépendance à Spring Cloud
Client déclaratif très concis Stack plus lourde pour des projets simples
Génération automatique depuis OpenAPI Moins de contrôle fin qu’un RestClient
Facilement extensible (interceptors, retries, encoders) Courbe d’apprentissage si on ne connaît pas Spring Cloud
Très adapté aux microservices Parfois surdimensionné pour un mono-service

Présentation de HttpExchange

@HttpExchange est un mécanisme standard Spring Framework (sans Spring Cloud) qui permet de définir un client HTTP sous forme d’interface, puis de le brancher via un HttpServiceProxyFactory et un RestClient (ou WebClient).

Petit point d’histoire

Pendant longtemps, RestTemplate était la norme. Il a été remplacé par WebClient, puis par RestClient dans Spring Framework 6, plus simple et plus moderne. @HttpExchange vient compléter cette évolution en permettant une approche déclarative sans passer par Spring Cloud.

Cas d’usage typiques

Pièges fréquents


✅ Avantages / ❌ Inconvénients de HttpExchange

Avantages Inconvénients
Standard Spring Framework, sans Spring Cloud Moins d’intégration microservices par défaut
Très léger, simple à activer Pas de génération OpenAPI native
Configuration fine via RestClient Plus de code “plomberie” à écrire
Parfait pour projets simples/modernes Peut nécessiter des libs supplémentaires (résilience, retry)
Excellent pour du mono-service Moins “plug & play” que Feign

Tableau comparatif : OpenFeign vs HttpExchange

Critère OpenFeign HttpExchange
Dépendances Spring Cloud + Feign Spring Framework uniquement
Mise en place Très rapide si Cloud déjà en place Très rapide, configuration minimale
Microservices Excellent (discovery, LB, config) Possible mais à assembler
Génération OpenAPI Oui Non
Observabilité Cloud + Micrometer prêts Via RestClient/WebClient + Micrometer
Résilience Facile via Cloud À ajouter (Resilience4j, etc.)
Contrôle fin HTTP Moyen Élevé
Courbe d’apprentissage Facile pour équipes Cloud Facile pour équipes Spring

Performances et observabilité

Performances

Le vrai levier de performance ne vient pas du choix du client, mais de :

Observabilité

Dans les deux cas, le point clé reste de rendre visibles :

Si votre équipe a déjà une pile observabilité bien rodée, Feign s’insère plus naturellement. Sinon, HttpExchange vous donne un meilleur contrôle mais demande un peu plus d’effort.


Quand choisir l’un ou l’autre ?

Choisir OpenFeign si :

Choisir HttpExchange si :


Exemple par le code (repo)

Dans le repo springboot-demo, le module de test est :

Il contient deux apps :

Dans AuthorApplication, on a :

1) Client HttpExchange

@HttpExchange
public interface BookHttpExchangeClient {

    @GetExchange("/books/author/{id}")
    List<Book> getBooksByAuthorId(@PathVariable("id") Long authorId);

    @PostExchange("/books")
    Book createBook(@RequestBody Book book);
}

2) Configuration via RestClient

@Bean
public BookHttpExchangeClient bookHttpExchangeClient(
        @Value("${bookManagement.url:http://localhost:8092}") String bookManagementUrl
) {
    RestClient restClient = RestClient.builder()
            .baseUrl(bookManagementUrl)
            .build();

    HttpServiceProxyFactory factory = HttpServiceProxyFactory
            .builderFor(RestClientAdapter.create(restClient))
            .build();

    return factory.createClient(BookHttpExchangeClient.class);
}

3) Adapter Feign (client généré)

@Service
@ConditionalOnProperty(name = "books.client", havingValue = "feign", matchIfMissing = true)
public class FeignBookClientAdapter implements BookClient {

    private final BookManagementApi bookManagementApi;

    public FeignBookClientAdapter(BookManagementApi bookManagementApi) {
        this.bookManagementApi = bookManagementApi;
    }

    @Override
    public List<Book> getBooksByAuthorId(Long authorId) {
        return bookManagementApi.getBooksByAuthorId(authorId);
    }

    @Override
    public Book createBook(Book book) {
        return bookManagementApi.createBook(book);
    }
}

4) Basculer par propriété

books.client=feign
# ou
books.client=http-exchange

Résultat : les endpoints REST de AuthorApplication restent inchangés, seule la stratégie d’appel change.


Conclusion

Le bon choix ne dépend pas de “qui gagne”, mais du contexte.

Dans tous les cas, les deux approches sont valides, modernes et compatibles avec Spring Boot 3.x.


Liens utiles dans le vault