https://docs.spring.io/spring-framework/reference/integration/rest-clients.html
RestTemplate
の後継であるRestClient
の使い方について。とはいえ、おおよそは旧来のspringユーザならお馴染みなものが多く、リファレンスを見ればだいたいは事が足りる。なので、ここでは旧来とは異なる設定方法だとかを中心に記述する。
build.gradle
plugins { id 'java' id 'org.springframework.boot' version '3.4.4' id 'io.spring.dependency-management' version '1.1.7' } group = 'com.example' version = '0.0.1-SNAPSHOT' java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { useJUnitPlatform() }
RestClientの生成
デフォルトのbuider設定のままで良ければcreate
、あれこれ追加設定をするならbuilder
を経由する。
RestClient defaultClient = RestClient.create();
RestClient customClient = RestClient.builder()
.baseUrl("https://example.com")
.build();
また、spring-bootのautoconfigがRestClient.Builder
をprototype scopeでinjectionするので以下のような設定も可能。参考:https://docs.spring.io/spring-boot/api/java/org/springframework/boot/autoconfigure/web/client/RestClientAutoConfiguration.html
import org.springframework.stereotype.Component; import org.springframework.web.client.RestClient; @Component public class RestClientBuilderSample { final RestClient client; public RestClientBuilderSample(RestClient.Builder builder) { this.client = builder.build(); } }
基底クライアントの変更
実際のHTTPアクセスには内部的に基底のHTTPクライアントライブラリが使用される。デフォルトはjava.net.http.HttpClient
、対応requestFactoryはorg.springframework.http.client.JdkClientHttpRequestFactory
*1となっている。
これの変更は、ドキュメントによると、ApacheやJettyであればクラスパスにそのライブラリを含めるだけで良い。たとえば、Apache HTTP Components HttpClientであれば以下となる。
// https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 implementation("org.apache.httpcomponents.client5:httpclient5")
明示的なrequestFactoryの指定、または、factoryに追加設定が必要な場合とは以下にする。以下はApache HTTP Components HttpClientの例。
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); RestClient client = RestClient.builder() .requestFactory(factory) .build();
それ以外のHTTPクライアントライブラリの使用方法はリファレンスを参照。Client Request Factories
factory - timeoutとかの設定
factoryでは主にtimeout値の設定変更を行う。以下はApache HTTP Components HttpClientの例。
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); factory.setReadTimeout(1000); factory.setConnectTimeout(1000); factory.setConnectionRequestTimeout(1000); RestClient client = RestClient.builder() .requestFactory(factory) .build();
注意点として、基底HTTPクライアントのfactoryにより設定可能項目が異なる。現時点ではjava.net.http.HttpClient
用のfactoryにはread-timeoutのみ存在するようだ。
JdkClientHttpRequestFactory factory = new JdkClientHttpRequestFactory(); factory.setReadTimeout(1000);
messageConverters - Message Converterの変更
必要なorg.springframework.http.converter.HttpMessageConverter
の実装クラスを追加する。たとえば、JSON変換「のみ」にする場合は以下となる。
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; RestClient client = RestClient.builder() .messageConverters(List.of(new MappingJackson2HttpMessageConverter())) .requestFactory(factory) .build();
messageConverters
は引数がConsumer
とList
の二種類存在する。前者はデフォルトの追加や削除など変更、後者は置換の場合に使用する。
デフォルトのMessage Converter
これを書いてるバージョンでは以下順のリストが設定されている。
org.springframework.http.converter.ByteArrayHttpMessageConverter
org.springframework.http.converter.StringHttpMessageConverter
org.springframework.http.converter.ResourceHttpMessageConverter
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
XMLのMessage Converter追加
以下の依存性を追加する。jackson-dataformat-xml
の場合はmessageConvertersの明示的な指定は不要、自動的にMappingJackson2XmlHttpMessageConverter
が追加される。
// https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml")
レスポンス
Javaオブジェクトでは無くResponseEntity
で受けたい場合は以下の通り。
ResponseEntity<String> response = client .get() .uri("http://localhost:8080/a/a") .retrieve() .toEntity(String.class)
retrieveの次のメソッドで実送信
以下のようにretrieve
メソッドまででは実際の送信はまだ行われず、body(Class<T>)
などで行われる。
// 下記だけではまだ実際の送信は行われない。 ResponseSpec response = client .get() .uri("http://localhost:8080/a/a") .retrieve(); // 下記で実際の送信が行われる。 String body = response.body(String.class);
レスポンスボディが無いとか無視する場合は以下。
response.toBodilessEntity();
exchange
get
やpost
,retrieve
では不足する場合はexchange
で細かい制御が行える。headerとかstatus-codeとかを参照して、例外投げたり結果オブジェクトの調節したり、などを行う。
import org.springframework.http.HttpRequest; import org.springframework.web.client.RestClient.RequestHeadersSpec.ConvertibleClientHttpResponse; SomeResponse response = client .post() .uri("http://localhost:8080/json") .exchange((HttpRequest clientRequest, ConvertibleClientHttpResponse clientResponse) -> { HttpHeaders headers = clientResponse.getHeaders(); HttpStatusCode statusCode = clientResponse.getStatusCode(); String statusText = clientResponse.getStatusText(); SomeResponse r = clientResponse.bodyTo(SomeResponse.class); return r; });
debug logging
これは基底のHTTPクライアントライブラリおよびバージョンごとに指定方法が異なる。
Apache HTTP Components HttpClient
バージョンorg.apache.httpcomponents.client5:httpclient5:5.4.x
の場合はsrc/main/resources/application.properties
に下記行を追加する。
logging.level.org.apache.hc.client5.http=DEBUG
java.net.http.HttpClient
VMオプションに以下を追加する。
-Djdk.httpclient.HttpClient.log=errors,requests,headers
はまりどころ
java.lang.ClassNotFoundException: org.apache.hc.client5.http.classic.HttpClient
Apache HTTP Components HttpClientを使うのであれば別途依存性が必要。「基底クライアントの変更」を参照。
java.lang.ClassNotFoundException: com.fasterxml.jackson.dataformat.xml.XmlMapper
xmlを扱うには別途依存性が必要。「Message Converterの変更」を参照。