[JAVA] Feign, qui implémente un client API avec juste une interface, est très pratique!

1. Qu'est-ce que Feign?

Feign est une bibliothèque client HTTP Java très simple. Évaluation de: star: 2745 sur github (au 2 avril 2018), il semble donc être une bibliothèque assez utilisée. Vous pouvez émettre une requête HTTP avec un code très court. Le flux lors de l'utilisation de "Feign" est le suivant.

Les inconvénients sont que seules les requêtes HTTP basées sur du texte peuvent être émises, et les réponses HTTP ne peuvent accéder qu'à BODY.

(Ajouté le 2018/4/8) Il n'est pas pris en charge par la valeur par défaut de Feign, mais vous pouvez gérer les requêtes HTTP binaires avec un autre module ou votre propre implémentation.

2. Préparation de la bibliothèque

«Fegin» est configuré pour que les composants utilisés puissent être remplacés. Cette fois, nous utiliserons ʻOkHttp, Jackson et Logback`.

pom.xml


<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
    <version>9.5.1</version>
</dependency>
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-jackson</artifactId>
    <version>9.5.1</version>
</dependency>
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-slf4j</artifactId>
    <version>9.5.1</version>
</dependency>
<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.2.3</version>
</dependency>

3. Définir l'interface API

Définissez l'API que vous souhaitez appeler en tant qu'interface.

Cette fois, j'aimerais examiner le cas de l'appel de l'API ci-dessous.

Numéro d'article chemin Méthode HTTP La description
1 /todos GET Obtenez tout TODO
2 /todos/{todoId} GET Obtient le TODO spécifié par todoId
3 /todos POST Créer un TODO avec les données transmises
Le type de contenu estapplication/jsonÀ
4 /todos/{todoId} PUT Mettre à jour le TODO spécifié par todoId
Le type de contenu estapplication/jsonÀ
5 /todos/{todoId} DELETE Supprimer le TODO spécifié par todoId

Le point de terminaison de l'API (URL) est http: // localhost: 8090 / todo-rest / api / v1.

TodoApi.java


package com.example.feign.demo;

import java.util.List;

import feign.Headers;
import feign.Param;
import feign.RequestLine;

public interface TodoApi {

    @RequestLine("GET /todos")
    List<Todo> findAll();
    
    @RequestLine("GET /todos/{todoId}")
    Todo getTodo(@Param("todoId") String todoId);
    
    @RequestLine("POST /todos")
    @Headers("Content-Type: application/json")
    Todo createTodo(Todo todo);

    @RequestLine("PUT /todos/{todoId}")
    @Headers("Content-Type: application/json")
    Todo updateTodo(@Param("todoId") String todoId, Todo todo);
    
    @RequestLine("DELETE /todos/{todoId}")
    void deleteTodo(@Param("todoId") String todoId);
}

4. Créez et exécutez une instance d'API dans Feign

J'ai défini l'interface API, mais pas sa classe d'implémentation. Une instance de l'API est créée avec Feign. L'appel de l'API exécute simplement les méthodes de l'interface.

TodoApiDemo.java


package com.example.feign.demo;

import java.util.List;

import feign.Feign;
import feign.Logger;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import feign.okhttp.OkHttpClient;
import feign.slf4j.Slf4jLogger;

public class TodoApiDemo {

    public static void main(String[] args) {
        // 1. create instance of api interface with feign 
        TodoApi todoApi = Feign.builder()      // builder call at first
                .client(new OkHttpClient())    // use OkHttpClient of feign
                .encoder(new JacksonEncoder()) // use Jackson of feign
                .decoder(new JacksonDecoder()) // use Jackson of feign
                .logger(new Slf4jLogger())     // use Slf4j of feign
                .logLevel(Logger.Level.FULL)   // setting log level to most detail
                .target(TodoApi.class, 
                        "http://localhost:8090/todo-rest/api/v1");
        
        // 2. call api [GET /todos]
        List<Todo> todos = todoApi.findAll();
        System.out.println(todos);
    }
}

Une méthode de configuration dédiée est fournie pour créer une instance avec le modèle Builder.

5. Exemple de test API (bonus)

Ce n'est pas difficile à appeler car il n'appelle que la méthode de l'instance d'API, mais pour référence, je décrirai l'exemple de test d'API. Le but étant d'utiliser «Feign», le contenu du test lui-même est approprié.

TodoApiTest.java


package com.example.feign.demo;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;

import java.util.Date;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import feign.Feign;
import feign.Logger;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import feign.okhttp.OkHttpClient;
import feign.slf4j.Slf4jLogger;

public class TodoApiTest {

    // test api
    TodoApi todoApi;
    
    private <T> T factory(Class<T> apiType, String url) {
        return Feign.builder()                 // builder call at first
                .client(new OkHttpClient())    // use OkHttpClient of feign
                .encoder(new JacksonEncoder()) // use Jackson of feign
                .decoder(new JacksonDecoder()) // use Jackson of feign
                .logger(new Slf4jLogger())     // use Slf4j
                .logLevel(Logger.Level.FULL)   // setting log level to most detail
                .target(apiType, url);
    }

    @Before
    public void setUp() throws Exception {
        todoApi = factory(TodoApi.class,
                "http://localhost:8090/todo-rest/api/v1");
    }

    @Test
    public void testFindAll() {
        List<Todo> todos = todoApi.findAll();
        System.out.println(todos);
        assertThat(todos.size(), is(2));
    }

    @Test
    public void testCreateTodo() {
        Todo todo = new Todo();
        todo.setTodoTitle("hello");
        Todo registeredTodo = todoApi.createTodo(todo);
        System.out.println(registeredTodo);
    }

    @Test
    public void testGetTodo() {
        String todoId = "36e06987-ef33-436a-a2c6-d215096ee902";
        Todo todo = todoApi.getTodo(todoId);
        System.out.println(todo);
        assertThat(todo.getTodoId(), is(todoId));
    }

    @Test
    public void testUpdateTodo() {
        String todoId = "36e06987-ef33-436a-a2c6-d215096ee902";
        String title = "update......";
        Todo todo = new Todo();
        todo.setTodoId(todoId);
        todo.setTodoTitle(title);
        todo.setCreatedAt(new Date());
        Todo updatedTodo = todoApi.updateTodo(todoId, todo);
        System.out.println(updatedTodo);
        assertThat(updatedTodo.getTodoId(), is(todoId));
        assertThat(updatedTodo.getTodoTitle(), is(title));
        assertThat(updatedTodo.isFinished(), is(true));
    }
    
    @Test
    public void testDeleteTodo() {
        String todoId = "36e06987-ef33-436a-a2c6-d215096ee902";
        todoApi.deleteTodo(todoId);
        System.out.println("ok");
    }
}

6. Enfin

Cette fois, j'ai expliqué à propos de Feign, qui est une bibliothèque pour le client HTTP Java. C'est une bibliothèque très facile à utiliser car c'est presque fait en définissant l'interface API. Bien que cela ne soit pas expliqué cette fois, «Feign» prend également en charge «JAXB» et «JAX-RS». Il existe une restriction selon laquelle seules les requêtes HTTP basées sur du texte peuvent être traitées, mais je voulais l'utiliser activement avec des API qui ne sont pas affectées par cela.

Recommended Posts

Feign, qui implémente un client API avec juste une interface, est très pratique!
Implémenter le client API avec juste des annotations à l'aide de Feign (OpenFeign)
Qu'est-ce qu'une interface
[swift5] Essayez de créer un client API avec différentes méthodes
Qu'est-ce qu'une API exactement?