ドキュメント

§Play WSを使用したREST APIの呼び出し

Playアプリケーション内から他のHTTPサービスを呼び出したい場合があります。Playは、WS(「WebService」)ライブラリを介してこれをサポートしており、非同期HTTP呼び出しを行う方法を提供します。

WS APIの使用には、リクエストの作成とレスポンスの処理という2つの重要な部分があります。最初にGETとPOSTのHTTPリクエストの作成方法について説明し、次にWSライブラリからのレスポンスの処理方法を示します。最後に、いくつかの一般的なユースケースについて説明します。

:Play 2.6では、Play WSは2つに分割されました。Playに依存しない基盤となるスタンドアロンクライアントと、Play固有のクラスを使用する上位のラッパーがあります。さらに、AsyncHttpClientとNettyのシェーディングバージョンがPlay WSで使用されるようになり、ライブラリの競合が最小限に抑えられます。これは主に、PlayのHTTPエンジンが異なるバージョンのNettyを使用できるようにするためです。詳細については、2.6移行ガイドを参照してください。

§プロジェクトへのWSの追加

WSを使用するには、最初にbuild.sbtファイルにjavaWsを追加します

libraryDependencies ++= Seq(
  javaWs
)

§Play WSでのHTTPキャッシュの有効化

Play WSはHTTPキャッシュをサポートしていますが、この機能を有効にするにはJSR-107キャッシュ実装が必要です。ehcacheを追加できます

libraryDependencies += ehcache

または、Caffeineなどの別のJSR-107互換キャッシュを使用することもできます。

ライブラリの依存関係が揃ったら、WSキャッシュ設定ページに示すようにHTTPキャッシュを有効にします。

HTTPキャッシュを使用すると、バックエンドRESTサービスへの繰り返しのリクエストを節約でき、stale-on-errorstale-while-revalidateなどの復元力機能と組み合わせると特に便利です。

§リクエストの作成

WSを使用するコントローラーまたはコンポーネントは、次のインポートを追加し、依存性注入を使用するためにWSClientタイプに依存関係を宣言する必要があります

import javax.inject.Inject;
import play.libs.ws.*;
import play.mvc.*;

public class MyClient implements WSBodyReadables, WSBodyWritables {
  private final WSClient ws;

  @Inject
  public MyClient(WSClient ws) {
    this.ws = ws;
  }
  // ...
}

HTTPリクエストを作成するには、ws.url()を使用してURLを指定します。

WSRequest request = ws.url("http://example.com");

これは、ヘッダーの設定など、さまざまなHTTPオプションを指定するために使用できるWSRequestを返します。複雑なリクエストを構築するために、呼び出しを連鎖させることができます。

WSRequest complexRequest =
    request
        .addHeader("headerKey", "headerValue")
        .setRequestTimeout(Duration.of(1000, ChronoUnit.MILLIS))
        .addQueryParameter("paramKey", "paramValue");

最後に、使用したいHTTPメソッドに対応するメソッドを呼び出します。これによりチェーンが終了し、WSRequestで構築されたリクエストに定義されているすべてのオプションが使用されます。

CompletionStage<? extends WSResponse> responsePromise = complexRequest.get();

これにより、CompletionStage<WSResponse>が返されます。ここで、WSResponseにはサーバーから返されたデータが含まれています。

Java 1.8は、CompletionStageを使用して非同期コードを管理します。Java WS APIは、さまざまなメソッドでCompletionStageを組み合わせることに大きく依存しています。F.Promiseを使用していた以前のバージョンのPlayを使用していた場合は、移行ガイドのCompletionStageセクションが非常に役立ちます。

java.util.URL.equals()の呼び出しなど、あらゆる種類のDNS作業を含むブロッキング作業を行っている場合は、スレッドプールで説明されているように、できればCustomExecutionContextを介して、カスタム実行コンテキストを使用する必要があります。プールサイズを、障害を考慮して十分な安全マージンを残せるように設定する必要があります。

信頼性の低いネットワークを呼び出している場合は、Futures.timeoutサーキットブレーカーFailsafeなど)の使用を検討してください。

§認証付きリクエスト

HTTP認証を使用する必要がある場合は、ユーザー名、パスワード、およびWSAuthSchemeを使用して、ビルダーで指定できます。WSAuthSchemeのオプションは、BASICDIGESTKERBEROSNTLM、およびSPNEGOです。

ws.url(url).setAuth("user", "password", WSAuthScheme.BASIC).get();

§リダイレクトをたどるリクエスト

HTTP呼び出しが302または301リダイレクトになった場合、別の呼び出しを行うことなく、リダイレクトを自動的にたどることができます。

ws.url(url).setFollowRedirects(true).get();

§クエリパラメータ付きリクエスト

リクエストのクエリパラメータを指定できます。

ws.url(url).addQueryParameter("paramKey", "paramValue");

§追加ヘッダー付きリクエスト

ws.url(url).addHeader("headerKey", "headerValue").get();

たとえば、特定の形式でプレーンテキストを送信する場合は、コンテンツタイプを明示的に定義することをお勧めします。

ws.url(url).addHeader("Content-Type", "application/json").post(jsonString);
// OR
ws.url(url).setContentType("application/json").post(jsonString);

WSCookieBuilderを使用して、リクエストのCookieを指定できます

ws.url(url)
    .addCookies(new WSCookieBuilder().setName("headerKey").setValue("headerValue").build())
    .get();

§タイムアウト付きリクエスト

リクエストタイムアウトを指定する場合は、setRequestTimeoutを使用して値をミリ秒単位で設定できます。値Duration.ofMillis(Long.MAX_VALUE)を使用して、無限のタイムアウトを設定できます。

ws.url(url).setRequestTimeout(Duration.of(1000, ChronoUnit.MILLIS)).get();

§フォームデータの送信

URLフォームエンコードデータを送信するには、適切なヘッダーと、コンテンツタイプが「application / x-www-form-urlencoded」のフォーマット済みデータを設定します。

ws.url(url)
    .setContentType("application/x-www-form-urlencoded")
    .post("key1=value1&key2=value2");

§multipart / formデータの送信

multipart / formデータを送信する最も簡単な方法は、Source<Http.MultipartFormData.Part<Source<ByteString>, ?>, ?>を使用することです

import play.libs.ws.ahc.AhcCurlRequestLogger;
import play.mvc.Http.MultipartFormData.*;
ws.url(url).post(Source.single(new DataPart("hello", "world")));

ファイルをmultipartフォームデータの一部としてアップロードするには、Http.MultipartFormData.FilePart<Source<ByteString>, ?>Sourceに渡す必要があります

Source<ByteString, ?> file = FileIO.fromPath(Paths.get("hello.txt"));
FilePart<Source<ByteString, ?>> fp = new FilePart<>("hello", "hello.txt", "text/plain", file);
DataPart dp = new DataPart("key", "value");

ws.url(url).post(Source.from(Arrays.asList(fp, dp)));

§JSONデータの送信

JSONデータを送信する最も簡単な方法は、play.libs.Jsonを使用してPlayのJSONサポートを使用することです

import com.fasterxml.jackson.databind.JsonNode;
import play.libs.Json;
JsonNode json = Json.newObject().put("key1", "value1").put("key2", "value2");

ws.url(url).post(json);

カスタムObjectMapperを渡すこともできます

ObjectMapper objectMapper = createCustomObjectMapper();
ws.url(url).post(body(json, objectMapper));

§XMLデータの送信

XMLデータを送信する最も簡単な方法は、play.libs.XMLを使用してPlayのXMLサポートを使用することです

Document xml = play.libs.XML.fromString("<document></document>");
ws.url(url).post(xml);

§ストリーミングデータの送信

Akkaストリームを使用して、リクエスト本文でデータをストリーミングすることもできます。

大きな画像を別のエンドポイントにストリーミングしてさらに処理する方法を示す例を次に示します

CompletionStage<WSResponse> wsResponse = ws.url(url).setBody(body(largeImage)).execute("PUT");

上記のコードスニペットのlargeImageは、Source<ByteString, ?>です。

§リクエストフィルター

リクエストフィルターを追加することで、WSRequestで追加の処理を行うことができます。リクエストフィルターは、play.libs.ws.WSRequestFilterインターフェースを拡張し、request.setRequestFilter(filter)を使用してリクエストに追加することで追加されます。

public CompletionStage<Result> index() {
  WSRequestFilter filter =
      executor ->
          request -> {
            logger.debug("url = " + request.getUrl());
            return executor.apply(request);
          };

  return ws.url(feedUrl)
      .setRequestFilter(filter)
      .get()
      .thenApply(
          (WSResponse r) -> {
            String title = r.getBody(json()).findPath("title").asText();
            return ok("Feed title: " + title);
          });
}

cURL 形式のリクエストを SLF4J に記録するサンプルリクエストフィルターが play.libs.ws.ahc.AhcCurlRequestLogger に追加されました。

ws.url("https://play.dokyumento.jp")
    .setRequestFilter(new AhcCurlRequestLogger())
    .addHeader("Header-Name", "Header value")
    .get();

出力は次のようになります

curl \
  --verbose \
  --request GET \
  --header 'Header-Key: Header value' \
  'https://play.dokyumento.jp'

§レスポンスの処理

WSResponseの処理は、thenApplythenComposeなどの変換をCompletionStageに適用することで行われます。

§JSONとしてのレスポンスの処理

play.libs.ws.WSBodyReadables.json()のデフォルトメソッドを使用して、r.getBody(json())を呼び出すことで、レスポンスをJsonNodeとして処理できます。

// implements WSBodyReadables or use WSBodyReadables.instance.json()
CompletionStage<JsonNode> jsonPromise = ws.url(url).get().thenApply(r -> r.getBody(json()));

§XMLとしてのレスポンスの処理

同様に、play.libs.ws.WSBodyReadables.xml()のデフォルトメソッドを使用して、r.getBody(xml())を呼び出すことで、レスポンスをXMLとして処理できます。

// implements WSBodyReadables or use WSBodyReadables.instance.xml()
CompletionStage<Document> documentPromise =
    ws.url(url).get().thenApply(r -> r.getBody(xml()));

§大きなレスポンスの処理

get()post()、またはexecute()を呼び出すと、レスポンスが利用可能になる前にレスポンスの本文がメモリにロードされます。数ギガバイトの大容量ファイルをダウンロードする場合、これにより望ましくないガベージコレクションが発生したり、メモリ不足エラーが発生したりする可能性があります。

Pekko StreamsSink を使用することで、レスポンスの本文を段階的に消費できます。WSRequeststream() メソッドは CompletionStage<WSResponse> を返します。ここで、WSResponse には、Source<ByteString, ?> を提供する getBodyAsStream() メソッドが含まれています。

注: 2.5.x では、request.stream() の呼び出しに対して StreamedResponse が返されていました。2.6.x では、標準の WSResponse が返され、getBodyAsSource() メソッドを使用して Source を返す必要があります。

WSストリーミング機能を活用したいコントローラーまたはコンポーネントは、次のインポートと依存関係を追加する必要があります

import javax.inject.Inject;
import org.apache.pekko.stream.Materializer;
import org.apache.pekko.stream.javadsl.*;
import play.libs.ws.*;
import play.mvc.*;

public class MyController extends Controller {

  @Inject WSClient ws;
  @Inject Materializer materializer;

  // ...
}

レスポンスによって返されるバイト数をカウントするために、畳み込み Sink を使用する簡単な例を次に示します

// Make the request
CompletionStage<WSResponse> futureResponse = ws.url(url).setMethod("GET").stream();

CompletionStage<Long> bytesReturned =
    futureResponse.thenCompose(
        res -> {
          Source<ByteString, ?> responseBody = res.getBodyAsSource();

          // Count the number of bytes returned
          Sink<ByteString, CompletionStage<Long>> bytesSum =
              Sink.fold(0L, (total, bytes) -> total + bytes.length());

          return responseBody.runWith(bytesSum, materializer);
        });

あるいは、本文を別の場所にストリーミングすることもできます。たとえば、ファイルなどです

File file = java.nio.file.Files.createTempFile("stream-to-file-", ".txt").toFile();
OutputStream outputStream = java.nio.file.Files.newOutputStream(file.toPath());

// Make the request
CompletionStage<WSResponse> futureResponse = ws.url(url).setMethod("GET").stream();

CompletionStage<File> downloadedFile =
    futureResponse.thenCompose(
        res -> {
          Source<ByteString, ?> responseBody = res.getBodyAsSource();

          // The sink that writes to the output stream
          Sink<ByteString, CompletionStage<org.apache.pekko.Done>> outputWriter =
              Sink.<ByteString>foreach(bytes -> outputStream.write(bytes.toArray()));

          // materialize and run the stream
          CompletionStage<File> result =
              responseBody
                  .runWith(outputWriter, materializer)
                  .whenComplete(
                      (value, error) -> {
                        // Close the output stream whether there was an error or not
                        try {
                          outputStream.close();
                        } catch (IOException e) {
                        }
                      })
                  .thenApply(v -> file);
          return result;
        });

レスポンス本文のもう1つの一般的な宛先は、コントローラーの Action からストリーミングして返すことです

// Make the request
CompletionStage<WSResponse> futureResponse = ws.url(url).setMethod("GET").stream();

CompletionStage<Result> result =
    futureResponse.thenApply(
        response -> {
          Source<ByteString, ?> body = response.getBodyAsSource();
          // Check that the response was successful
          if (response.getStatus() == 200) {
            // Get the content type
            String contentType =
                Optional.ofNullable(response.getHeaders().get("Content-Type"))
                    .map(contentTypes -> contentTypes.get(0))
                    .orElse("application/octet-stream");

            // If there's a content length, send that, otherwise return the body chunked
            Optional<String> contentLength =
                Optional.ofNullable(response.getHeaders().get("Content-Length"))
                    .map(contentLengths -> contentLengths.get(0));
            if (contentLength.isPresent()) {
              return ok().sendEntity(
                      new HttpEntity.Streamed(
                          body,
                          Optional.of(Long.parseLong(contentLength.get())),
                          Optional.of(contentType)));
            } else {
              return ok().chunked(body).as(contentType);
            }
          } else {
            return new Result(Status.BAD_GATEWAY);
          }
        });

stream() を呼び出す前に、リクエストで setMethod(String) を呼び出して使用する HTTP メソッドを設定する必要があることに気付いたかもしれません。GET の代わりに PUT を使用する別の例を次に示します

CompletionStage<WSResponse> futureResponse =
    ws.url(url).setMethod("PUT").setBody(body("some body")).stream();

もちろん、他の有効な HTTP 動詞も使用できます。

§一般的なパターンとユースケース

§WS 呼び出しのチェーン

thenCompose を使用して、WS 呼び出しをチェーンできます。

final CompletionStage<WSResponse> responseThreePromise =
    ws.url(urlOne)
        .get()
        .thenCompose(responseOne -> ws.url(responseOne.getBody()).get())
        .thenCompose(responseTwo -> ws.url(responseTwo.getBody()).get());

§例外からの回復

呼び出し中の例外から回復するには、handle または exceptionally を使用してレスポンスを置き換えることができます。

CompletionStage<WSResponse> responsePromise = ws.url("http://example.com").get();
responsePromise.handle(
    (result, error) -> {
      if (error != null) {
        return ws.url("http://backup.example.com").get();
      } else {
        return CompletableFuture.completedFuture(result);
      }
    });

§コントローラーでの使用

非同期結果の処理 で定義されている非同期アクションパターンを使用して、CompletionStage<WSResponse> を Play サーバーで直接処理できる CompletionStage<Result> にマップできます。

public CompletionStage<Result> index() {
  return ws.url(feedUrl)
      .get()
      .thenApply(response -> ok("Feed title: " + response.asJson().findPath("title").asText()));
}

§Futures タイムアウトでの WSClient の使用

WS 呼び出しのチェーンが時間内に完了しない場合、結果をタイムアウトブロックでラップすると便利です。チェーンが時間内に完了しない場合、失敗した Future が返されます。これは、単一のリクエストにのみ適用される withRequestTimeout を使用するよりも一般的です。
これを行う最良の方法は、Play の ノンブロッキングタイムアウト機能 を使用し、Futures.timeoutCustomExecutionContext を使用して、何らかの解決を保証することです

public CompletionStage<Result> index() {
  CompletionStage<Result> f =
      futures.timeout(
          ws.url("http://playframework.com")
              .get()
              .thenApplyAsync(
                  result -> {
                    try {
                      Thread.sleep(10000L);
                      return Results.ok();
                    } catch (InterruptedException e) {
                      return Results.status(SERVICE_UNAVAILABLE);
                    }
                  },
                  customExecutionContext),
          1L,
          TimeUnit.SECONDS);

  return f.handleAsync(
      (result, e) -> {
        if (e != null) {
          if (e instanceof CompletionException) {
            Throwable completionException = e.getCause();
            if (completionException instanceof TimeoutException) {
              return Results.status(SERVICE_UNAVAILABLE, "Service has timed out");
            } else {
              return internalServerError(e.getMessage());
            }
          } else {
            logger.error("Unknown exception " + e.getMessage(), e);
            return internalServerError(e.getMessage());
          }
        } else {
          return result;
        }
      });
}

§WSClient の直接作成

上記のように、依存性注入 を使用して WSClient インスタンスを取得することをお勧めします。依存性注入によって作成された WSClient インスタンスは、アプリケーションの起動時に自動的に作成され、アプリケーションの停止時にクリーンアップされるため、使い方が簡単です。

ただし、必要に応じて、コードから直接 WSClient をインスタンス化し、これを使用してリクエストを作成したり、基盤となる AsyncHttpClient オプションを設定したりできます。

注: WSClient を手動で作成する場合は、使い終わったら client.close() を呼び出してクリーンアップする必要があります。各クライアントは独自の スレッドプールを作成します。クライアントを閉じない場合、またはクライアントを 너무 많이 作成すると、スレッドまたはファイルハンドルが不足します。基になるリソースが消費されるため、「新しいネイティブスレッドを作成できません」または「開いているファイルが多すぎます」などのエラーが発生します。

WSClient インスタンスを自分で作成する例を次に示します

import org.apache.pekko.stream.Materializer;
import org.apache.pekko.stream.javadsl.*;
import org.apache.pekko.util.ByteString;
import play.mvc.Results;
// Set up the client config (you can also use a parser here):
// play.api.Configuration configuration = ... // injection
// play.Environment environment = ... // injection

WSClient customWSClient =
    play.libs.ws.ahc.AhcWSClient.create(
        play.libs.ws.ahc.AhcWSClientConfigFactory.forConfig(
            configuration.underlying(), environment.classLoader()),
        null, // no HTTP caching
        materializer);

また、play.test.WSTestClient.newClient を使用して、機能テストで WSClient のインスタンスを作成することもできます。詳細については、JavaTestingWebServiceClients を参照してください。

または、実行中の Play アプリケーションや設定をまったく使用せずに、WSClient を完全にスタンドアロンで実行することもできます

import org.apache.pekko.actor.ActorSystem;
import org.apache.pekko.stream.Materializer;

import org.apache.pekko.stream.SystemMaterializer;
import play.shaded.ahc.org.asynchttpclient.*;
import play.libs.ws.*;
import play.libs.ws.ahc.*;

import org.junit.Test;
// Set up Pekko
String name = "wsclient";
ActorSystem system = ActorSystem.create(name);
Materializer materializer = SystemMaterializer.get(system).materializer();

// Set up AsyncHttpClient directly from config
AsyncHttpClientConfig asyncHttpClientConfig =
    new DefaultAsyncHttpClientConfig.Builder()
        .setMaxRequestRetry(0)
        .setShutdownQuietPeriod(0)
        .setShutdownTimeout(0)
        .build();
AsyncHttpClient asyncHttpClient = new DefaultAsyncHttpClient(asyncHttpClientConfig);

// Set up WSClient instance directly from asynchttpclient.
WSClient client = new AhcWSClient(asyncHttpClient, materializer);

// Call out to a remote system and then and close the client and pekko.
client
    .url("http://www.google.com")
    .get()
    .whenComplete(
        (r, e) -> {
          Optional.ofNullable(r)
              .ifPresent(
                  response -> {
                    String statusText = response.getStatusText();
                    System.out.println("Got a response " + statusText);
                  });
        })
    .thenRun(
        () -> {
          try {
            client.close();
          } catch (Exception e) {
            e.printStackTrace();
          }
        })
    .thenRun(system::terminate);

これは、設定からアクセスできない特定の HTTP クライアントオプションがある場合に役立ちます。

WSClient をスタンドアロンで実行したいが、設定SSL を含む)を使用したい場合は、次のような設定パーサーを使用できます

// Set up Pekko
String name = "wsclient";
ActorSystem system = ActorSystem.create(name);
Materializer materializer = Materializer.matFromSystem(system);

// Read in config file from application.conf
Config conf = ConfigFactory.load();
WSConfigParser parser = new WSConfigParser(conf, ClassLoader.getSystemClassLoader());
AhcWSClientConfig clientConf = AhcWSClientConfigFactory.forClientConfig(parser.parse());

// Start up asynchttpclient
final DefaultAsyncHttpClientConfig asyncHttpClientConfig =
    new AhcConfigBuilder(clientConf).configure().build();
final DefaultAsyncHttpClient asyncHttpClient =
    new DefaultAsyncHttpClient(asyncHttpClientConfig);

// Create a new WSClient, and then close the client.
WSClient client = new AhcWSClient(asyncHttpClient, materializer);
client.close();
system.terminate();

繰り返しますが、カスタムクライアントの作業が完了したら、クライアントを閉じる必要があります。そうしないと、スレッドがリークします

try {
  customWSClient.close();
} catch (IOException e) {
  logger.error(e.getMessage(), e);
}

理想的には、すべてのリクエストが完了したことを確認した後にのみ、クライアントを閉じる必要があります。WSClient ロジックは非同期であり、try-with-resources は本文で同期コードのみをサポートするため、try-with-resources を使用して WSClient インスタンスを自動的に閉じることはできません。

§カスタム BodyReadables と BodyWritables

Play WS には、play.libs.ws.WSBodyWritables の形式で本文の豊富な型サポートが付属しています。これには、WSRequest の本文の JsonNodeXML などの入力を ByteString または Source<ByteString, ?> に変換するメソッド、および play.libs.ws.WSBodyReadables が含まれています。これには、WSResponse の本文を ByteString または Source[ByteString, _] から読み取り、JsValue や XML などの適切な型を返すメソッドが含まれています。デフォルトのメソッドは WSRequest と WSResponse から使用できますが、response.getBody(myReadable())request.post(myWritable(data)) を使用してカスタム型を使用することもできます。これは、カスタムライブラリを使用する場合、つまり STaX API を介して XML をストリーミングする場合に特に役立ちます。

§カスタム Readable の作成

レスポンスを解析することで、カスタムの readable を作成できます

public interface URLBodyReadables {
  default BodyReadable<java.net.URL> url() {
    return response -> {
      try {
        String s = response.getBody();
        return java.net.URI.create(s).toURL();
      } catch (MalformedURLException e) {
        throw new RuntimeException(e);
      }
    };
  }
}

§カスタム BodyWritable の作成

InMemoryBodyWritable を使用して、リクエストにカスタムの body writable を次のように作成できます。ストリーミングでカスタムの body writable を指定するには、SourceBodyWritable を使用します。

public interface URLBodyWritables {
  default InMemoryBodyWritable body(java.net.URL url) {
    try {
      String s = url.toURI().toString();
      ByteString byteString = ByteString.fromString(s);
      return new InMemoryBodyWritable(byteString, "text/plain");
    } catch (URISyntaxException e) {
      throw new RuntimeException(e);
    }
  }
}

§スタンドアロン WS

Play の外部で WS を呼び出したい場合は、Play ライブラリに依存しないスタンドアロンバージョンの Play WS を使用できます。プロジェクトに play-ahc-ws-standalone を追加することで、これを行うことができます

libraryDependencies += "org.playframework" %% "play-ahc-ws-standalone" % playWSStandalone

詳細については、https://github.com/playframework/play-ws および 2.6 移行ガイド を参照してください。

§AsyncHttpClient へのアクセス

WSClient から、基盤となるシェーディングされた AsyncHttpClient にアクセスできます。

play.shaded.ahc.org.asynchttpclient.AsyncHttpClient underlyingClient =
    (play.shaded.ahc.org.asynchttpclient.AsyncHttpClient) ws.getUnderlying();

§WS の設定

application.conf で次のプロパティを使用して、WS クライアントを設定します

§タイムアウト

WS には 3 つの異なるタイムアウトがあります。タイムアウトに達すると、WS リクエストが中断されます。

リクエストタイムアウトは、setTimeout() を使用して特定の接続に対してオーバーライドできます(「リクエストの作成」セクションを参照)。

§SSL を使用した WS の設定

SSL/TLS(HTTPS)を介した HTTP で使用するために WS を設定するには、WS SSL の設定 を参照してください。

§キャッシュを使用した WS の設定

HTTP キャッシュで使用するために WS を設定するには、WS キャッシュの設定 を参照してください。

§AsyncClientConfig の設定

基盤となる AsyncHttpClientConfig で、次の高度な設定を行うことができます。

詳細については、AsyncHttpClientConfig のドキュメント を参照してください。

次: OpenID サービスへの接続


このドキュメントに誤りを見つけましたか?このページのソースコードは こちら にあります。ドキュメントガイドライン を読んだ後、プルリクエストを送信してください。質問やアドバイスがあれば、コミュニティフォーラム にアクセスして、コミュニティとの会話を始めてください。