本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 適用於 Java 的 AWS SDK 2.x 處理分頁結果
當回應物件太大而無法在單一回應中傳回時,許多 AWS 操作會傳回分頁結果。在 適用於 Java 的 AWS SDK 1.0 中,回應包含您用來擷取下一頁結果的字符。相反地, 適用於 Java 的 AWS SDK 2.x 具有自動調色方法,可進行多次服務呼叫,自動為您取得下一頁的結果。您只需編寫處理結果的程式碼即可。同步和非同步用戶端皆可使用自動分頁功能。
注意
這些程式碼片段假設您了解使用 SDK 的基本概念,並已使用單一登入存取來設定您的環境。
同步分頁
下列範例示範同步分頁方法來列出 Amazon S3 儲存貯體中的物件。
逐一查看頁面
第一個範例示範如何使用listRes
分頁器物件、ListObjectsV2Iterable
stream
方法逐一查看所有回應頁面。程式碼會在回應頁面上串流,將回應串流轉換為S3Object
內容串流,然後處理 Amazon S3 物件的內容。
下列匯入適用於此同步分頁區段中的所有範例。
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Random;
import software.amazon.awssdk.core.waiters.WaiterResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
import software.amazon.awssdk.services.s3.model.S3Object;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
import software.amazon.awssdk.services.s3.model.DeleteBucketRequest;
import software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest;
import software.amazon.awssdk.services.s3.model.CreateMultipartUploadResponse;
import software.amazon.awssdk.services.s3.model.CompletedMultipartUpload;
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
import software.amazon.awssdk.services.s3.model.CompletedPart;
import software.amazon.awssdk.services.s3.model.CreateBucketConfiguration;
import software.amazon.awssdk.services.s3.model.UploadPartRequest;
import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest;
import software.amazon.awssdk.services.s3.waiters.S3Waiter;
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
import software.amazon.awssdk.services.s3.model.HeadBucketResponse;
ListObjectsV2Request listReq = ListObjectsV2Request.builder()
.bucket(bucketName)
.maxKeys(1)
.build();
ListObjectsV2Iterable listRes = s3.listObjectsV2Paginator(listReq);
// Process response pages
listRes.stream()
.flatMap(r -> r.contents().stream())
.forEach(content -> System.out
.println(" Key: " + content.key() + " size = " + content.size()));
請參閱 GitHub 上的完整範例
反覆運算物件
以下範例示範如何逐一查看回應傳回的物件,而非回應的頁面。ListObjectsV2Iterable
類別的 contents
方法會傳回 SdkIterable
使用串流
下列程式碼片段會在回應內容上使用 stream
方法,以逐一查看分頁項目集合。
// Helper method to work with paginated collection of items directly.
listRes.contents().stream()
.forEach(content -> System.out
.println(" Key: " + content.key() + " size = " + content.size()));
請參閱 GitHub 上的完整範例
使用每個迴圈
由於 SdkIterable
擴展了Iterable
界面,因此您可以像任何 一樣處理內容Iterable
。下列程式碼片段使用標準for-each
迴圈來逐一查看回應的內容。
for (S3Object content : listRes.contents()) {
System.out.println(" Key: " + content.key() + " size = " + content.size());
}
請參閱 GitHub 上的完整範例
手動分頁
如果您的使用案例有需要,也可以使用手動分頁。使用回應物件中的下一個符記以進行後續請求。下列範例使用while
迴圈。
ListObjectsV2Request listObjectsReqManual = ListObjectsV2Request.builder()
.bucket(bucketName)
.maxKeys(1)
.build();
boolean done = false;
while (!done) {
ListObjectsV2Response listObjResponse = s3.listObjectsV2(listObjectsReqManual);
for (S3Object content : listObjResponse.contents()) {
System.out.println(content.key());
}
if (listObjResponse.nextContinuationToken() == null) {
done = true;
}
listObjectsReqManual = listObjectsReqManual.toBuilder()
.continuationToken(listObjResponse.nextContinuationToken())
.build();
}
請參閱 GitHub 上的完整範例
非同步分頁
下列範例示範列出 DynamoDB 資料表的非同步分頁方法。
反覆查看資料表名稱的頁面
下列兩個範例使用非同步 DynamoDB 用戶端,呼叫 listTablesPaginator
方法並請求取得 ListTablesPublisher
ListTablesPublisher
實作兩個界面,提供許多處理回應的選項。我們會查看每個界面的方法。
使用 Subscriber
下列程式碼範例示範如何使用 實作的org.reactivestreams.Publisher
界面來處理分頁結果ListTablesPublisher
。若要進一步了解被動串流模型,請參閱被動串流 GitHub 儲存庫
下列匯入適用於此非同步分頁區段中的所有範例。
import io.reactivex.rxjava3.core.Flowable;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import reactor.core.publisher.Flux;
import software.amazon.awssdk.core.async.SdkPublisher;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.awssdk.services.dynamodb.model.ListTablesRequest;
import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse;
import software.amazon.awssdk.services.dynamodb.paginators.ListTablesPublisher;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
下列程式碼會取得ListTablesPublisher
執行個體。
// Creates a default client with credentials and region loaded from the
// environment.
final DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.create();
ListTablesRequest listTablesRequest = ListTablesRequest.builder().limit(3).build();
ListTablesPublisher publisher = asyncClient.listTablesPaginator(listTablesRequest);
下列程式碼使用 的匿名實作org.reactivestreams.Subscriber
來處理每個頁面的結果。
onSubscribe
方法會呼叫 Subscription.request
方法以啟動向發佈者請求資料。必須呼叫這個方法,才能開始從發佈者取得資料。
訂閱者onNext
的方法會存取所有資料表名稱並列印出每個資料表,以處理回應頁面。處理頁面後,會向發佈者請求另一個頁面。此方法會重複呼叫,直到擷取所有頁面為止。
如果擷取資料時發生錯誤,會觸發 onError
方法。最後,所有頁面都已請求完,會呼叫 onComplete
方法。
// A Subscription represents a one-to-one life-cycle of a Subscriber subscribing
// to a Publisher.
publisher.subscribe(new Subscriber<ListTablesResponse>() {
// Maintain a reference to the subscription object, which is required to request
// data from the publisher.
private Subscription subscription;
@Override
public void onSubscribe(Subscription s) {
subscription = s;
// Request method should be called to demand data. Here we request a single
// page.
subscription.request(1);
}
@Override
public void onNext(ListTablesResponse response) {
response.tableNames().forEach(System.out::println);
// After you process the current page, call the request method to signal that
// you are ready for next page.
subscription.request(1);
}
@Override
public void onError(Throwable t) {
// Called when an error has occurred while processing the requests.
}
@Override
public void onComplete() {
// This indicates all the results are delivered and there are no more pages
// left.
}
});
請參閱 GitHub 上的完整範例
使用 Consumer
ListTablesPublisher
實作 的SdkPublisher
界面具有採用 Consumer
並傳回 subscribe
的方法CompletableFuture<Void>
。
來自此界面的 subscribe
方法可用於簡單的使用案例,而 org.reactivestreams.Subscriber
可能過多的額外負荷。由於以下程式碼會耗用每個頁面,因此它會呼叫每個頁面上的 tableNames
方法。tableNames
方法會傳回使用 forEach
方法處理的 java.util.List
DynamoDB 資料表名稱的 。
// Use a Consumer for simple use cases.
CompletableFuture<Void> future = publisher.subscribe(
response -> response.tableNames()
.forEach(System.out::println));
請參閱 GitHub 上的完整範例
反覆運算資料表名稱
以下範例示範如何逐一查看回應傳回的物件,而非回應的頁面。類似於先前與其contents
方法一起顯示的同步 Amazon S3 範例,DynamoDB 非同步結果類別ListTablesPublisher
具有與基礎項目集合互動的tableNames
便利方法。tableNames
方法的傳回類型是 SdkPublisher
使用 Subscriber
下列程式碼會取得資料表名稱SdkPublisher
基礎集合的 。
// Create a default client with credentials and region loaded from the
// environment.
final DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.create();
ListTablesRequest listTablesRequest = ListTablesRequest.builder().limit(3).build();
ListTablesPublisher listTablesPublisher = asyncClient.listTablesPaginator(listTablesRequest);
SdkPublisher<String> publisher = listTablesPublisher.tableNames();
下列程式碼使用 的匿名實作org.reactivestreams.Subscriber
來處理每個頁面的結果。
訂閱者onNext
的方法會處理集合的個別元素。在這種情況下,它是資料表名稱。處理資料表名稱後,會向發佈者請求另一個資料表名稱。此方法會重複呼叫,直到擷取所有資料表名稱為止。
// Use a Subscriber.
publisher.subscribe(new Subscriber<String>() {
private Subscription subscription;
@Override
public void onSubscribe(Subscription s) {
subscription = s;
subscription.request(1);
}
@Override
public void onNext(String tableName) {
System.out.println(tableName);
subscription.request(1);
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
});
請參閱 GitHub 上的完整範例
使用 Consumer
下列範例使用 的 subscribe
方法SdkPublisher
,需要 Consumer
來處理每個項目。
// Use a Consumer.
CompletableFuture<Void> future = publisher.subscribe(System.out::println);
future.get();
請參閱 GitHub 上的完整範例
使用第三方程式庫
您可以使用其他第三方程式庫,而非實作自訂的訂閱者。此範例示範如何使用 RxJava,但可以使用任何實作被動串流界面的程式庫。如需該程式庫的詳細資訊,請參閱 GitHub 上的 RxJava wiki 頁面
若要使用該程式庫,請將其新增做為相依性。如果使用 Maven,範例會顯示要使用的 POM 片段。
POM 項目
<dependency>
<groupId>io.reactivex.rxjava3</groupId>
<artifactId>rxjava</artifactId>
<version>3.1.6</version>
</dependency>
Code
DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.create();
ListTablesPublisher publisher = asyncClient.listTablesPaginator(ListTablesRequest.builder()
.build());
// The Flowable class has many helper methods that work with
// an implementation of an org.reactivestreams.Publisher.
List<String> tables = Flowable.fromPublisher(publisher)
.flatMapIterable(ListTablesResponse::tableNames)
.toList()
.blockingGet();
System.out.println(tables);
請參閱 GitHub 上的完整範例