先日の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>
spring-cloud-starter-openfeignを依存関係に追加してください。
FeignConfig.java
@Configuration(proxyBeanMethods = false) @EnableFeignClients(basePackages = {"com.b1a9idps.consumer.client"}) public class FeignConfig {}
@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); }
クライアントインターフェースを用意します。コントローラを実装する感覚でインターフェースを書くことができます。
インターフェースに @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("寫樂", "宮泉銘醸")); } }
クライアントを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": "高木酒造" } ]
補足
リクエストログをみたい
logging.level.[clientが置いてあるパッケージ]=debug feign.client.config.default.logger-level=basic