使用程式設計 DynamoDB AWS SDK for Java 2.x - Amazon DynamoDB

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用程式設計 DynamoDB AWS SDK for Java 2.x

本程式設計指南為想要將 Amazon DynamoDB 與 Java 搭配使用的程式設計人員提供指導。本指南涵蓋不同的概念,包括抽象層、組態管理、錯誤處理、控制重試原則,以及管理 keep-alive。

關於 AWS SDK for Java 2.x

您可以使用官方從 Java 存取 DynamoDB 資料庫。 AWS SDK for Java對SDK於 Java 有兩個版本:1.x 和 2.x。1.x 版已 end-of-support 於二零二四年一月十二日佈。它將於 2024 年 7 月 31 日進入維護模式,截止日期 end-of-support 為 2025 年 12 月 31 日。對於新開發,我們強烈建議您使用 2.x,該 2.x 於 2018 年首次發布。本指南專門針對 2.x,並僅著重於與 DynamoDB SDK 相關的部分。

如需有關維護和支援的資訊 AWS SDKs,請參閱AWS SDK和工具維護政策AWS SDKs和工具版本支援對照表AWS SDKs和工具參考指南

AWS SDK for Java 2.x 是 1.x 代碼庫的主要重寫。Java 2.x 版支援現代 Java 功能,例如 Java 8 中引入的非封鎖 I/O。SDKSDKfor Java 2.x 還增加了對可插拔HTTP客戶端實現的支持,以提供更多的網絡連接靈活性和配置選項。

Java 1.x 和 Java 2.x 版之間的一個明顯變化是使用新的軟件包名稱。SDK SDKJava 1.x SDK 使用com.amazonaws包名稱,而 Java 2.x SDK 使用。software.amazon.awssdk同樣,Java 1.x 的 Maven 工件SDK使用 com.amazonawsgroupId,而 Java 2.x SDK 工件使用. software.amazon.awssdk groupId

重要

AWS SDK for Java 1.x 有一個 DynamoDB 的套件。com.amazonaws.dynamodbv2包名稱中的「v2」並不表示它適用於 Java 2(J2SE)。相API反地,「v2」表示套件支援 DynamoDB 低階的第二個版本,而不是低階的原始版本。API

Support Java 版本

AWS SDK for Java 2.x 提供對長期支援 (LTS) Java 發行版本的完整支援。

AWS SDK for Java 2.x入門

下面的教程告訴你如何使用阿帕奇 Maven 定義的 Java 2.x 的SDK依賴關係。本教學課程也會示範如何撰寫連線至 DynamoDB 的程式碼,以列出可用的 DynamoDB 表格。本指南中的教學課程是以開AWS SDK for Java 2.x 發人員指南 AWS SDK for Java 2.x中的〈開始使用自學課程為基礎。我們已編輯此教學課程,以呼叫 DynamoDB 而非 Amazon S3。

步驟 1:設定此教學課程

在開始本自學課程之前,您需要下列項目:

  • 存取動 DynamoDB 權限。

  • 一種 Java 開發環境,設定了 AWS 服務 使用 AWS 存取入口網站.

若要設定此教學課程,請依照AWS SDK for Java 2.x 開發人員指南中安裝程式概觀中的指示進行。在您使用 Java 的單一登入存取權設定開發環境之後,SDK並擁有使用中的 AWS 存取入口網站工作階段,然後繼續執行本教學課程的步驟 2

步驟 2:建立專案

若要為本教學課程建立專案,請執行 Maven 命令,提示您輸入如何設定專案。輸入並確認所有輸入後,Maven 通過創建文件並創建存根 Java 文件來完成構建項目。pom.xml

  1. 開啟終端機或命令提示字元視窗,然後導覽至您選擇的目錄,例如您的DesktopHome資料夾。

  2. 在終端機上輸入下列命令,然後按 Enter

    mvn archetype:generate \ -DarchetypeGroupId=software.amazon.awssdk \ -DarchetypeArtifactId=archetype-app-quickstart \ -DarchetypeVersion=2.22.0
  3. 對於每個提示,輸入第二欄中列示的值。

    提示 要輸入的值
    Define value for property 'service': dynamodb
    Define value for property 'httpClient': apache-client
    Define value for property 'nativeImage': false
    Define value for property 'credentialProvider' identity-center
    Define value for property 'groupId': org.example
    Define value for property 'artifactId': getstarted
    Define value for property 'version' 1.0-SNAPSHOT: <Enter>
    Define value for property 'package' org.example: <Enter>
  4. 輸入最後一個值之後,Maven 會列出您所做的選擇。若要確認,請輸入 Y。 或者,輸入 N,然後重新輸入您的選擇。

Maven 創建一個getstarted基於您輸入的artifactId值命名的項目文件夾。在資getstarted料夾內,尋找您README.md可以檢閱的pom.xml檔案、檔案和src目錄。

Maven 構建以下目錄樹。

getstarted ├── README.md ├── pom.xml └── src ├── main │ ├── java │ │ └── org │ │ └── example │ │ ├── App.java │ │ ├── DependencyFactory.java │ │ └── Handler.java │ └── resources │ └── simplelogger.properties └── test └── java └── org └── example └── HandlerTest.java 10 directories, 7 files

以下展示了pom.xml項目文件的內容。

dependencyManagement節包含的相依性 AWS SDK for Java 2.x,而且該dependencies區段具有 DynamoDB 的相依性。指定這些依賴關係會強制 Maven 在 Java 類路徑中包含相關.jar文件。默認情況下, AWS SDK不包括所有的所有類 AWS 服務。對於 DynamoDB,如果您使用低階介面,則應該對成品具有相依性。dynamodb或者,如果您使用高級接口,則在dynamodb-enhanced工件上。如果你沒有包含相關的依賴關係,那麼你的代碼就無法編譯。由於maven.compiler.sourcemaven.compiler.target屬性中的1.8值,專案會使用 Java 1.8。

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>getstarted</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.shade.plugin.version>3.2.1</maven.shade.plugin.version> <maven.compiler.plugin.version>3.6.1</maven.compiler.plugin.version> <exec-maven-plugin.version>1.6.0</exec-maven-plugin.version> <aws.java.sdk.version>2.22.0</aws.java.sdk.version> <-------- SDK version picked up from archetype version. <slf4j.version>1.7.28</slf4j.version> <junit5.version>5.8.1</junit5.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>${aws.java.sdk.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>dynamodb</artifactId> <-------- DynamoDB dependency <exclusions> <exclusion> <groupId>software.amazon.awssdk</groupId> <artifactId>netty-nio-client</artifactId> </exclusion> <exclusion> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>sso</artifactId> <-------- Required for identity center authentication. </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>ssooidc</artifactId> <-------- Required for identity center authentication. </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> <-------- HTTP client specified. <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>${slf4j.version}</version> </dependency> <!-- Needed to adapt Apache Commons Logging used by Apache HTTP Client to Slf4j to avoid ClassNotFoundException: org.apache.commons.logging.impl.LogFactoryImpl during runtime --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <!-- Test Dependencies --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>${junit5.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven.compiler.plugin.version}</version> </plugin> </plugins> </build> </project>

步驟 3:撰寫程式碼

下面的代碼顯示了 Maven 創建的App類。該main方法是應用程序的進入點,它創建了該Handler類的實例,然後調用其sendRequest方法。

package org.example; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class App { private static final Logger logger = LoggerFactory.getLogger(App.class); public static void main(String... args) { logger.info("Application starts"); Handler handler = new Handler(); handler.sendRequest(); logger.info("Application ends"); } }

Maven 創建的DependencyFactory類包含構建並返回DynamoDbClient實例的dynamoDbClient工廠方法。DynamoDbClient執行個體會使用以 APACH HTTP E 為基礎的用戶端的執行個體。這是因為您apache-client在 Maven 提示您使用哪個HTTP客戶端時指定。

下列程式碼顯示 DependencyFactory 類別。

package org.example; import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; /** * The module containing all dependencies required by the {@link Handler}. */ public class DependencyFactory { private DependencyFactory() {} /** * @return an instance of DynamoDbClient */ public static DynamoDbClient dynamoDbClient() { return DynamoDbClient.builder() .httpClientBuilder(ApacheHttpClient.builder()) .build(); } }

Handler類包含程序的主要邏輯。在App類別中建立Handler的執行個體時,會DependencyFactory提供DynamoDbClient服務用戶端。您的程式碼會使用DynamoDbClient執行個體來呼叫 DynamoDB。

Maven 生成帶有TODO註釋以下Handler類。教學課程的下一個步驟會以程式碼取代TODO註解。

package org.example; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; public class Handler { private final DynamoDbClient dynamoDbClient; public Handler() { dynamoDbClient = DependencyFactory.dynamoDbClient(); } public void sendRequest() { // TODO: invoking the API calls using dynamoDbClient. } }

若要填入邏輯,請使用下列程式碼取代Handler類別的全部內容。該sendRequest方法被填入,並添加必要的導入。

下列程式碼會使用DynamoDbClient執行個體擷取現有資料表的清單。如果指定帳戶存在資料表 AWS 區域,則程式碼會使用Logger執行個體來記錄這些資料表的名稱。

package org.example; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse; public class Handler { private final DynamoDbClient dynamoDbClient; public Handler() { dynamoDbClient = DependencyFactory.dynamoDbClient(); } public void sendRequest() { Logger logger = LoggerFactory.getLogger(Handler.class); logger.info("calling the DynamoDB API to get a list of existing tables"); ListTablesResponse response = dynamoDbClient.listTables(); if (!response.hasTableNames()) { logger.info("No existing tables found for the configured account & region"); } else { response.tableNames().forEach(tableName -> logger.info("Table: " + tableName)); } } }

步驟 4:建置並執行應用程式

創建項目並包含完整的Handler類後,構建並運行應用程序。

  1. 請確定您有作用中的 AWS IAM Identity Center 工作階段。若要確認,請執行 AWS Command Line Interface (AWS CLI) 命令aws sts get-caller-identity並檢查回應。如果您沒有使用中的工作階段,請參閱使用登入以取 AWS CLI得指示。

  2. 打開終端機或命令提示符窗口,然後導航到您的項目目錄getstarted

  3. 要構建您的項目,請運行以下命令:

    mvn clean package
  4. 若要執行應用程式,請執行下列命令:

    mvn exec:java -Dexec.mainClass="org.example.App"

檢視檔案後,請刪除物件,然後刪除值區。

Success (成功)

如果您的 Maven 項目構建並運行沒有錯誤,那麼恭喜!您已成功地使用 Java 2.x 版建置您的第一個 Java 應用程式。SDK

清除

若要清理您在本自學課程中建立的資源,請刪除專案資料夾getstarted

檢閱文 AWS SDK for Java 2.x 件

AWS SDK for Java 2.x 開發人員指南涵蓋了所有內容的SDK所有方面 AWS 服務。我們建議您檢閱下列主題:

提示

檢閱這些主題後,請將「AWS SDK for Java 2.x API參考」加入書籤。它涵蓋了所有內容 AWS 服務,我們建議您將其用作主要API參考。

支援的介面

AWS SDK for Java 2.x 支援下列介面,視您想要的抽象層級而定。

低階介面

低階介面提供基礎服務API的 one-to-one 對應。每個 DynamoDB API 都可透過此介面取得。這意味著低級界面可以提供完整的功能,但使用起來通常更加冗長和複雜。例如,您必須使用.s()函數來保存字符串和.n()函數來保存數字。下面的例子中PutItem插入使用低級接口的項目。

import org.slf4j.*; import software.amazon.awssdk.http.crt.AwsCrtHttpClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.*; import java.util.Map; public class PutItem { // Create a DynamoDB client with the default settings connected to the DynamoDB // endpoint in the default region based on the default credentials provider chain. private static final DynamoDbClient DYNAMODB_CLIENT = DynamoDbClient.create(); private static final Logger LOGGER = LoggerFactory.getLogger(PutItem.class); private void putItem() { PutItemResponse response = DYNAMODB_CLIENT.putItem(PutItemRequest.builder() .item(Map.of( "pk", AttributeValue.builder().s("123").build(), "sk", AttributeValue.builder().s("cart#123").build(), "item_data", AttributeValue.builder().s("YourItemData").build(), "inventory", AttributeValue.builder().n("500").build() // ... more attributes ... )) .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) .tableName("YourTableName") .build()); LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)"); } }

高階介面

中的高階介面稱 AWS SDK for Java 2.x 為 DynamoDB 增強型用戶端。此介面提供更慣用的程式碼撰寫體驗。

增強型用戶端提供了一種在用戶端資料類別和專為儲存該資料而設計的 DynamoDB 表之間進行對應的方法。您要在自己的程式碼中定義資料表及其對應模型類別之間的關係。然後,您可以依靠SDK來管理資料類型操作。如需有關增強型用戶端的詳細資訊,請參閱AWS SDK for Java 2.x 開發人員指南API中的 DynamoDB 增強型用戶端

下面的示例PutItem使用高級接口。在此範例中,DynamoDbBean具名YourItem會建立TableSchema可直接用作putItem()呼叫輸入的 a。

import org.slf4j.*; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.*; import software.amazon.awssdk.enhanced.dynamodb.model.*; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; public class DynamoDbEnhancedClientPutItem { private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<YourItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromBean(YourItem.class)); private static final Logger LOGGER = LoggerFactory.getLogger(PutItem.class); private void putItem() { PutItemEnhancedResponse<YourItem> response = DYNAMODB_TABLE.putItemWithResponse(PutItemEnhancedRequest.builder(YourItem.class) .item(new YourItem("123", "cart#123", "YourItemData", 500)) .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) .build()); LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)"); } @DynamoDbBean public static class YourItem { public YourItem() {} public YourItem(String pk, String sk, String itemData, int inventory) { this.pk = pk; this.sk = sk; this.itemData = itemData; this.inventory = inventory; } private String pk; private String sk; private String itemData; private int inventory; @DynamoDbPartitionKey public void setPk(String pk) { this.pk = pk; } public String getPk() { return pk; } @DynamoDbSortKey public void setSk(String sk) { this.sk = sk; } public String getSk() { return sk; } public void setItemData(String itemData) { this.itemData = itemData; } public String getItemData() { return itemData; } public void setInventory(int inventory) { this.inventory = inventory; } public int getInventory() { return inventory; } } }

AWS SDK for Java 1.x 具有自己的高級接口,通常由其主類DynamoDBMapper引用。在一個單獨的包(和 Maven 工件)中發布名為software.amazon.awssdk.enhanced.dynamodb。 AWS SDK for Java 2.x Java 2.x 通SDK常由它的主類DynamoDbEnhancedClient提到。

使用不可變數據類的高級接口

DynamoDB 增強型用戶端的對應功能API也適用於不可變的資料類別。一個不可變的類只有 getter,並且需要一個構建器類,SDK用於創建類的實例。Java 中的不變性是一種常用的樣式,開發人員可以使用它來創建沒有副作用的類。這些類在複雜的多線程應用程序中的行為更可預測。而不是使用@DynamoDbBean註釋,如圖所示High-level interface example,不可變的類使用@DynamoDbImmutable註釋,它將構建器類作為其輸入。

下列範例會將建置器類別DynamoDbEnhancedClientImmutablePutItem當做輸入,以建立資料表結構定義。然後,此範例會提供結構描述做為PutItemAPI呼叫的輸入。

import org.slf4j.*; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.model.*; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; public class DynamoDbEnhancedClientImmutablePutItem { private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<YourImmutableItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromImmutableClass(YourImmutableItem.class)); private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedClientImmutablePutItem.class); private void putItem() { PutItemEnhancedResponse<YourImmutableItem> response = DYNAMODB_TABLE.putItemWithResponse(PutItemEnhancedRequest.builder(YourImmutableItem.class) .item(YourImmutableItem.builder() .pk("123") .sk("cart#123") .itemData("YourItemData") .inventory(500) .build()) .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) .build()); LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)"); } }

下面的例子顯示了不可變的數據類。

@DynamoDbImmutable(builder = YourImmutableItem.YourImmutableItemBuilder.class) class YourImmutableItem { private final String pk; private final String sk; private final String itemData; private final int inventory; public YourImmutableItem(YourImmutableItemBuilder builder) { this.pk = builder.pk; this.sk = builder.sk; this.itemData = builder.itemData; this.inventory = builder.inventory; } public static YourImmutableItemBuilder builder() { return new YourImmutableItemBuilder(); } @DynamoDbPartitionKey public String getPk() { return pk; } @DynamoDbSortKey public String getSk() { return sk; } public String getItemData() { return itemData; } public int getInventory() { return inventory; } static final class YourImmutableItemBuilder { private String pk; private String sk; private String itemData; private int inventory; private YourImmutableItemBuilder() {} public YourImmutableItemBuilder pk(String pk) { this.pk = pk; return this; } public YourImmutableItemBuilder sk(String sk) { this.sk = sk; return this; } public YourImmutableItemBuilder itemData(String itemData) { this.itemData = itemData; return this; } public YourImmutableItemBuilder inventory(int inventory) { this.inventory = inventory; return this; } public YourImmutableItem build() { return new YourImmutableItem(this); } } }

使用不可變數據類和第三方樣板生成庫的高級接口

不可變的資料類別 (如前面的範例所示) 需要一些樣板程式碼。例如,在數據類的吸氣和 setter 邏輯,除了Builder類。協力廠商程式庫 (例如 Project London) 可協助您產生該樣板程式碼類型。減少大部分的樣板程式碼可協助您限制處理不可變資料類別和. AWS SDK 這進一步導致提高了代碼的生產力和可讀性。如需詳細資訊,請參閱AWS SDK for Java 2.x 開發人員指南中的使用第三方程式庫,例如 London。

下列範例示範龍目島專案如何簡化使用 DynamoDB 增強型用戶端所需的程式碼。API

import org.slf4j.*; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.model.*; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; public class DynamoDbEnhancedClientImmutableLombokPutItem { private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<YourImmutableLombokItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromImmutableClass(YourImmutableLombokItem.class)); private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedClientImmutableLombokPutItem.class); private void putItem() { PutItemEnhancedResponse<YourImmutableLombokItem> response = DYNAMODB_TABLE.putItemWithResponse(PutItemEnhancedRequest.builder(YourImmutableLombokItem.class) .item(YourImmutableLombokItem.builder() .pk("123") .sk("cart#123") .itemData("YourItemData") .inventory(500) .build()) .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) .build()); LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)"); } }

下面的例子顯示了不可變數據類的不可變數據對象。

import lombok.*; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.*; @Builder @DynamoDbImmutable(builder = YourImmutableLombokItem.YourImmutableLombokItemBuilder.class) @Value public class YourImmutableLombokItem { @Getter(onMethod_=@DynamoDbPartitionKey) String pk; @Getter(onMethod_=@DynamoDbSortKey) String sk; String itemData; int inventory; }

YourImmutableLombokItem類使用項目龍目島和 AWS SDK提供的以下註釋:

  • @Builder-APIs 為龍目島項目提供的數據類生成複雜的構建器。

  • @ DynamoDbImmutable — 將類別識DynamoDbImmutable別為提供的 DynamoDB 可對應實體註釋。 AWS SDK

  • @Value — 的不可變變體@Data。默認情況下,所有字段都是私有和最終的,並且不會生成設置者。龍目島項目提供了這個註釋。

文件介面

AWS SDK for Java 2.x Document 介面可避免指定資料類型描述元的需求。資料類型是由資料本身的語義隱含的。本文件介面類似於 AWS SDK for Java 1.x 的 Document 介面,但具有重新設計的介面。

以下Document interface example顯示使用「文件」介面表示的PutItem呼叫。這個例子也使用 EnhancedDocument. 若要使用增強的文件對 DynamoDB 表執行命令API,您必須先將表格與文件表格結構描述相關聯,才能建立DynamoDBTable資源物件。Document 表格結構描述產生器需要主索引鍵和屬性轉換器提供者。

您可以使用AttributeConverterProvider.defaultProvider()來轉換預設類型的文件屬性。您可以使用自訂AttributeConverterProvider實作來變更整體預設行為。您也可以變更單一屬性的轉換器。《AWS SDKs和工具參考指南》提供有關如何使用自定義轉換器的更多詳細信息和示例。它們的主要用途是用於沒有默認轉換器的域類的屬性。使用自訂轉換器,您可以提SDK供寫入或讀取 DynamoDB 所需的資訊。

import org.slf4j.*; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; import software.amazon.awssdk.enhanced.dynamodb.model.*; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; public class DynamoDbEnhancedDocumentClientPutItem { private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<EnhancedDocument> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.documentSchemaBuilder() .addIndexPartitionKey(TableMetadata.primaryIndexName(),"pk", AttributeValueType.S) .addIndexSortKey(TableMetadata.primaryIndexName(), "sk", AttributeValueType.S) .attributeConverterProviders(AttributeConverterProvider.defaultProvider()) .build()); private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedDocumentClientPutItem.class); private void putItem() { PutItemEnhancedResponse<EnhancedDocument> response = DYNAMODB_TABLE.putItemWithResponse( PutItemEnhancedRequest.builder(EnhancedDocument.class) .item( EnhancedDocument.builder() .attributeConverterProviders(AttributeConverterProvider.defaultProvider()) .putString("pk", "123") .putString("sk", "cart#123") .putString("item_data", "YourItemData") .putNumber("inventory", 500) .build()) .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) .build()); LOGGER.info("PutItem call consumed [" + response.consumedCapacity().capacityUnits() + "] Write Capacity Unites (WCU)"); } }

若要將JSON文件與原生 Amazon DynamoDB 資料類型之間進行轉換,您可以使用下列公用程式方法:

將介面與Query範例進行比較

本節顯示使用各種接口表達的相同Query調用。若要微調這些查詢的結果,請注意下列事項:

  • DynamoDB 會鎖定一個特定的分區索引鍵值,因此您必須完全指定分割區索引鍵。

  • 若要讓查詢目標只有購物車項目,排序索引鍵具有使用的索引鍵條件運算式begins_with

  • 我們使limit()用將查詢限制為最多 100 個返回的項目。

  • 我們設置scanIndexForward為假。結果按 UTF -8 個字節的順序返回,這通常意味著首先返回數量最小的購物車項目。通過scanIndexForward將設置為 false,我們反轉順序,並首先返回具有最高數量的購物車項目。

  • 我們應用過濾器來刪除不匹配條件的任何結果。無論項目符合篩選器,所篩選的資料都會消耗讀取容量。

範例 Query使用低級接口

下列範例會查詢名為YourTableName使用keyConditionExpression. 這會將查詢限制在以特定字首值開頭的特定分區索引鍵值和排序索引鍵值。這些關鍵條件會限制從 DynamoDB 讀取的資料量。最後,查詢會使用 a 對從 DynamoDB 擷取的資料套用篩選器。filterExpression

import org.slf4j.*; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.*; import java.util.Map; public class Query { // Create a DynamoDB client with the default settings connected to the DynamoDB // endpoint in the default region based on the default credentials provider chain. private static final DynamoDbClient DYNAMODB_CLIENT = DynamoDbClient.builder().build(); private static final Logger LOGGER = LoggerFactory.getLogger(Query.class); private static void query() { QueryResponse response = DYNAMODB_CLIENT.query(QueryRequest.builder() .expressionAttributeNames(Map.of("#name", "name")) .expressionAttributeValues(Map.of( ":pk_val", AttributeValue.fromS("id#1"), ":sk_val", AttributeValue.fromS("cart#"), ":name_val", AttributeValue.fromS("SomeName"))) .filterExpression("#name = :name_val") .keyConditionExpression("pk = :pk_val AND begins_with(sk, :sk_val)") .limit(100) .scanIndexForward(false) .tableName("YourTableName") .build()); LOGGER.info("nr of items: " + response.count()); LOGGER.info("First item pk: " + response.items().get(0).get("pk")); LOGGER.info("First item sk: " + response.items().get(0).get("sk")); } }
範例 Query使用文件介面

下列範例會查詢YourTableName使用 Document 介面命名的表格。

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; import software.amazon.awssdk.enhanced.dynamodb.model.*; import java.util.Map; public class DynamoDbEnhancedDocumentClientQuery { // Create a DynamoDB client with the default settings connected to the DynamoDB // endpoint in the default region based on the default credentials provider chain. private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<EnhancedDocument> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.documentSchemaBuilder() .addIndexPartitionKey(TableMetadata.primaryIndexName(),"pk", AttributeValueType.S) .addIndexSortKey(TableMetadata.primaryIndexName(), "sk", AttributeValueType.S) .attributeConverterProviders(AttributeConverterProvider.defaultProvider()) .build()); private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedDocumentClientQuery.class); private void query() { PageIterable<EnhancedDocument> response = DYNAMODB_TABLE.query(QueryEnhancedRequest.builder() .filterExpression(Expression.builder() .expression("#name = :name_val") .expressionNames(Map.of("#name", "name")) .expressionValues(Map.of(":name_val", AttributeValue.fromS("SomeName"))) .build()) .limit(100) .queryConditional(QueryConditional.sortBeginsWith(Key.builder() .partitionValue("id#1") .sortValue("cart#") .build())) .scanIndexForward(false) .build()); LOGGER.info("nr of items: " + response.items().stream().count()); LOGGER.info("First item pk: " + response.items().iterator().next().getString("pk")); LOGGER.info("First item sk: " + response.items().iterator().next().getString("sk")); } }
範例 Query使用高階介面

下列範例會查詢使用 DynamoDB 增強型YourTableName用戶端命名的資料表。API

import org.slf4j.*; import software.amazon.awssdk.enhanced.dynamodb.*; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.*; import software.amazon.awssdk.enhanced.dynamodb.model.*; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import java.util.Map; public class DynamoDbEnhancedClientQuery { private static final DynamoDbEnhancedClient ENHANCED_DYNAMODB_CLIENT = DynamoDbEnhancedClient.builder().build(); private static final DynamoDbTable<YourItem> DYNAMODB_TABLE = ENHANCED_DYNAMODB_CLIENT.table("YourTableName", TableSchema.fromBean(DynamoDbEnhancedClientQuery.YourItem.class)); private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbEnhancedClientQuery.class); private void query() { PageIterable<YourItem> response = DYNAMODB_TABLE.query(QueryEnhancedRequest.builder() .filterExpression(Expression.builder() .expression("#name = :name_val") .expressionNames(Map.of("#name", "name")) .expressionValues(Map.of(":name_val", AttributeValue.fromS("SomeName"))) .build()) .limit(100) .queryConditional(QueryConditional.sortBeginsWith(Key.builder() .partitionValue("id#1") .sortValue("cart#") .build())) .scanIndexForward(false) .build()); LOGGER.info("nr of items: " + response.items().stream().count()); LOGGER.info("First item pk: " + response.items().iterator().next().getPk()); LOGGER.info("First item sk: " + response.items().iterator().next().getSk()); } @DynamoDbBean public static class YourItem { public YourItem() {} public YourItem(String pk, String sk, String name) { this.pk = pk; this.sk = sk; this.name = name; } private String pk; private String sk; private String name; @DynamoDbPartitionKey public void setPk(String pk) { this.pk = pk; } public String getPk() { return pk; } @DynamoDbSortKey public void setSk(String sk) { this.sk = sk; } public String getSk() { return sk; } public void setName(String name) { this.name = name; } public String getName() { return name; } } }
使用不可變數據類的高級接口

當您Query使用高階不可變資料類別執行時,除了實體類別YourItemYourImmutableItem建構之外,程式碼與高階介面範例相同。如需詳細資訊,請參閱PutItem範例。

使用不可變數據類和第三方樣板生成庫的高級接口

當您Query使用高階不可變資料類別執行時,除了實體類別YourItemYourImmutableLombokItem建構之外,程式碼與高階介面範例相同。如需詳細資訊,請參閱PutItem範例。

其他程式碼範例

如需如何將 DynamoDB 與 Java 2.x 搭配使用的其他範例,請參閱下列程式碼範例儲存庫:SDK

同步和異步編程

提 AWS SDK for Java 2.x 供同同步用戶端 AWS 服務,例如 DynamoDB。

DynamoDbClientDynamoDbEnhancedClient類別會提供同步方法,這些方法會封鎖執行緒的執行,直到用戶端收到來自服務的回應為止。如果您不需要非同步作業,此用戶端是與 DynamoDB 互動的最直接方式。

DynamoDbAsyncClientDynamoDbEnhancedAsyncClient類別提供立即傳回的非同步方法,並將控制權交還給呼叫執行緒,而不需等待回應。非封鎖用戶端的優點是,它使用在幾個執行緒之間進行高度並行處理,以最少的運算資源提供有效率的 I/O 要求處理。這提高了吞吐量和響應能力。

AWS SDK for Java 2.x 使用原生支援非阻塞 I/O。 AWS SDK for Java 1.x 必須模擬非阻塞 I/O。

同步方法在響應可用之前返回,因此您需要一種方法在準備就緒時獲取響應。在異步方法 AWS SDK for Java 返回一個包含 future 異步操作結果的CompletableFuture對象。當您呼叫get()join()在這些CompletableFuture物件上時,程式碼會封鎖,直到結果可用為止。如果您在發出請求的同時調用這些,則行為類似於普通的同步調用。

如需非同步程式設計的詳細資訊,請參閱AWS SDK for Java 2.x 開發人員指南中的使用非同步程式

HTTP客戶

為了支援每個用戶端,有一個HTTP用戶端可以處理與 AWS 服務. 您可以插入替代HTTP客戶端,選擇具有最適合您應用的特性的客戶端。有些更輕量;有些則有更多的組態選項。

有些用HTTP戶端僅支援同步使用,而其他用戶端僅支援非同步使用。如需可協助您為工作負載選取最佳HTTP用戶端的流程圖,請參閱AWS SDK for Java 2.x 開發人員指南中的HTTP用戶端建議

下列清單顯示了一些可能的HTTP用戶端:

基於阿帕奇的HTTP客戶端

ApacheHttpClient類別支援同步服務用戶端。它是同步使用的預設用HTTP戶端。如需有關設定ApacheHttpClient類別的詳細資訊,請參閱開發人員指南中的 < 設定以 Apache> 為基礎的HTTP AWS SDK for Java 2.x 用戶端

URLConnection基於HTTP用戶端

UrlConnectionHttpClient類別是同步用戶端的另一個選項。它的載入速度比以 APACHE 為基礎的HTTP用戶端快,但功能較少。如需有關設定UrlConnectionHttpClient類別的資訊,請參閱AWS SDK for Java 2.x 開發人員指南中的 < 設定URLConnection基於HTTP用戶端 >。

基於網絡的客戶端 HTTP

NettyNioAsyncHttpClient類支持異步客戶端。這是異步使用的默認選擇。如需設定NettyNioAsyncHttpClient類別的相關資訊,請參閱AWS SDK for Java 2.x 開發人員指南中的 < 設定 Netty HTTP 用戶端 >。

AWS CRT基於HTTP用戶端

來自 AWS Common Runtime (CRT) 程式庫的較新版本AwsCrtHttpClientAwsCrtAsyncHttpClient類別是支援同步和非同步用戶端的更多選項。與其他HTTP客戶相比, AWS CRT提供:

  • 更快的SDK啟動時間

  • 更小的內存佔用

  • 減少延遲時間

  • 連線健康管理

  • DNS負載平衡

如需有關設定AwsCrtHttpClientAwsCrtAsyncHttpClient類別的資訊,請參閱AWS SDK for Java 2.x 開發人員指南中的 < 設定 AWS CRT基於用HTTP戶端 >。

AWS CRT基於HTTP客戶端不是默認的,因為這會破壞現有應用程序的向後兼容性。但是,對於 DynamoDB,我們建議您同時使用 AWS CRT以基礎的用HTTP戶端進行同步和非同步用途。

如需 AWS CRT基於用HTTP戶端的簡介,請參閱AWS 開發人員工具部落格 AWS SDK for Java 2.x上的宣布用 AWS CRTHTTP戶端可用性

設定 HTTP 用戶端

設定用戶端時,您可以提供各種組態選項,包括:

  • 設置API通話的不同方面的超時。

  • 啟用TCP保持活著。

  • 發生錯誤時控制重試原則。

  • 指定執行攔截器執行個體可以修改的執行屬性。執行攔截器可以編寫攔截API請求和響應執行的代碼。這可讓您執行諸如發佈指標和修改執行中要求之類的工作。

  • 添加或操作HTTP標題。

  • 啟用用戶端效能指標的追蹤。使用此功能可協助您收集有關應用程式中服務用戶端的指標,並分析 Amazon 中的輸出 CloudWatch。

  • 指定用於排程工作的替代執行程式服務,例如非同步重試嘗試和逾時工作。

您可以將ClientOverrideConfiguration物件提供給服務用戶端Builder類別來控制組態。您將在以下各節的一些代碼示例中看到這一點。

ClientOverrideConfiguration供標準組態選擇。不同的可插拔HTTP客戶端也具有特定於實現的配置可能性。

逾時組態

您可以調整用戶端組態,以控制與維修呼叫相關的各種逾時。與其他產品相比,DynamoDB 提供的延遲時間較低。 AWS 服務因此,您可能想要調整這些屬性以降低逾時值,以便在發生網路問題時快速失敗。

您可以使用 DynamoDB 用戶端ClientOverrideConfiguration上或變更基HTTP礎用戶端實作的詳細組態選項,來自訂延遲相關行為。

您可以使用以下方法配置以下具有影響力的屬性:ClientOverrideConfiguration

  • apiCallAttemptTimeout— 在放棄和逾時之前等待HTTP請求完成的單次嘗試的時間量。

  • apiCallTimeout— 用戶端必須完全執行API呼叫的時間量。這包括由所有要求 (包括重試) 組成的要HTTP求處理常式執行。

提 AWS SDK for Java 2.x 供某些逾時選項的預設值,例如連線逾時和通訊端逾時。SDK不提供通話逾時或個別API通API話嘗試逾時的預設值。如果未在中設定這些逾時ClientOverrideConfiguration,則SDK會使用通訊端逾時值來取代整體API呼叫逾時。通訊端逾時的預設值為 30 秒。

RetryMode

與您應該考慮的超時配置相關的另一個配置是RetryMode配置對象。此配置物件包含重試行為的集合。

SDK適用於 Java 2.x 的支援下列重試模式:

  • legacy-默認的重試模式,如果你沒有明確改變它。此重試模式特定於 Java SDK。它的特點是最多三次重試,或者針對 DynamoDB 等服務的重試次數,最多可重試八次。

  • standard— 命名為「標準」,因為它與其他更一致 AWS SDKs。此模式會等待從 0 毫秒到 1,000 毫秒的隨機時間,以進行第一次重試。如果需要另一次重試,則此模式會從 0 毫秒到 1,000 毫秒之間挑選另一個隨機時間,並將其乘以 2。如果需要額外的重試,那麼它會執行相同的隨機選擇乘以四,依此類推。每次等待時間上限為 20 秒。此模式會在偵測到的失敗情況下執行重試次數超過legacy模式。對於 DynamoDB,除非您使用覆寫,否則最多可執行三次總嘗試次數。numRetries

  • adaptive— 建立在standard模式上並動態限制 AWS 請求的速率,以最大限度地提高成功率。這可能會以請求延遲為代價的情況發生。如果可預測的延遲很重要,我們不建議調適性重試模式。

您可以在AWS SDKs和工具參考指南中的「重試行為」主題中找到這些重試模式的展開定義。

重試原則

所有RetryMode配置都有一個 RetryPolicy,它是基於一個或多個RetryCondition配置構建的。對TokenBucketRetryCondition於 DynamoDB SDK 用戶端實作的重試行為而言,這一點特別重要。此條件會限制使用 Token 值區演算法SDK進行的重試次數。根據選取的重試模式,節流例外可能會或可能不會從. TokenBucket

當用戶端遇到可重試的錯誤時,例如節流例外狀況或暫時性伺服器錯誤,則SDK會自動重試要求。您可以控制這些重試發生的次數和速度。

設定用戶端時,您可以提供RetryPolicy支援下列參數的:

  • numRetries— 在請求被視為失敗之前,應套用的重試次數上限。無論您使用的重試模式為何,預設值都是 8。

    警告

    請務必在適當考量之後變更此預設值。

  • backoffStrategy— 套用BackoffStrategy至重試,FullJitterBackoffStrategy且為預設策略。此策略會根據目前的次數或重試次數、基本延遲和最大輪詢時間,在其他重試之間執行指數延遲。然後,它增加了抖動以提供一些隨機性。無論重試模式如何,指數延遲中使用的基本延遲都是 25 ms。

  • retryConditionRetryCondition決定是否完全重試要求。默認情況下,它重試一組特定的HTTP狀態代碼和異常,它認為是可重試的。在大多數情況下,預設組態應該足夠。

下列程式碼提供替代的重試原則。它總共指定了五次重試(總共六個請求)。第一次重試應該在大約 100 毫秒的延遲後發生,每次額外的重試都會以指數方式加倍該時間,最大延遲為一秒鐘。

DynamoDbClient client = DynamoDbClient.builder() .overrideConfiguration(ClientOverrideConfiguration.builder() .retryPolicy(RetryPolicy.builder() .backoffStrategy(FullJitterBackoffStrategy.builder() .baseDelay(Duration.ofMillis(100)) .maxBackoffTime(Duration.ofSeconds(1)) .build()) .numRetries(5) .build()) .build()) .build();

DefaultsMode

超時屬性ClientOverrideConfigurationRetryMode不管理通常通過指定DefaultsMode.

AWS SDK for Java 2.x (版本 2.17.102 或更新版本) 引入了對. DefaultsMode 此功能為一般可設定設定提供一組預設值,例如HTTP通訊設定、重試行為、服務地區端點設定,以及可能的任何SDK相關組態。使用此功能時,您可以取得針對常見使用案例量身打造的新組態預設值。

預設模式在所有的標準化 AWS SDKs。SDK適用於 Java 2.x 的支援下列預設模式:

  • legacy— 提供預設設定,這些設定依 AWS SDK建立之前DefaultsMode存在而有所不同。

  • standard— 提供大多數案例的預設非最佳化設定。

  • in-region— 基於標準模式構建,並包括針對 AWS 服務 從同一模式調用的應用程序量身定制的設置 AWS 區域。

  • cross-region— 以標準模式為基礎,並針對 AWS 服務 在不同地區呼叫的應用程式提供高逾時的設定。

  • mobile— 基於標準模式構建,並包括針對延遲較高的移動應用程序量身定制的高超時設置。

  • auto— 基於標準模式構建,並包括實驗功能。SDK嘗試探索執行階段環境以自動判斷適當的設定。自動檢測是基於啟發式的,不提供 100% 的準確性。如果無法確定運行時環境,則使用標準模式。自動偵測可能會查詢執行個體中繼資料和使用者資料,這可能會導致延遲。如果啟動延遲對您的應用程式很重要,我們建議您DefaultsMode改為選擇明確的。

您可以透過下列方式設定預設模式:

  • 直接在用戶端上,透過AwsClientBuilder.Builder#defaultsMode(DefaultsMode)

  • 在組態設定檔上,透過defaults_mode設定檔案屬性。

  • 在全球範圍內,透過aws.defaultsMode系統屬性。

  • 在全球範圍內,透過AWS_DEFAULTS_MODE環境變數。

注意

對於除此之外的任何模式legacy,出售的默認值可能會隨著最佳實踐的發展而改變。因此,如果您使用的模式不是legacy,建議您在升級SDK.

AWS SDKs和工具參考指南中的智慧型組態預設值提供了不同預設模式下的組態屬性及其預設值的清單。

您可以根據應用程式的特性和應用程式互動的特性 AWS 服務 來選擇預設模式值。

這些值的配置時考慮了廣泛 AWS 服務 的選擇。對於在一個區域中部署 DynamoDB 表和應用程式的典型 DynamoDB 部署,預設模式在in-region預設模式中最為相關。standard

範例 針對低延遲呼叫進行調整的 DynamoDB SDK 用戶端組態

下列範例會將逾時調整為降低預期低延遲 DynamoDB 呼叫的值。

DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.builder() .defaultsMode(DefaultsMode.IN_REGION) .httpClientBuilder(AwsCrtAsyncHttpClient.builder()) .overrideConfiguration(ClientOverrideConfiguration.builder() .apiCallTimeout(Duration.ofSeconds(3)) .apiCallAttemptTimeout(Duration.ofMillis(500)) .build()) .build();

個別用HTTP戶端實作可能會為您提供更精細的逾時和連線使用行為控制。例如,對於以用戶端為 AWS CRT基礎的用戶端,您可以啟動ConnectionHealthConfiguration,如此可讓用戶端主動監控已使用連線的健全狀況。如需詳細資訊,請參閱AWS SDK for Java 2.x 開發人員指南的 AWS CRT基於用HTTP戶端的進階設定

保持活動配置

啟用保持活動狀態可以通過重複使用連接來減少延遲。有兩種不同類型的保持活著:保持活著和HTTP保持活著。TCP

  • HTTPKeep-Alive 嘗試維護客戶端和服務器之間的HTTPS連接,以便稍後的請求可以重複使用該連接。這會在以後的請求中跳過重量級HTTPS身份驗證。HTTP依預設,所有用戶端都會啟用「保持連線」。

  • TCPKeep-Alive 要求:基礎作業系統透過通訊端連線傳送小型封包,以提供額外的保證,讓通訊端保持運作狀態,並立即偵測任何中斷。這可確保以後的請求不會花費時間嘗試使用丟棄的套接字。依預設,所有用戶端上的「TCP保持連線」都會停用。下列程式碼範例說明如何在每個用HTTP戶端上啟用它。針對所有非CRT基礎用HTTP戶端啟用時,實際的 Keep-Alive 機制取決於作業系統。因此,您必須透過作業系統設定其他 TCP Keep-Alive 值,例如逾時和封包數目。您可以在 Linux 或 macOS sysctl 上使用,或在視窗上使用註冊表值來執行此操作。

範例 在基於 APACHE 的客戶TCP端上啟用保持活動狀態 HTTP
DynamoDbClient client = DynamoDbClient.builder() .httpClientBuilder(ApacheHttpClient.builder().tcpKeepAlive(true)) .build();
URLConnection基於HTTP用戶端

任何使用URLConnection以基礎為基礎的用HTTP戶端的同步用戶端都HttpURLConnection沒有啟用 keep-alive 的機制

範例 在基於 Nett 的客戶端上啟用TCP保持活動狀態 HTTP
DynamoDbAsyncClient client = DynamoDbAsyncClient.builder() .httpClientBuilder(NettyNioAsyncHttpClient.builder().tcpKeepAlive(true)) .build();
範例 在以基礎為基礎的用戶TCP端上啟用保持作 AWS CRT用中 HTTP

使用 AWS CRT基於HTTP客戶端,您可以啟用TCP保持活動狀態並控制持續時間。

DynamoDbClient client = DynamoDbClient.builder() .httpClientBuilder(AwsCrtHttpClient.builder() .tcpKeepAliveConfiguration(TcpKeepAliveConfiguration.builder() .keepAliveInterval(Duration.ofSeconds(50)) .keepAliveTimeout(Duration.ofSeconds(5)) .build())) .build();

使用非同步 DynamoDB 用戶端時,您可以啟用TCP保持活動,如下列程式碼所示。

DynamoDbAsyncClient client = DynamoDbAsyncClient.builder() .httpClientBuilder(AwsCrtAsyncHttpClient.builder() .tcpKeepAliveConfiguration(TcpKeepAliveConfiguration.builder() .keepAliveInterval(Duration.ofSeconds(50)) .keepAliveTimeout(Duration.ofSeconds(5)) .build())) .build();

錯誤處理

當涉及到異常處理時, AWS SDK for Java 2.x 使用運行時(未選中)異常。

覆蓋所有SDK異常的基本異常是 SdkServiceException,它從未選中的 Java 擴展RuntimeException。如果你 catch 到這一點,你會 catch SDK 拋出的所有異常。

SdkServiceException有一個名為的子類別AwsServiceException。該子類別表示与 AWS 服務。它有一個名為的子類別 DynamoDbException,表示與 DynamoDB 通訊時存在問題。如果您發現這一點,您將 catch 與 DynamoDB 相關的所有異常,但沒有其他SDK異常。

下有更特定的例外型態DynamoDbException。其中一些例外狀況類型適用於控制平面操作,例如。TableAlreadyExistsException其他則適用於資料平面作業。以下是一個常見的數據平面異常的例子:

  • ConditionalCheckFailedException— 您在要求中指定評估為 false 的條件。例如,您可能已嘗試對項目執行條件式更新,但屬性的實際值不符合條件中的預期值。不會重試以這種方式失敗的要求。

其他情況沒有定義特定的例外狀況。例如,當您的請求被限制時,特定的ProvisionedThroughputExceededException可能會被拋出,而在其他情況下,會拋出更通用DynamoDbException的。在任何一種情況下,您都可以通過檢查是否返回來確定節流是否isThrottlingException()導致異常。true

根據您的應用程式需求,您可以 catch 取所有AwsServiceExceptionDynamoDbException執行個體。但是,在不同情況下,您通常需要不同的行為。處理條件檢查失敗的邏輯與處理節流的邏輯不同。定義您要處理的特殊路徑,並確保測試替代路徑。這可協助您確保您可以處理所有相關案例。

如需可能遇到的常見錯誤清單,請參閱使用 DynamoDB 時發生錯誤。另請參閱 Amazon DynamoDB API 參考資料中的常見錯誤。「API參考」還提供了每個API作業 (例如作業) 可能出現的確切錯Query誤。如需處理例外狀況的詳細資訊,請參閱AWS SDK for Java 2.x 開發人員指南 AWS SDK for Java 2.x中的 < 例外狀況處理

AWS 請求識別碼

每個請求都包含一個請求 ID,如果您正在使用診斷問題,則可 AWS Support 以提取請求 ID。衍生自的每個例外狀況都SdkServiceException有可用來擷取要求 ID 的requestId()方法。

日誌

使用SDK提供的記錄功能對於從用戶端程式庫擷取任何重要訊息以及用於更深入的偵錯目的都很有用。記錄器是分層的,並SDK用software.amazon.awssdk作其根記錄器。您可以使用TRACE、、、、DEBUGINFOWARNERROR或之一來設定層級OFFALL配置的級別適用於該記錄器,並向下到記錄器層次結構。

對於其日誌記錄, AWS SDK for Java 2.x 使用 Java 的簡單日誌外觀()SLF4J。這充當其他記錄器周圍的抽象層,您可以使用它來插入您喜歡的記錄器。如需有關插入記錄器的指示,請參閱SLF4J使用者手冊。

每個記錄器都有特定的行為。根據預設,Log4j 2.x 記錄器會建立一個ConsoleAppender,將記錄事件附加到記錄檔層級,而System.out且預設值會附加至記錄檔層級。ERROR

默認情況下,SLF4J輸出中包含的 SimpleLogger System.err記錄器默認為INFO日誌級別。

建議您針對任何生產部署將層級設定WARNsoftware.amazon.awssdk為,以便從用戶端程式庫 catch 取SDK任何重要訊息,同時限制輸出數量。

SLF4J如果在類路徑上找不到受支持的記錄器(無SLF4J綁定),則默認為無操作實現。此實現會記錄消息,SLF4J以System.err解釋無法在類路徑上找到記錄器實現。為了防止這種情況,你必須添加一個記錄器實現。要做到這一點,你可以在你的 Apache Maven pom.xml 添加一個依賴關係的工件,如org.slf4j.slf4j-simpleorg.apache.logging.log4j.log4j-slf4j2-imp

如需有關如何在中設定記錄的詳細資訊SDK,包括將記錄相依性新增至您的應用程式組態,請參閱AWS SDK for Java 開發人員指南中的使用 Java 2.x 進行記錄。SDK

Log4j2.xml文件中的以下配置顯示了如何調整日誌記錄行為,如果您使用 Apache 的 Log4j 2 記錄器。此配置將根記錄器級別設置為WARN。階層中的所有記錄器都會繼承此記錄層級,包括software.amazon.awssdk記錄器。

依預設,輸出會移至System.out。在下面的例子中,我們仍然覆蓋默認輸出 Log4j 的追加程序來應用量身定制的 Log4j。PatternLayout

Log4j2.xml組態檔案的範例

下列組態會將訊息記錄到所有記錄器階層的ERROR和層WARN級的主控台。

<Configuration status="WARN"> <Appenders> <Console name="ConsoleAppender" target="SYSTEM_OUT"> <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" /> </Console> </Appenders> <Loggers> <Root level="WARN"> <AppenderRef ref="ConsoleAppender"/> </Root> </Loggers> </Configuration>

AWS 請求識別碼記錄

當出現問題時,您可以IDs在異常中找到請求。但是,如果您希望請IDs求未生成異常的請求,則可以使用日誌記錄。

software.amazon.awssdk.request錄器IDs在DEBUG水平輸出請求。下列範例會延伸前一configuration example個項目ERROR,以保持根記錄器層級WARNsoftware.amazon.awssdk at 層級和 software.amazon.awssdk.request at 層級DEBUG。設定這些層級有助於 catch 取要求IDs和其他要求相關詳細資料,例如端點和狀態碼。

<Configuration status="WARN"> <Appenders> <Console name="ConsoleAppender" target="SYSTEM_OUT"> <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" /> </Console> </Appenders> <Loggers> <Root level="ERROR"> <AppenderRef ref="ConsoleAppender"/> </Root> <Logger name="software.amazon.awssdk" level="WARN" /> <Logger name="software.amazon.awssdk.request" level="DEBUG" /> </Loggers> </Configuration>

以下為日誌輸出的範例:

2022-09-23 16:02:08 [main] DEBUG software.amazon.awssdk.request:85 - Sending Request: DefaultSdkHttpFullRequest(httpMethod=POST, protocol=https, host=dynamodb.us-east-1.amazonaws.com, encodedPath=/, headers=[amz-sdk-invocation-id, Content-Length, Content-Type, User-Agent, X-Amz-Target], queryParameters=[]) 2022-09-23 16:02:08 [main] DEBUG software.amazon.awssdk.request:85 - Received successful response: 200, Request ID: QS9DUMME2NHEDH8TGT9N5V53OJVV4KQNSO5AEMVJF66Q9ASUAAJG, Extended Request ID: not available

分頁

某些要求 (例如Query和) 會Scan限制單一要求傳回的資料大小,並要求您重複提出要求以提取後續頁面。

您可以使用參數控制每個頁面要讀取的最大項目Limit數。例如,您可以使用Limit參數只擷取最後 10 個項目。此限制指定在套用任何篩選之前,要從表格讀取的項目數。如果你想在過濾後恰好 10 個項目,沒有辦法指定。您只能控制預先篩選的計數,並在實際擷取 10 個項目時檢查用戶端。無論限制為何,回應的大小上限都是 1 MB。

A LastEvaluatedKey 可能會包含在API回應中。這表示回應因為達到計數限制或大小限制而結束。此索引鍵是針對該回應評估的最後一個索引鍵。透過與直接互動API,您可以擷取此項目,LastEvaluatedKey並將其傳遞給後續呼叫,以ExclusiveStartKey便從該起點讀取下一個區塊。如果傳回 noLastEvaluatedKey,則表示沒有其他符合QueryScanAPI呼叫的項目。

下列範例使用低階介面,根據keyConditionExpression參數將項目限制為 100。

QueryRequest.Builder queryRequestBuilder = QueryRequest.builder() .expressionAttributeValues(Map.of( ":pk_val", AttributeValue.fromS("123"), ":sk_val", AttributeValue.fromN("1000"))) .keyConditionExpression("pk = :pk_val AND sk > :sk_val") .limit(100) .tableName(TABLE_NAME); while (true) { QueryResponse queryResponse = DYNAMODB_CLIENT.query(queryRequestBuilder.build()); queryResponse.items().forEach(item -> { LOGGER.info("item PK: [" + item.get("pk") + "] and SK: [" + item.get("sk") + "]"); }); if (!queryResponse.hasLastEvaluatedKey()) { break; } queryRequestBuilder.exclusiveStartKey(queryResponse.lastEvaluatedKey()); }

透過提供 AWS SDK for Java 2.x 可進行多個服務呼叫的自動分頁方法,以自動為您取得下一頁結果,藉此簡化與 DynamoDB 的互動。這簡化了您的代碼,但它消除了一些對資源使用情況的控制,您可以通過手動讀取頁面來保持這些控制。

透過使用 DynamoDB 用戶端中可用的Iterable方法,例如QueryPaginatorScanPaginator,SDK會處理分頁。這些方法的返回類型是一個自定義迭代,您可以使用它來遍歷所有頁面。SDK內部會為您處理服務呼叫。使用 Java 流API,可以處理的結果顯QueryPaginator示在下面的例子。

QueryPublisher queryPublisher = DYNAMODB_CLIENT.queryPaginator(QueryRequest.builder() .expressionAttributeValues(Map.of( ":pk_val", AttributeValue.fromS("123"), ":sk_val", AttributeValue.fromN("1000"))) .keyConditionExpression("pk = :pk_val AND sk > :sk_val") .limit(100) .tableName("YourTableName") .build()); queryPublisher.items().subscribe(item -> System.out.println(item.get("itemData"))).join();

資料類別註解

Java 提SDK供了幾個註釋,你可以把你的數據類的屬性。這些註釋會影響與屬性的SDK互動方式。藉由新增註解,您可以讓屬性表現為隱含的原子計數器、維護自動產生的時間戳記值,或追蹤項目版本號碼。如需詳細資訊,請參閱 < 資料類別註解 >。