深入解析 AWS SDK for Java 2.x 的 DynamoDB 异步编程实战(附测试与分页原理)
示例工程教程后端【免费下载链接】aws-doc-sdk-examplesWelcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below.项目地址https://gitcode.com/gh_mirrors/aw/aws-doc-sdk-examples点击查看免费下载本文基于 AWS 官方文档示例仓库中的javav2/example_code/dynamodbasync模块系统讲解如何用 AWS SDK for Java 2.x 的DynamoDbAsyncClient以异步方式完成 DynamoDB 的表创建、读取条目、列举表以及异步分页并覆盖完整的 JUnit 5 测试流程、config.properties配置、mvn test命令行执行与构建结果分析。读完本文你将掌握异步客户端与CompletableFuture的协作模式、异步 Waiter 的表就绪等待技巧以及基于 Reactive Streams 的listTablesPaginator手动/自动分页与第三方响应式库RxJava、Reactor的接入方法。模块概览与定位该模块位于仓库 javav2/example_code/dynamodbasync是针对 Amazon DynamoDB 的Java 异步Asynchronous代码示例集合与同步版示例javav2/example_code/dynamodb形成对照。模块内共包含四个可直接运行的主类全部位于 src/main/java/com/example/dynamodbasync类文件核心能力底层 APIDynamoDBAsyncCreateTable.java异步创建表并用异步 Waiter 等待表就绪createTablewaitUntilTableExistsDynamoDBAsyncGetItem.java异步按主键读取单个条目getItemDynamoDBAsyncListTables.java异步列出当前账号/区域的表listTablesAsyncPagination.java异步分页的完整演示手动/自动/第三方订阅者listTablesPaginatorSdkPublisher注意运行这些示例会针对你所配置凭据对应的 AWS 账号与区域执行真实操作可能产生 AWS 服务费用。请先确认你的账号权限与成本预期后再运行。构建环境准备Maven 与依赖解析模块使用 Apache Maven 管理依赖核心构建文件为 pom.xml关键配置如下Java 版本java.version21/java.version同时通过maven-compiler-plugin版本 3.1锁定源码与字节码目标版本为 21SDK 依赖管理通过software.amazon.awssdk:bom版本2.35.10以 BOM 方式统一管理 AWS SDK 版本避免逐一手写版本号核心依赖dynamodb异步客户端主模块与dynamodb-enhanced增强型客户端同一示例集内配套使用测试依赖org.junit.jupiter:junit-jupiter版本5.11.4scope 为 test配合maven-surefire-plugin版本3.5.2执行测试第三方响应式流依赖io.reactivex.rxjava3:rxjava3.1.6与io.projectreactor:reactor-core3.3.5.RELEASE供分页示例中的第三方订阅者演示使用SSO 支持sso与ssooidc用于支持 AWS IAM Identity Center 凭据链。在实际环境中你既可以使用 Apache Maven 也可以使用 Gradle 来配置和构建 AWS SDK for Java 项目更完整的入门流程可参考 AWS SDK for Java 2.x 官方入门指南。若想在本仓库内快速体验仓库还提供了两个配套脚本run_example.sh接收类名与参数通过mvn exec:java -Dexec.mainClasscom.example.dynamodbasync.$className -Dexec.args$运行指定示例类Makefile提供目标封装便于快速构建与运行。异步客户端与 CompletableFuture 的核心用法AWS SDK for Java 2.x 的异步客户端DynamoDbAsyncClient与同步客户端最大的区别是所有请求方法返回CompletableFutureT立即返回调用方实际请求在线程池中异步执行。请求完成后通过回调或.join()获取结果。异步列出表thenApply whenComplete 组合DynamoDBAsyncListTables.java 展示了最典型的异步流式写法Region region Region.US_EAST_1; DynamoDbAsyncClient client DynamoDbAsyncClient.builder() .region(region) .build(); CompletableFutureListTablesResponse response client.listTables(ListTablesRequest.builder() .build()); // 将响应映射为仅包含表名的另一个 Future CompletableFutureListString tableNames response.thenApply(ListTablesResponse::tableNames); // 完成成功或失败后统一处理 tableNames.whenComplete((tables, err) - { try { if (tables ! null) { tables.forEach(System.out::println); } else { err.printStackTrace(); } } finally { client.close(); // 应用完全结束后再关闭客户端 } }); tableNames.join();三个关键点值得注意thenApply做响应映射把CompletableFutureListTablesResponse转换成只包含表名的CompletableFutureListString让下游回调只关心业务数据whenComplete统一成败处理无论异步操作成功还是抛错都会进入该回调tables null时通过err拿到异常.join()保证主线程等待异步回调是非阻塞的若主线程不等待程序可能直接退出同步等待使示例在命令行场景下可观察到完整输出。异步创建表asyncWaiter 等待表就绪DynamoDBAsyncCreateTable.java 是“异步 API 异步轮询”的进阶示例// 创建表的请求使用 PAY_PER_REQUEST 按量计费模式 CreateTableRequest request CreateTableRequest.builder() .attributeDefinitions(AttributeDefinition.builder() .attributeName(key) .attributeType(ScalarAttributeType.S) .build()) .keySchema(KeySchemaElement.builder() .attributeName(key) .keyType(KeyType.HASH) .build()) .billingMode(BillingMode.PAY_PER_REQUEST) // DynamoDB 按流量自动扩缩容 .tableName(tableName) .build(); CompletableFutureCreateTableResponse response client.createTable(request); response.whenComplete((table, err) - { if (table ! null) { // 通过 asyncWaiter 异步等待表进入 ACTIVE 状态 DynamoDbAsyncWaiter asyncWaiter client.waiter(); DescribeTableRequest tableRequest DescribeTableRequest.builder() .tableName(table.tableDescription().tableName()) .build(); CompletableFutureWaiterResponseDescribeTableResponse waiterResponse asyncWaiter.waitUntilTableExists(tableRequest); waiterResponse.whenComplete((r, t) - { String tableARN r.matched().response().get().table().tableArn(); System.out.println(The table tableARN is ready); }); waiterResponse.join(); } else { err.printStackTrace(); } }); response.join();实战要点BillingMode.PAY_PER_REQUEST按量计费注释明确指出 DynamoDB 会基于流量自动扩缩容适合示例与测试场景避免手动配置读写容量单位DynamoDbAsyncWaiter通过client.waiter()获取waitUntilTableExists返回CompletableFutureWaiterResponseDescribeTableResponse表进入 ACTIVE 后回调被触发此时可安全读取tableArn等元数据两个.join()response.join()等待建表完成waiterResponse.join()等待表就绪保证示例在退出前看到确定结果通过USAGE帮助文本可确认运行参数DynamoDBAsyncCreateTable table key例如DynamoDBAsyncCreateTable Music3 Artist。异步读取条目getItem 与 AttributeValueDynamoDBAsyncGetItem.java 演示按主键异步读取条目HashMapString, AttributeValue keyToGet new HashMap(); keyToGet.put(key, AttributeValue.builder().s(keyVal).build()); GetItemRequest request GetItemRequest.builder() .key(keyToGet) .tableName(tableName) .build(); java.util.CollectionAttributeValue returnedItem client.getItem(request).join().item().values();运行参数为三个table key keyVal例如DynamoDBAsyncGetItem Music3 Artist Famous Band。与同步版不同这里直接对getItem(request)返回的CompletableFuture调用.join()阻塞取结果再逐字段打印异常统一捕获DynamoDbException。源码中通过USAGE字符串明确给出了该程序的警告“该程序会真实读取你指定的条目”提醒读者注意数据与成本影响。异步分页全解析listTablesPaginator 的三种消费方式当表的数量很大时listTables单次最多返回 100 个表名可通过limit调整每页大小需要分页遍历。异步分页的核心是 SDK 生成的ListTablesPublisher——一个实现了org.reactivestreams.Publisher的异步响应式流。 AsyncPagination.java 将三种消费方式集中到一个类中通过命令行参数auto、manual或default选择执行路径Usage: AsynPagination type Where: type - the type of pagination. (auto, manual or default) Example: AsynPagination auto方式一手动分页一次一页手动方式本质上就是一次listTables调用 thenApply映射一次只拿一页适合需要完全控制请求节奏的场景CompletableFutureListTablesResponse response client.listTables(ListTablesRequest.builder().build()); CompletableFutureListString tableNames response.thenApply(ListTablesResponse::tableNames); tableNames.whenComplete((tables, err) - { if (tables ! null) { tables.forEach(System.out::println); } else { err.printStackTrace(); } }); Thread.sleep(3_000); // 非阻塞代码需等待异步结果完成方式二自动分页响应式订阅自动分页使用listTablesPaginator生成ListTablesPublisher以limit(3)控制每页条数便于观察多页输出final DynamoDbAsyncClient asyncClient DynamoDbAsyncClient.create(); ListTablesRequest listTablesRequest ListTablesRequest.builder().limit(3).build(); ListTablesPublisher publisher asyncClient.listTablesPaginator(listTablesRequest); // 方式 2aConsumer 简化订阅 CompletableFutureVoid future publisher.subscribe( response - response.tableNames().forEach(System.out::println)); future.get(); // 方式 2b完整 Subscriber 实现背压 publisher.subscribe(new SubscriberListTablesResponse() { private Subscription subscription; Override public void onSubscribe(Subscription s) { subscription s; subscription.request(1); // 每处理完一页后再请求下一页 } Override public void onNext(ListTablesResponse response) { response.tableNames().forEach(System.out::println); subscription.request(1); } Override public void onError(Throwable t) { /* 请求处理出错时回调 */ } Override public void onComplete() { /* 所有结果已投递完毕 */ } }); Thread.sleep(3_000);这段代码是理解 SDK 异步分页机制的钥匙listTablesPaginator返回ListTablesPublisher该对象实现 Reactive Streams 的Publisher会在后台自动发起后续页请求Consumer 变体subscribe(Consumer)返回CompletableFutureVoid适合简单打印场景.get()阻塞等待全部页处理完毕完整 Subscriber 变体演示了背压backpressure协议在onSubscribe中request(1)请求第一页在onNext处理完当前页后再次request(1)请求下一页onComplete表示所有页已投递完毕由于订阅是非阻塞的示例用Thread.sleep(3_000)保证主线程存活、能观察到全部页输出。方式三在条目集合上自动迭代tableNames()除了订阅“响应页”ListTablesPublisher还提供tableNames()返回SdkPublisherString让调用方直接按单个表名粒度消费省去自己从响应中取列表的样板代码ListTablesRequest listTablesRequest ListTablesRequest.builder().limit(3).build(); ListTablesPublisher listTablesPublisher asyncClient.listTablesPaginator(listTablesRequest); SdkPublisherString publisher listTablesPublisher.tableNames(); // Consumer 方式 CompletableFutureVoid future publisher.subscribe(System.out::println); future.get(); // Subscriber 方式同样按需 request publisher.subscribe(new SubscriberString() { 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() {} }); Thread.sleep(3_000);方式四接入第三方响应式库RxJava / ReactorListTablesPublisher是标准 Reactive StreamsPublisher因此可以无缝接入社区响应式库。仓库 pom.xml 中已声明rxjava 3.1.6与reactor-core 3.3.5示例演示了两种等价写法// RxJava 3Flowable.fromPublisher 桥接 SDK Publisher DynamoDbAsyncClient asyncClient DynamoDbAsyncClient.create(); ListTablesPublisher publisher asyncClient.listTablesPaginator(ListTablesRequest.builder().build()); ListString tables Flowable.fromPublisher(publisher) .flatMapIterable(ListTablesResponse::tableNames) .toList() .blockingGet(); System.out.println(tables);// ReactorFlux.from 桥接任意响应式流兼容 Publisher DynamoDbAsyncClient asyncClient DynamoDbAsyncClient.create(); ListTablesPublisher publisher asyncClient.listTablesPaginator(ListTablesRequest.builder().build()); ListString tables Flux.from(publisher) .flatMapIterable(ListTablesResponse::tableNames) .collectList() .block(); System.out.println(tables);从源码结构看SDK 的SdkPublisher是围绕org.reactivestreams.Publisher设计的因此Flowable.fromPublisher与Flux.from都能直接消费 SDK 分页流随后便可利用flatMapIterable、toList/collectList、blockingGet/block等响应式操作符做聚合、转换与阻塞收集——这为在已有 RxJava/Reactor 技术栈的项目中复用 AWS SDK 异步分页提供了官方示例佐证。JUnit 5 测试配置、执行与结果解读模块 README 明确指出异步示例的测试文件名为DynamoDBAsyncTest基于JUnit 5编写位于src/test/java目录该路径同样记录在 metadata.yaml 的测试清单中。测试可在 IntelliJ 等 Java IDE 中直接运行也可在命令行用 Maven 执行每个测试运行时都会输出成功/失败消息例如Test 3 passed。WARNING运行这些 JUnit 测试会操作真实的 Amazon DynamoDB 资源可能产生账号费用请在受控账号中执行。config.properties 的必填配置运行测试前必须在 src/main/resources/config.properties 中定义测试所需的全部值。若任一值未定义测试将失败。仓库自带一份示例值可作为填空模板配置项含义仓库示例值tableName一个已存在的表名供读取/查询类测试使用Customer100key该表的分区键名idkeyVal分区键的键值对应一个真实条目50newTableName测试中要新建的表名Customer110newKey新表使用的键55原 README 给出的示意值如表名Music3、键Artist、键值Famous Band只是示例实际运行时必须以你账号中真实存在的资源为准并把config.properties中的值替换为真实表与真实条目。命令行执行 mvn test在模块根目录执行mvn testMaven Surefire 插件pom.xml 中版本3.5.2会扫描src/test/java下的 JUnit 5 测试并执行。正常输出形如[INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running DynamoDBAsyncTest Running Amazon DynamoDB Test 1 Running Amazon DynamoDB Test 2 ... Done! [INFO] Results: [INFO] [INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] BUILD SUCCESSTests run: 3, Failures: 0, Errors: 0, Skipped: 0意味着 3 个用例全部通过。若任何断言失败或配置缺失则会出现Tests run: N, Failures: M, Errors: K的非零失败计数。测试失败排查若config.properties中值不正确例如tableName指向不存在的表、keyVal对应条目不存在测试将失败输出类似[INFO] BUILD FAILURE [ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.1:test (default-test) on project ...: There are test failures.此时应回到config.properties逐一核对五项配置是否与你账号中的真实 DynamoDB 资源一致表是否存在、键名/键值是否匹配修正后重新运行mvn test。README 中同时提醒若配置文件未定义全部值JUnit 测试会直接失败。常见陷阱与最佳实践小结综合 README 与四个示例类的源码实现可沉淀出以下实践要点异步不等于免等待所有示例最终都通过.join()、.get()或Thread.sleep等待异步结果否则 JVM 可能在回调执行前退出客户端生命周期源码注释多次强调“只在应用完全结束运行时才client.close()”在finally块中关闭是推荐做法见DynamoDBAsyncListTables与DynamoDBAsyncCreateTable异步 Waiter 是异步链式的正确解法建表后不要用同步轮询而是通过DynamoDbAsyncWaiter.waitUntilTableExists获得CompletableFutureWaiterResponse...与上游createTable的 Future 无缝串联分页务必利用 Paginator手动一次一页适合低频场景需要全量遍历时优先使用listTablesPaginator Consumer/Subscriber并以背压方式逐页request(1)控制流量标准响应式流带来生态红利ListTablesPublisher是标准org.reactivestreams.Publisher可直接被 RxJavaFlowable.fromPublisher、ReactorFlux.from消费聚合到List后再阻塞收集与既有响应式栈共存测试前先填配置config.properties五项配置缺一不可且必须对应账号内真实资源生产或共享账号中运行前务必评估费用与权限。深入阅读指引模块入口 READMEjavav2/example_code/dynamodbasync/README.md异步分页完整示例AsyncPagination.java异步建表 Waiter 示例DynamoDBAsyncCreateTable.java异步读取条目示例DynamoDBAsyncGetItem.java异步列表示例DynamoDBAsyncListTables.java构建与依赖pom.xml、run_example.sh、Makefile测试配置模板config.properties服务清单metadata.yaml本模块位于 javav2 语言示例集内同语言其他服务示例可参考 javav2/example_code 目录结构。赞分享示例工程教程后端【免费下载链接】aws-doc-sdk-examplesWelcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below.项目地址https://gitcode.com/gh_mirrors/aw/aws-doc-sdk-examples点击查看免费下载相关推荐微信聊天记录永久备份终极指南WeChatMsg完整方案实现数据自主微信聊天记录永久备份终极指南WeChatMsg完整方案实现数据自主 你是否曾因手机更换而丢失珍贵的微信聊天记录那些与亲友的温馨对话、重要的工作沟通、充满回忆AWS SDK for Java 2.x 实战在 aws-doc-sdk-examples 中运行与测试 Amazon MQ 的 Java 示例AWS SDK for Java 2.x 实战在 aws doc sdk examples 中运行与测试 Amazon MQ 的 Java 示例 本文基于 j示例工程教程后端AWS SDK for Java 2.x DynamoDB AdaptiveRetryStrategy 实战指南配置、迁移与最佳实践AWS SDK for Java 2.x DynamoDB AdaptiveRetryStrategy 实战指南配置、迁移与最佳实践 本文基于 aws doc示例工程教程后端上一篇PKSM宝可梦存档管理器从新手到高手的终极使用指南下一篇3分钟掌握PDF补丁丁免费开源的PDF全能处理工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考