Feignの紹介
1. 概要
このチュートリアルでは、Netflixによって開発された宣言型HTTPクライアントであるFeignを紹介します。
Feignは、HTTPAPIクライアントを簡素化することを目的としています。 簡単に言えば、開発者は、実際の実装が実行時にプロビジョニングされている間、インターフェースを宣言して注釈を付けるだけで済みます。
2. 例
このチュートリアルでは、RESTAPIエンドポイントを公開する書店アプリケーションの例を使用します。
プロジェクトのクローンを簡単に作成して、ローカルで実行できます。
mvn install spring-boot:run
3. 設定
まず、必要な依存関係を追加しましょう。
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>10.11</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
<version>10.11</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-slf4j</artifactId>
<version>10.11</version>
</dependency>
feign-core 依存関係(これもプルインされます)に加えて、いくつかのプラグインを使用します。特に、SquareのOkHttpを内部的に使用するためのfeign-okhttpです。リクエストを行うクライアント。GoogleのGSONをJSONプロセッサとして使用する場合はfeign-gson、リクエストをログに記録するために Simple LoggingFacadeを使用する場合はfeign-slf4j。
実際にログ出力を取得するには、クラスパスに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
}
注:JSONプロセッサーには少なくとも「引数なしのコンストラクター」が必要です。
実際、RESTプロバイダーはハイパーメディア駆動型API 、であるため、さらに単純なラッパークラスが必要になります。
public class BookResource {
private Book book;
// standard constructor, getters and setters
}
注: We ‘は、 BookResource をシンプルに保ちます。これは、サンプルのFeignクライアントがハイパーメディア機能の恩恵を受けていないためです。
4. サーバ側
Feignクライアントを定義する方法を理解するために、まず、RESTプロバイダーでサポートされているメソッドと応答のいくつかを調べます。
簡単なcurlshellコマンドを使用して、すべての本を一覧表示してみましょう。 すべての呼び出しの前に/api を付けることを忘れないでください。これは、アプリケーションのサーブレットコンテキストです。
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"
}
]
}
]
getリクエストにISBNを追加することで、個々のBookリソースをクエリすることもできます。
curl http://localhost:8081/api/books/1447264533
5. 偽のクライアント
最後に、Feignクライアントを定義しましょう。
@RequestLine アノテーションを使用して、HTTP動詞とパス部分を引数として指定します。 パラメータは、@Paramアノテーションを使用してモデル化されます。
public interface BookClient {
@RequestLine("GET /{isbn}")
BookResource findByIsbn(@Param("isbn") String isbn);
@RequestLine("GET")
List<BookResource> findAll();
@RequestLine("POST")
@Headers("Content-Type: application/json")
void create(Book book);
}
注:偽のクライアントは、テキストベースのHTTP APIのみを使用できます。つまり、バイナリデータを処理できません。 ファイルのアップロードまたはダウンロード。
これですべてです!次に、 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. 単体テスト
クライアントをテストするための3つのテストケースを作成しましょう。 org.hamcrest.CoreMatchers。*およびorg.junit.Assert。*には静的インポートを使用することに注意してください。
@Test
public void givenBookClient_shouldRunSuccessfully() throws Exception {
List<Book> 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. 参考文献
サービスが利用できない場合に何らかのフォールバックが必要な場合は、 HystrixFeign をクラスパスに追加し、 HystrixFeign.builder()を使用してクライアントを構築できます。
Hystrixの詳細については、この専用チュートリアルシリーズをご覧ください。
さらに、Spring Cloud Netflix HystrixをFeignと統合したい場合は、こちらに専用の記事があります。
さらに、クライアント側の負荷分散やサービス検出をクライアントに追加することもできます。
これは、 Ribbon をクラスパスに追加し、次のようにビルダーを使用することで実現できます。
BookClient bookClient = Feign.builder()
.client(RibbonClient.create())
.target(BookClient.class, "http://localhost:8081/api/books");
サービスディスカバリでは、Spring CloudNetflixEurekaを有効にしてサービスを構築する必要があります。 次に、Spring CloudNetflixFeignと統合するだけです。 その結果、リボンの負荷分散を無料で利用できます。 これについての詳細はここで見つけることができます。
8. 結論
この記事では、Feignを使用して宣言型HTTPクライアントを構築し、テキストベースのAPIを使用する方法について説明しました。
いつものように、このチュートリアルに示されているすべてのコードサンプルはGitHubで入手できます。