Введение в Feign

Вступление к симуляции

1. обзор

В этом руководстве мы представим и объяснимFeign, декларативный клиентHTTP, разработанный Netflix.

Feign направлен на упрощение клиентовHTTP API. Проще говоря, разработчику нужно только объявить и аннотировать интерфейс, в то время как фактическая реализация будет обеспечена во время выполнения.

2. пример

Мы представим пример службы книжного магазинаREST API, которая запрашивается и тестируется на основе клиентаFeignHTTP.

Прежде чем мы создадим образец клиентаFeign, мы добавим необходимые зависимости и запустим службуREST.

Пример службы книжного магазина можно клонировать изhere.

После загрузки служебного приложения мы запустим его:

$> mvn install spring-boot:run

3. Настроить

Сначала мы создадим новый проектMaven и включим следующие зависимости:


    io.github.openfeign
    feign-okhttp
    9.3.1


    io.github.openfeign
    feign-gson
    9.3.1


    io.github.openfeign
    feign-slf4j
    9.3.1

Помимо зависимостиfeign-core (которая также втягивается), мы будем использовать несколько плагинов, в частности:feign-okhttp для внутреннего использования клиентаSquare’s OkHttp для выполнения запросов,feign-gson для используяGoogle’s GSON в качестве процессораJSON иfeign-slf4j для использованияSimple Logging Facade для регистрации запросов.

Чтобы получить какой-то вывод журнала, вам понадобится ваша любимая реализация логгера, поддерживаемаяSLF4J, в пути к классам.

Прежде чем мы продолжим создавать наш клиентский интерфейс, мы настроим модельBook для хранения наших данных:

public class Book {
    private String isbn;
    private String author;
    private String title;
    private String synopsis;
    private String language;

    // standard constructor, getters and setters
}

NOTE: ПроцессоруJSON необходим как минимум «конструктор без аргументов».

Фактически, наш поставщикREST - этоhypermedia-driven API,, поэтому нам понадобится простой класс-оболочка:

public class BookResource {
    private Book book;

    // standard constructor, getters and setters
}

Note: МысохранимBookResource простым, потому что наш клиентFeign не использует возможности гипермедиа!

4. Сторона сервера

Чтобы понять, как определить клиентаFeign, мы сначала рассмотрим некоторые методы и ответы, поддерживаемые нашим поставщикомREST.

Давайте попробуем с помощью простой команды оболочкиcurl, чтобы вывести список всех книг. Не забывайте ставить перед звонками префикс‘/api', который представляет собойservlet-context, определенный вapplication.properties:

$> curl http://localhost:8081/api/books

мы получим полное хранилище книг в видеJSON:

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

  ...

  {
    "book": {
      "isbn": "0451524934",
      "author": "George Orwell",
      "title": "1984",
      "synopsis": null,
      "language": null
    },
    "links": [
      {
        "rel": "self",
        "href": "http://localhost:8081/api/books/0451524934"
      }
    ]
  }
]

Мы также можем запросить отдельный ресурсBook, добавивISBN к запросу на получение:

$> curl http://localhost:8081/api/books/1447264533

5. Имитировать клиента

Теперь мы определим нашего клиентаFeign.

Мы будем использовать аннотацию@RequestLine, чтобы указатьHTTP verb и часть пути в качестве аргумента, а параметры будут смоделированы с использованием аннотации@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);
}

NOTE: клиентов Feign можно использовать только для использования текстовых HTTP API, что означает, что они не могут обрабатывать двоичные данные, например загрузка файла или загрузки.

That’s all! Теперь мы будем использоватьFeign.builder() для настройки нашего клиента на основе интерфейса. Фактическая реализация будет обеспечена во время выполнения:

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, "http://localhost:8081/api/books");

Feign поддерживает различные плагины, такие как кодировщики и декодерыJSON /XML или базовый клиентHTTP для выполнения запросов.

6. Модульный тест

Давайте создадим класс модульного тестирования, содержащий три метода@Test, для тестирования нашего клиента. В тесте будет использоваться статический импорт из пакетовorg.hamcrest.CoreMatchers.* и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"));
}

Эти тесты довольно очевидны. Чтобы запустить его, просто выполните цель Maventest:

$> mvn test

7. Дальнейшее чтение

Если вам нужен какой-то запасной вариант, в случае недоступности службы вы можете добавитьHystrixFeign к вашемуclasspath и вместо этого создать свой клиент сHystrixFeign.builder().

Чтобы узнать больше оHystrix, подпишитесь наthis dedicated tutorial series.

Если вы хотите интегрироватьSpring Cloud Netflix Hystrix сFeign, вы можете узнать больше об этомhere.

Также можно добавить клиенту балансировку нагрузки и / или обнаружение служб.

Первый делается путем добавленияRibbon в путь к классам и вызова построителя следующим образом:

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

Для обнаружения службы необходимо создать службу с включеннымSpring Cloud Netflix Eureka. Затем просто интегрируйтесь сSpring Cloud Netflix Feign, и вы получите балансировку нагрузкиRibbon бесплатно. Подробнее об этом можно прочитать вhere.

8. Заключение

В этой статье объясняется, как создать декларативный клиентHTTP с использованиемFeign для использования текстовыхAPIs.

Как обычно, вы найдете источникиon GitHub.