REST サービスの呼び出し
Spring Boot は、リモート REST サービスを呼び出すための様々な便利な方法を提供します。ノンブロッキングのリアクティブアプリケーションを開発していて、Spring または WebFlux を使用している場合は、WebClient (Javadoc) を使用できます。命令型 API をご希望の場合は、RestClient (Javadoc) または RestTemplate (Javadoc) を使用できます。
WebClient
クラスパスに Spring または WebFlux がある場合は、WebClient (Javadoc) を使用して リモート REST サービスを呼び出すことをお勧めします。WebClient (Javadoc) インターフェースは関数型 API を提供し、完全にリアクティブです。WebClient (Javadoc) の詳細については、Spring Framework ドキュメントの専用セクションを参照してください。
リアクティブ型の Spring、WebFlux アプリケーションを作成していない場合は、WebClient (Javadoc) の代わりに RestClient を使用できます。これは同様の関数 API を提供しますが、リアクティブ型ではなく命令型です。 |
Spring Boot は、プロトタイプ WebClient.Builder (Javadoc) Bean を作成し、事前構成します。これをコンポーネントに挿入し、WebClient (Javadoc) インスタンスの作成に使用することを強くお勧めします。Spring Boot は、HTTP リソースを共有し、サーバーのものと同じ方法でコーデックの設定を反映するようにビルダーを構成します (WebFlux HTTP コーデックの自動構成を参照)。
次のコードは典型的な例を示しています。
Java
Kotlin
import reactor.core.publisher.Mono;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
@Service
public class MyService {
private final WebClient webClient;
public MyService(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://example.org").build();
}
public Mono<Details> someRestCall(String name) {
return this.webClient.get().uri("/{name}/details", name).retrieve().bodyToMono(Details.class);
}
}import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Mono
@Service
class MyService(webClientBuilder: WebClient.Builder) {
private val webClient: WebClient
init {
webClient = webClientBuilder.baseUrl("https://example.org").build()
}
fun someRestCall(name: String): Mono<Details> {
return webClient.get().uri("/{name}/details", name)
.retrieve().bodyToMono(Details::class.java)
}
}WebClient ランタイム
Spring Boot は、アプリケーションクラスパスで使用可能なライブラリに応じて、WebClient (Javadoc) を駆動するために使用する ClientHttpConnector (Javadoc) を自動検出します。優先順位に従って、次のクライアントがサポートされます。
Reactor Netty
Jetty RS クライアント
Apache HttpClient
JDK HttpClient
クラスパス上で複数のクライアントが使用可能な場合は、最も優先されるクライアントが使用されます。
spring-boot-starter-webflux スターターは、デフォルトで io.projectreactor.netty:reactor-netty に依存しており、サーバーとクライアントの両方の実装をもたらします。代わりにリアクティブサーバーとして Jetty を使用することを選択した場合は、Jetty リアクティブ HTTP クライアントライブラリ org.eclipse.jetty:jetty-reactive-httpclient への依存関係を追加する必要があります。サーバーとクライアントに同じテクノロジーを使用すると、クライアントとサーバー間で HTTP リソースが自動的に共有されるため、利点があります。
開発者は、カスタム ReactorResourceFactory (Javadoc) または JettyResourceFactory (Javadoc) Bean を提供することで、Jetty および Reactor Netty のリソース構成をオーバーライドできます。これは、クライアントとサーバーの両方に適用されます。
クライアントの選択を上書きする場合は、独自の ClientHttpConnector (Javadoc) Bean を定義して、クライアント構成を完全に制御できます。
Spring Framework リファレンスドキュメントの WebClient 構成オプションについて詳しく知ることができます。
グローバル HTTP コネクター構成
自動検出された ClientHttpConnector (Javadoc) がニーズを満たさない場合は、spring.http.clients.reactive.connector プロパティを使用して特定のコネクターを選択できます。例: クラスパスに Reactor と Netty があるが、Jetty の HttpClient (英語) を使用する場合は、以下を追加できます。
プロパティ
YAML
spring.http.clients.reactive.connector=jettyspring:
http:
clients:
reactive:
connector: jetty| すべての HTTP クライアントに適用されるグローバル構成プロパティを使用することもできます。 |
より複雑なカスタマイズが必要な場合は、ClientHttpConnectorBuilderCustomizer (Javadoc) を使用するか、独自の ClientHttpConnectorBuilder (Javadoc) Bean を宣言することで自動構成を無効化できます。これは、基盤となる HTTP ライブラリの内部構造をカスタマイズする必要がある場合に便利です。
例: 以下は、特定の ProxySelector (標準 Javadoc) で構成された JDK クライアントを使用します。
Java
Kotlin
import java.net.ProxySelector;
import org.springframework.boot.http.client.reactive.ClientHttpConnectorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyConnectorHttpConfiguration {
@Bean
ClientHttpConnectorBuilder<?> clientHttpConnectorBuilder(ProxySelector proxySelector) {
return ClientHttpConnectorBuilder.jdk().withHttpClientCustomizer((builder) -> builder.proxy(proxySelector));
}
}import org.springframework.boot.http.client.reactive.ClientHttpConnectorBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.net.ProxySelector
@Configuration(proxyBeanMethods = false)
class MyConnectorHttpConfiguration {
@Bean
fun clientHttpConnectorBuilder(proxySelector: ProxySelector): ClientHttpConnectorBuilder<*> {
return ClientHttpConnectorBuilder.jdk().withHttpClientCustomizer { builder -> builder.proxy(proxySelector) }
}
}WebClient のカスタマイズ
WebClient (Javadoc) のカスタマイズには、カスタマイズをどの程度広範囲に適用するかに応じて、主に 3 つのアプローチがあります。
カスタマイズの範囲をできるだけ狭くするには、自動構成された WebClient.Builder (Javadoc) を挿入し、必要に応じてそのメソッドを呼び出します。WebClient.Builder (Javadoc) インスタンスはステートフルです。つまり、ビルダーの変更は、その後に作成されるすべてのクライアントに反映されます。同じビルダーで複数のクライアントを作成する場合は、WebClient.Builder other = builder.clone(); を使用してビルダーを複製することも検討できます。
アプリケーション全体ですべての WebClient.Builder (Javadoc) インスタンスに追加のカスタマイズを行うには、WebClientCustomizer (Javadoc) Bean を宣言し、注入時点で WebClient.Builder (Javadoc) をローカルに変更できます。
最後に、元の API にフォールバックして WebClient.create() を使用することもできます。その場合、自動構成や WebClientCustomizer (Javadoc) は適用されません。
WebClient SSL サポート
WebClient (Javadoc) で使用される ClientHttpConnector (Javadoc) でカスタム SSL 構成が必要な場合は、ビルダーの apply メソッドで使用できる WebClientSsl (Javadoc) インスタンスを挿入できます。
WebClientSsl (Javadoc) インターフェースは、application.properties または application.yaml ファイルで定義した任意の SSL バンドルへのアクセスを提供します。
次のコードは典型的な例を示しています。
Java
Kotlin
import reactor.core.publisher.Mono;
import org.springframework.boot.webclient.autoconfigure.WebClientSsl;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
@Service
public class MyService {
private final WebClient webClient;
public MyService(WebClient.Builder webClientBuilder, WebClientSsl ssl) {
this.webClient = webClientBuilder.baseUrl("https://example.org").apply(ssl.fromBundle("mybundle")).build();
}
public Mono<Details> someRestCall(String name) {
return this.webClient.get().uri("/{name}/details", name).retrieve().bodyToMono(Details.class);
}
}import org.springframework.boot.webclient.autoconfigure.WebClientSsl
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Mono
@Service
class MyService(webClientBuilder: WebClient.Builder, ssl: WebClientSsl) {
private val webClient: WebClient
init {
webClient = webClientBuilder.baseUrl("https://example.org")
.apply(ssl.fromBundle("mybundle")).build()
}
fun someRestCall(name: String): Mono<Details> {
return webClient.get().uri("/{name}/details", name)
.retrieve().bodyToMono(Details::class.java)
}
}RestClient
アプリケーションで Spring、WebFlux、プロジェクト Reactor を使用していない場合は、RestClient (Javadoc) を使用して リモート REST サービスを呼び出すことをお勧めします。
RestClient (Javadoc) インターフェースは、関数型の命令型 API を提供します。
Spring Boot は、プロトタイプ RestClient.Builder (Javadoc) Bean を作成し、事前構成します。これをコンポーネントに挿入し、それを使用して RestClient (Javadoc) インスタンスを作成することを強くお勧めします。Spring Boot は、そのビルダーを HttpMessageConverters (Javadoc) と適切な ClientHttpRequestFactory (Javadoc) で構成しています。
次のコードは典型的な例を示しています。
Java
Kotlin
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
@Service
public class MyService {
private final RestClient restClient;
public MyService(RestClient.Builder restClientBuilder) {
this.restClient = restClientBuilder.baseUrl("https://example.org").build();
}
public Details someRestCall(String name) {
return this.restClient.get().uri("/{name}/details", name).retrieve().body(Details.class);
}
}import org.springframework.boot.docs.io.restclient.restclient.ssl.Details
import org.springframework.stereotype.Service
import org.springframework.web.client.RestClient
@Service
class MyService(restClientBuilder: RestClient.Builder) {
private val restClient: RestClient
init {
restClient = restClientBuilder.baseUrl("https://example.org").build()
}
fun someRestCall(name: String): Details {
return restClient.get().uri("/{name}/details", name)
.retrieve().body(Details::class.java)!!
}
}RestClient のカスタマイズ
RestClient (Javadoc) のカスタマイズには、カスタマイズをどの程度広範囲に適用するかに応じて、主に 3 つのアプローチがあります。
カスタマイズの範囲をできるだけ狭くするには、自動構成された RestClient.Builder (Javadoc) を挿入し、必要に応じてそのメソッドを呼び出します。RestClient.Builder (Javadoc) インスタンスはステートフルです。つまり、ビルダーの変更は、その後に作成されるすべてのクライアントに反映されます。同じビルダーで複数のクライアントを作成する場合は、RestClient.Builder other = builder.clone(); を使用してビルダーを複製することも検討できます。
アプリケーション全体ですべての RestClient.Builder (Javadoc) インスタンスに追加のカスタマイズを行うには、RestClientCustomizer (Javadoc) Bean を宣言し、注入時点で RestClient.Builder (Javadoc) をローカルに変更できます。
最後に、元の API にフォールバックして RestClient.create() を使用することもできます。その場合、自動構成や RestClientCustomizer (Javadoc) は適用されません。
| グローバル HTTP クライアント構成を変更することもできます。 |
RestClient SSL サポート
RestClient (Javadoc) で使用される ClientHttpRequestFactory (Javadoc) でカスタム SSL 構成が必要な場合は、ビルダーの apply メソッドで使用できる RestClientSsl (Javadoc) インスタンスを挿入できます。
RestClientSsl (Javadoc) インターフェースは、application.properties または application.yaml ファイルで定義した任意の SSL バンドルへのアクセスを提供します。
次のコードは典型的な例を示しています。
Java
Kotlin
import org.springframework.boot.restclient.autoconfigure.RestClientSsl;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
@Service
public class MyService {
private final RestClient restClient;
public MyService(RestClient.Builder restClientBuilder, RestClientSsl ssl) {
this.restClient = restClientBuilder.baseUrl("https://example.org").apply(ssl.fromBundle("mybundle")).build();
}
public Details someRestCall(String name) {
return this.restClient.get().uri("/{name}/details", name).retrieve().body(Details.class);
}
}import org.springframework.boot.docs.io.restclient.restclient.ssl.settings.Details
import org.springframework.boot.restclient.autoconfigure.RestClientSsl
import org.springframework.stereotype.Service
import org.springframework.web.client.RestClient
@Service
class MyService(restClientBuilder: RestClient.Builder, ssl: RestClientSsl) {
private val restClient: RestClient
init {
restClient = restClientBuilder.baseUrl("https://example.org")
.apply(ssl.fromBundle("mybundle")).build()
}
fun someRestCall(name: String): Details {
return restClient.get().uri("/{name}/details", name)
.retrieve().body(Details::class.java)!!
}
}SSL バンドルに加えて他のカスタマイズを適用する必要がある場合は、ClientHttpRequestFactoryBuilder (Javadoc) とともに HttpClientSettings (Javadoc) クラスを使用できます。
Java
Kotlin
import java.time.Duration;
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
import org.springframework.boot.http.client.HttpClientSettings;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
@Service
public class MyService {
private final RestClient restClient;
public MyService(RestClient.Builder restClientBuilder, SslBundles sslBundles) {
HttpClientSettings settings = HttpClientSettings.ofSslBundle(sslBundles.getBundle("mybundle"))
.withReadTimeout(Duration.ofMinutes(2));
ClientHttpRequestFactory requestFactory = ClientHttpRequestFactoryBuilder.detect().build(settings);
this.restClient = restClientBuilder.baseUrl("https://example.org").requestFactory(requestFactory).build();
}
public Details someRestCall(String name) {
return this.restClient.get().uri("/{name}/details", name).retrieve().body(Details.class);
}
}import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
import org.springframework.boot.http.client.HttpClientSettings
import org.springframework.boot.ssl.SslBundles
import org.springframework.stereotype.Service
import org.springframework.web.client.RestClient
import java.time.Duration
@Service
class MyService(restClientBuilder: RestClient.Builder, sslBundles: SslBundles) {
private val restClient: RestClient
init {
val settings = HttpClientSettings.defaults()
.withReadTimeout(Duration.ofMinutes(2))
.withSslBundle(sslBundles.getBundle("mybundle"))
val requestFactory = ClientHttpRequestFactoryBuilder.detect().build(settings);
restClient = restClientBuilder
.baseUrl("https://example.org")
.requestFactory(requestFactory).build()
}
fun someRestCall(name: String): Details {
return restClient.get().uri("/{name}/details", name).retrieve().body(Details::class.java)!!
}
}RestTemplate
Spring Framework の RestTemplate (Javadoc) クラスは RestClient (Javadoc) より古く、多くのアプリケーションが リモート REST サービスを呼び出すために使用する従来の方法です。RestClient (Javadoc) に移行したくない既存のコードがある場合、または RestTemplate (Javadoc) API にすでに精通している場合は、RestTemplate (Javadoc) を使用することを選択できます。
RestTemplate (Javadoc) インスタンスは使用前にカスタマイズする必要があることが多いため、Spring Boot は単一の自動構成された RestTemplate (Javadoc) Bean を提供しません。ただし、必要に応じて RestTemplate (Javadoc) インスタンスを作成するために使用できる RestTemplateBuilder (Javadoc) は自動構成されます。自動構成された RestTemplateBuilder (Javadoc) により、適切な HttpMessageConverters (Javadoc) と適切な ClientHttpRequestFactory (Javadoc) が RestTemplate (Javadoc) インスタンスに適用されます。
次のコードは典型的な例を示しています。
Java
Kotlin
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class MyService {
private final RestTemplate restTemplate;
public MyService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
public Details someRestCall(String name) {
return this.restTemplate.getForObject("/{name}/details", Details.class, name);
}
}import org.springframework.boot.restclient.RestTemplateBuilder
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate
@Service
class MyService(restTemplateBuilder: RestTemplateBuilder) {
private val restTemplate: RestTemplate
init {
restTemplate = restTemplateBuilder.build()
}
fun someRestCall(name: String): Details {
return restTemplate.getForObject("/{name}/details", Details::class.java, name)!!
}
}RestTemplateBuilder (Javadoc) には、RestTemplate (Javadoc) をすばやく構成するために使用できる便利なメソッドが多数含まれています。たとえば、BASIC 認証サポートを追加するには、builder.basicAuthentication("user", "password").build() を使用できます。
RestTemplate のカスタマイズ
RestTemplate (Javadoc) のカスタマイズには、カスタマイズをどの程度広範囲に適用するかに応じて、主に 3 つのアプローチがあります。
カスタマイズの範囲をできるだけ狭くするには、自動構成された RestTemplateBuilder (Javadoc) を挿入し、必要に応じてそのメソッドを呼び出します。各メソッド呼び出しは新しい RestTemplateBuilder (Javadoc) インスタンスを返すため、カスタマイズはビルダーのこの使用にのみ影響します。
アプリケーション全体にわたる追加カスタマイズを行うには、RestTemplateCustomizer (Javadoc) Bean を使用します。このような Bean はすべて、自動構成された RestTemplateBuilder (Javadoc) に自動的に登録され、それを使用して構築されたすべてのテンプレートに適用されます。
次の例は、192.168.0.5 を除くすべてのホストに対してプロキシの使用を構成するカスタマイザーを示しています。
Java
Kotlin
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
import org.apache.hc.client5.http.routing.HttpRoutePlanner;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.springframework.boot.restclient.RestTemplateCustomizer;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
public class MyRestTemplateCustomizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
HttpRoutePlanner routePlanner = new CustomRoutePlanner(new HttpHost("proxy.example.com"));
HttpClient httpClient = HttpClientBuilder.create().setRoutePlanner(routePlanner).build();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
}
static class CustomRoutePlanner extends DefaultProxyRoutePlanner {
CustomRoutePlanner(HttpHost proxy) {
super(proxy);
}
@Override
protected HttpHost determineProxy(HttpHost target, HttpContext context) throws HttpException {
if (target.getHostName().equals("192.168.0.5")) {
return null;
}
return super.determineProxy(target, context);
}
}
}import org.apache.hc.client5.http.classic.HttpClient
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder
import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner
import org.apache.hc.client5.http.routing.HttpRoutePlanner
import org.apache.hc.core5.http.HttpException
import org.apache.hc.core5.http.HttpHost
import org.apache.hc.core5.http.protocol.HttpContext
import org.springframework.boot.restclient.RestTemplateCustomizer
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
import org.springframework.web.client.RestTemplate
class MyRestTemplateCustomizer : RestTemplateCustomizer {
override fun customize(restTemplate: RestTemplate) {
val routePlanner: HttpRoutePlanner = CustomRoutePlanner(HttpHost("proxy.example.com"))
val httpClient: HttpClient = HttpClientBuilder.create().setRoutePlanner(routePlanner).build()
restTemplate.requestFactory = HttpComponentsClientHttpRequestFactory(httpClient)
}
internal class CustomRoutePlanner(proxy: HttpHost?) : DefaultProxyRoutePlanner(proxy) {
@Throws(HttpException::class)
public override fun determineProxy(target: HttpHost, context: HttpContext): HttpHost? {
if (target.hostName == "192.168.0.5") {
return null
}
return super.determineProxy(target, context)
}
}
} 最後に、独自の RestTemplateBuilder (Javadoc) Bean を定義できます。これにより、自動構成されたビルダーが置き換えられます。自動構成で実行されたように、カスタムビルダーに RestTemplateCustomizer (Javadoc) Bean を適用する場合は、RestTemplateBuilderConfigurer (Javadoc) を使用して構成します。次の例では、カスタム接続および読み取りタイムアウトも指定されていることを除いて、Spring Boot の自動構成で実行されたものと一致する RestTemplateBuilder (Javadoc) を公開します。
Java
Kotlin
import java.time.Duration;
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.boot.restclient.autoconfigure.RestTemplateBuilderConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyRestTemplateBuilderConfiguration {
@Bean
public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer configurer) {
return configurer.configure(new RestTemplateBuilder())
.connectTimeout(Duration.ofSeconds(5))
.readTimeout(Duration.ofSeconds(2));
}
}import org.springframework.boot.restclient.autoconfigure.RestTemplateBuilderConfigurer
import org.springframework.boot.restclient.RestTemplateBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.time.Duration
@Configuration(proxyBeanMethods = false)
class MyRestTemplateBuilderConfiguration {
@Bean
fun restTemplateBuilder(configurer: RestTemplateBuilderConfigurer): RestTemplateBuilder {
return configurer.configure(RestTemplateBuilder()).connectTimeout(Duration.ofSeconds(5))
.readTimeout(Duration.ofSeconds(2))
}
} 最も極端な(そしてめったに使用されない)オプションは、コンフィギュラを使用せずに独自の RestTemplateBuilder (Javadoc) Bean を作成することです。これにより、自動構成されたビルダーが置き換えられるだけでなく、RestTemplateCustomizer (Javadoc) Bean が使用されなくなります。
| グローバル HTTP クライアント構成を変更することもできます。 |
RestTemplate SSL サポート
RestTemplate (Javadoc) でカスタム SSL 構成が必要な場合は、次の例に示すように、SSL バンドルを RestTemplateBuilder (Javadoc) に適用できます。
Java
Kotlin
import org.springframework.boot.docs.io.restclient.resttemplate.Details;
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class MyService {
private final RestTemplate restTemplate;
public MyService(RestTemplateBuilder restTemplateBuilder, SslBundles sslBundles) {
this.restTemplate = restTemplateBuilder.sslBundle(sslBundles.getBundle("mybundle")).build();
}
public Details someRestCall(String name) {
return this.restTemplate.getForObject("/{name}/details", Details.class, name);
}
}import org.springframework.boot.docs.io.restclient.resttemplate.Details
import org.springframework.boot.ssl.SslBundles
import org.springframework.boot.restclient.RestTemplateBuilder
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate
@Service
class MyService(restTemplateBuilder: RestTemplateBuilder, sslBundles: SslBundles) {
private val restTemplate: RestTemplate
init {
restTemplate = restTemplateBuilder.sslBundle(sslBundles.getBundle("mybundle")).build()
}
fun someRestCall(name: String): Details {
return restTemplate.getForObject("/{name}/details", Details::class.java, name)!!
}
}RestClient および RestTemplate の HTTP クライアントの検出
Spring Boot は、アプリケーションクラスパスで使用可能なライブラリに応じて、RestClient (Javadoc) および RestTemplate (Javadoc) で使用する HTTP クライアントを自動検出します。優先順位に従って、次のクライアントがサポートされます。
Apache HttpClient
Jetty HttpClient
Reactor Netty HttpClient
JDK クライアント (
java.net.http.HttpClient)シンプルな JDK クライアント (
java.net.HttpURLConnection)
クラスパス上で複数のクライアントが使用可能であり、グローバル構成が指定されていない場合は、最も優先されるクライアントが使用されます。
グローバル HTTP クライアント構成
自動検出された HTTP クライアントがニーズを満たさない場合は、spring.http.clients.imperative.factory プロパティを使用して特定のファクトリを選択できます。例: クラスパスに Apache HttpClient があるが、Jetty の HttpClient (英語) を使用する場合は、以下を追加できます。
プロパティ
YAML
spring.http.clients.imperative.factory=jettyspring:
http:
clients:
imperative:
factory: jetty| すべての HTTP クライアントに適用されるグローバル構成プロパティを使用することもできます。 |
より複雑なカスタマイズが必要な場合は、ClientHttpRequestFactoryBuilderCustomizer (Javadoc) を使用するか、独自の ClientHttpRequestFactoryBuilder (Javadoc) Bean を宣言することで自動構成を無効化できます。これは、基盤となる HTTP ライブラリの内部構造をカスタマイズする必要がある場合に便利です。
例: 以下は、特定の ProxySelector (標準 Javadoc) で構成された JDK クライアントを使用します。
Java
Kotlin
import java.net.ProxySelector;
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyClientHttpConfiguration {
@Bean
ClientHttpRequestFactoryBuilder<?> clientHttpRequestFactoryBuilder(ProxySelector proxySelector) {
return ClientHttpRequestFactoryBuilder.jdk()
.withHttpClientCustomizer((builder) -> builder.proxy(proxySelector));
}
}import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.net.ProxySelector
@Configuration(proxyBeanMethods = false)
class MyClientHttpConfiguration {
@Bean
fun clientHttpRequestFactoryBuilder(proxySelector: ProxySelector): ClientHttpRequestFactoryBuilder<*> {
return ClientHttpRequestFactoryBuilder.jdk()
.withHttpClientCustomizer { builder -> builder.proxy(proxySelector) }
}
}API のバージョニング
WebClient と RestClient はどちらも、API を時間の経過とともに進化させることができるように、バージョン管理されたリモート HTTP 呼び出しをサポートしています。通常、これには、使用する API のバージョンを示す HTTP ヘッダー、クエリパラメーター、URL パスセグメントの送信が含まれます。
WebClient.Builder または RestClient.Builder のメソッドを使用して API のバージョン管理を構成できます。
| API のバージョン管理はサーバー側でもサポートされています。詳細については、Spring MVC および Spring WebFlux のセクションを参照してください。 |
| サーバー側の API バージョン管理設定は、クライアントの自動構成には考慮されません。API バージョン管理戦略を使用する必要があるクライアント(通常はテスト用)は、明示的に設定する必要があります。 |
HTTP サービスインターフェースクライアント
RestClient (Javadoc) または WebClient (Javadoc) を直接使用して HTTP サービスを呼び出す代わりに、アノテーション付き Java インターフェースを使用して呼び出すこともできます。
HTTP サービスインターフェースは、@HttpExchange (Javadoc) アノテーションが付けられたメソッド、またはより一般的にはメソッド固有のバリアント ( @GetExchange (Javadoc) 、@PostExchange (Javadoc) 、@DeleteExchange (Javadoc) など) を使用して、サービス契約を定義します。
例: 次のコードは、リクエストのエコーを含む JSON オブジェクトを返す "echo" API の HTTP サービスを定義します。
Java
Kotlin
import java.util.Map;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.service.annotation.HttpExchange;
import org.springframework.web.service.annotation.PostExchange;
@HttpExchange(url = "https://echo.zuplo.io")
public interface EchoService {
@PostExchange
Map<?, ?> echo(@RequestBody Map<String, String> message);
}import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.service.annotation.HttpExchange
import org.springframework.web.service.annotation.PostExchange
@HttpExchange(url = "https://echo.zuplo.io")
interface EchoService {
@PostExchange
fun echo(@RequestBody message: Map<String, String>): Map<*, *>
}HTTP サービスインターフェースクライアントの開発方法の詳細については、Spring Framework リファレンスドキュメントを参照してください。
HTTP サービスのインポート
HTTP サービスインターフェースをクライアントとして使用するには、インポートする必要があります。これを行うメソッドの一つは、通常はアプリケーションのメインクラスで @ImportHttpServices (Javadoc) アノテーションを使用することです。このアノテーションを使用して特定のクラスをインポートしたり、特定のパッケージからインポートするクラスをスキャンしたりできます。
例: 次の構成では、com.example.myclients パッケージ内の HTTP サービスインターフェースがスキャンされます。
Java
Kotlin
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.service.registry.ImportHttpServices;
@SpringBootApplication
@ImportHttpServices(basePackages = "com.example.myclients")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.web.service.registry.ImportHttpServices
@SpringBootApplication
@ImportHttpServices(basePackages = ["com.example.myclients"])
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args)
}サービスクライアントグループ
@HttpExchange (Javadoc) アノテーションに絶対 URL をハードコードすることは、多くの場合、本番環境のアプリケーションでは理想的ではありません。代わりに、通常はコード内で HTTP サービスクライアントに論理名を付与し、その名前に基づいてプロパティから URL を検索する方がよいでしょう。
HTTP サービスクライアントは、名前付きグループに登録することでこれを実現できます。HTTP サービスグループは、共通の機能を共有する HTTP サービスインターフェースの集合です。
たとえば、https://echo.zuplo.io を呼び出す HTTP サービスクライアントに使用する "echo" グループを定義する場合があります。
| HTTP サービスグループは、URL 以外にも様々な定義に使用できます。たとえば、接続タイムアウトや SSL 設定をグループで定義できます。また、必要な認証ヘッダーを挿入するコードを追加するなど、クライアントのカスタマイズロジックをグループに関連付けることもできます。 |
@ImportHttpServices (Javadoc) を使用するときに HTTP サービスインターフェースをグループに関連付けるには、group 属性を使用できます。
たとえば、上記の例が com.example.myclients パッケージ内のすべての HTTP サービスインターフェースが echo グループに属するように構成されていると仮定します。まず、サービスインターフェースからハードコードされた URL を削除します。
Java
Kotlin
import java.util.Map;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.service.annotation.PostExchange;
public interface EchoService {
@PostExchange
Map<?, ?> echo(@RequestBody Map<String, String> message);
}import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.service.annotation.HttpExchange
import org.springframework.web.service.annotation.PostExchange
interface EchoService {
@PostExchange
fun echo(@RequestBody message: Map<String, String>): Map<*, *>
}次のように記述できます。
Java
Kotlin
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.service.registry.ImportHttpServices;
@SpringBootApplication
@ImportHttpServices(group = "echo", basePackages = "com.example.myclients")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.web.service.registry.ImportHttpServices
@SpringBootApplication
@ImportHttpServices(group = "echo", basePackages = ["com.example.myclients"])
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args)
} 最後に、base-url プロパティを使用して、echo グループを実際の URL にリンクできます。
プロパティ
YAML
spring.http.serviceclient.echo.base-url=https://echo.zuplo.iospring:
http:
serviceclient:
echo:
base-url: "https://echo.zuplo.io"| グループを指定しない場合、HTTP サービスクライアントは "default" という名前のグループに関連付けられます。 |
同じパッケージ内に複数の HTTP サービスインターフェースがあり、異なるグループに関連付ける必要がある場合は、個別にリストすることができます。 例:
|
プロパティの構成
HTTP サービスの構成プロパティは、spring.http.serviceclient.<group-name> で指定できます。
プロパティを使用して、次のようなアスペクトを構成できます。
ベース URL。
送信する必要があるデフォルトのヘッダー。
API バージョン管理の構成。
リダイレクト設定。
接続と読み取りのタイムアウト。
使用する SSL バンドル。
| すべての HTTP クライアントに適用されるグローバル構成プロパティを使用することもできます。 |
例: 以下のプロパティは次のようになります。
すべての HTTP クライアントが 1 秒の接続タイムアウトを使用するように構成します (特に指定しない限り)。
"echo" グループの HTTP サービスクライアントを次のように構成します。
特定のベース URL を使用します。
2 秒の読み取りタイムアウトを設定します。
X-Versionヘッダーを使用して API バージョン情報を挿入します。
プロパティ
YAML
spring.http.clients.connect-timeout=1s
spring.http.serviceclient.echo.base-url=https://echo.zuplo.io
spring.http.serviceclient.echo.read-timeout=2s;
spring.http.serviceclient.echo.apiversion.default=1.0.0
spring.http.serviceclient.echo.apiversion.insert.header=X-Versionspring:
http:
clients:
connect-timeout: 1s
serviceclient:
echo:
base-url: "https://echo.zuplo.io"
read-timeout: 2s;
apiversion:
default: 1.0.0
insert:
header: X-Versionカスタム
HTTP サービスクライアントを基本プロパティを超えてカスタマイズする必要がある場合は、HTTP サービスグループコンフィギュレーターを使用できます。RestClient をベースとする HTTP サービスクライアントの場合は、RestClientHttpServiceGroupConfigurer (Javadoc) を実装する Bean を宣言できます。WebClient をベースとする HTTP サービスクライアントの場合は、WebClientHttpServiceGroupConfigurer (Javadoc) を実装する Bean を宣言できます。
どちらも同じように動作し、Spring Boot の自動構成によって自動的に適用されます。
例: 次の構成では、グループ名を含む各送信リクエストに HTTP ヘッダーを追加するグループカスタマイザーが追加されます。
Java
Kotlin
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.support.RestClientHttpServiceGroupConfigurer;
@Configuration(proxyBeanMethods = false)
public class MyHttpServiceGroupConfiguration {
@Bean
RestClientHttpServiceGroupConfigurer myHttpServiceGroupConfigurer() {
return (groups) -> groups.forEachClient((group, clientBuilder) -> {
String groupName = group.name();
clientBuilder.defaultHeader("service-group", groupName);
});
}
}import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.client.support.RestClientHttpServiceGroupConfigurer
@Configuration(proxyBeanMethods = false)
class MyHttpServiceGroupConfiguration {
@Bean
fun myHttpServiceGroupConfigurer(): RestClientHttpServiceGroupConfigurer {
return RestClientHttpServiceGroupConfigurer { groups ->
groups.forEachClient { group, clientBuilder ->
val groupName = group.name()
clientBuilder.defaultHeader("service-group", groupName)
}
}
}
}高度な構成
Spring Framework は、@ImportHttpServices (Javadoc) アノテーションに加えて、AbstractHttpServiceRegistrar (Javadoc) クラスも提供しています。このクラスを独自に拡張して @Import (Javadoc) することで、プログラムによる設定を行うことができます。詳細については、Spring Framework リファレンスドキュメントを参照してください。
HTTP サービスクライアントを登録するためにどの方法を使用するかに関係なく、Spring Boot のサポートは同じままです。
すべての HTTP クライアントにグローバル設定を適用する
使用されている基盤となるテクノロジに関係なく、すべての HTTP クライアントには構成可能な共通の設定があります。
これらには次のものが含まれます。
接続タイムアウト。
読み取りタイムアウト。
HTTP リダイレクトをどのように処理するか。
接続時に使用する SSL バンドル。
これらの共通設定は、ClientHttpConnectorBuilder (Javadoc) および ClientHttpRequestFactoryBuilder (Javadoc) の build(…) メソッドに渡すことができる HttpClientSettings (Javadoc) クラスによって表されます。
すべての自動構成されたクライアントに同じ構成を適用する場合は、spring.http.clients プロパティを使用できます。
プロパティ
YAML
spring.http.clients.connect-timeout=2s
spring.http.clients.read-timeout=1s
spring.http.clients.redirects=dont-followspring:
http:
clients:
connect-timeout: 2s
read-timeout: 1s
redirects: dont-follow