All Articles

Spring Cloud OpenFeignで遊ぶ

先日のSpring Oneで、Unleash the True Power of Spring Cloud: Learn How to Customize Spring Cloudで紹介されていたSpring Cloud OpenFeignで遊んでみました。 素敵すぎて、もっと早く知りたかった…と感じました。

Spring Cloud OpenFeignとは

2018年6月にリリースされたSpring BootのためのOpenFeignインテグレーションです。
Spring Cloud OpenFeignを使うと宣言的にRESTクライアントを作成することができます。

Links

サンプルコード

サンプルで使用しているライブラリ等は次の通りです。

Java 11
Maven
Spring Boot 2.3.3.RELEASE
Spring MVC
Spring Cloud OpenFeign 2.2.5.RELEASE

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>
...
</project>
view raw pom.xml hosted with ❤ by GitHub

spring-cloud-starter-openfeignを依存関係に追加してください。

FeignConfig.java

@Configuration(proxyBeanMethods = false)
@EnableFeignClients(basePackages = {"com.b1a9idps.consumer.client"})
public class FeignConfig {}
view raw FeignConfig.java hosted with ❤ by GitHub

@EnableFeignClients を付与することでデフォルト設定を使うことができるようになります。

SakeClient.java

@FeignClient(value = "sakes", url = "${producer.url}")
public interface SakeClient {
@GetMapping(value = "/sakes")
List<SakeResponse> list();
@GetMapping(value = "/sakes/{id}")
SakeResponse get(@PathVariable Integer id);
@PostMapping(value = "/sakes")
SakeResponse create(SakeCreateRequest request);
}
view raw SakeClient.java hosted with ❤ by GitHub

クライアントインターフェースを用意します。コントローラを実装する感覚でインターフェースを書くことができます。
インターフェースに @FeignClient を付与して、コンポーネントスキャンの対象にします。

@FeignClientのプロパティ
- url:リクエスト先のURL。
- name(value):任意のクライアント名。RibbonロードバランサーやSpring Cloud LoadBalancerを利用する際に使われる。

SakeController.java

@RestController
@RequestMapping("/sakes")
public class SakeController {
final SakeClient sakeClient;
public SakeController(SakeClient sakeClient) {
this.sakeClient = sakeClient;
}
@GetMapping
public List<SakeResponse> list() {
return sakeClient.list();
}
@GetMapping("{id}")
public SakeResponse get(@PathVariable Integer id) {
return sakeClient.get(id);
}
@PostMapping
public SakeResponse create() {
return sakeClient.create(new SakeCreateRequest("寫樂", "宮泉銘醸"));
}
}
view raw SakeController.java hosted with ❤ by GitHub

クライアントをDIしてメソッドコールするだけです。

実行結果

アプリケーションを起動してcurlでAPIを叩いた結果です。

$ curl -v http://localhost:8080/api/sakes | jq .
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /api/sakes HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Fri, 04 Sep 2020 04:12:38 GMT
<
{ [172 bytes data]
100 166 0 166 0 0 14628 0 --:--:-- --:--:-- --:--:-- 15090
* Connection #0 to host localhost left intact
[
{
"id": 1,
"name": "若波",
"brewingName": "若波酒造"
},
{
"id": 2,
"name": "新政",
"brewingName": "新政酒造"
},
{
"id": 3,
"name": "十四代",
"brewingName": "高木酒造"
}
]
view raw result.txt hosted with ❤ by GitHub