遷移 step-by-step 指示與示例 - AWS SDK for Java 2.x

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

遷移 step-by-step 指示與示例

本節提供 step-by-step 指南,說明如何將目前使用適用於 Java v1.x 的 SDK 的應用程式移轉至適用於 Java 2.x 的 SDK。第一部分介紹了步驟的概述,隨後是遷移的詳細示例。

此處涵蓋的步驟說明一般 AWS 服務 使用案例的移轉,其中應用程式會使用模型導向服務用戶端呼叫。如果您需要遷移使用較高層級 API 的程式碼,例如 S3 傳輸管理員CloudFront預先簽署,請參閱目AWS SDK for Java 1.x 和 2.x 之間有什麼不同錄下的章節。

這裡描述的方法是一個建議。您可以使用其他技術並利用 IDE 的代碼編輯功能來達到相同的結果。

步驟概觀

1. 首先添加適用于 Java 2.x 用料表的 SDK

通過將適用於 Java 2.x 的 SDK 的 Maven BOM(物料清單)元素添加到 POM 文件中,您可以確保您需要的所有 v2 依賴項都來自同一版本。您的 POM 可以包含 v1 和 v2 依賴關係。這使您可以逐步遷移代碼,而不是一次更改所有代碼。

<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.24.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

您可以在 Maven 中央存儲庫上找到最新版本

2. 搜索 V1 類導入語句的文件

通過掃描應用程序中的文件以查找 v1 導入中使用的 Service_ID,您將找到使用的唯一服務 ID。一個服務 ID 是一個簡短的,唯一的名稱。 AWS 服務例如cognitoidentity,Amazon Cognito 身份的服務 ID。

3. 從 V1 導入語句確定 V2 Maven 的依賴關係

找到所有唯一的 v1 Service_ID 之後,您可以通過參考來確定 v2 依賴項的相應 Maven 工件。Package 名稱至 MartifactId 對應

4. 將 v2 依賴元素添加到 POM 文件

使用在步驟 3 確定的依賴元素更新 Maven POM 文件。

5. 在 Java 文件中,逐步更改 V1 類到 v2 類

當您用 v2 類替換 v1 類時,請進行必要的更改以支持 v2 API,例如使用構建器而不是構造函數以及使用流暢的 getter 和 setter。

6. 從 POM 中刪除 v1 Maven 依賴關係,並從文件中導入 v1

遷移代碼以使用 v2 類後,請從文件中刪除所有剩餘的 v1 導入以及構建文件中的所有依賴項。

7. 重構代碼以使用 v2 API 增強功能

程式碼成功編譯並通過測試之後,您可以利用 v2 增強功能,例如使用不同的 HTTP 用戶端或分頁器來簡化程式碼。此為選用步驟。

移轉範例

在此範例中,我們移轉使用 SDK 進行 Java v1 並存取多個應用程式 AWS 服務。我們在步驟 5 中詳細執行以下 v1 方法。這是一個包含八個方法的類中的一個方法,並且在應用程序中有 32 個類。

下面只列出了 Java 文件中的第一個 SDK 導入。

import com.amazonaws.ClientConfiguration; import com.amazonaws.regions.Region; import com.amazonaws.regions.RegionUtils; import com.amazonaws.services.ec2.AmazonEC2Client; import com.amazonaws.services.ec2.model.AmazonEC2Exception; import com.amazonaws.services.ec2.model.CreateTagsRequest; import com.amazonaws.services.ec2.model.DescribeInstancesRequest; import com.amazonaws.services.ec2.model.DescribeInstancesResult; import com.amazonaws.services.ec2.model.Instance; import com.amazonaws.services.ec2.model.InstanceStateName; import com.amazonaws.services.ec2.model.Reservation; import com.amazonaws.services.ec2.model.Tag; import com.amazonaws.services.ec2.model.TerminateInstancesRequest; ... private static List<Instance> getRunningInstances(AmazonEC2Client ec2, List<String> instanceIds) { List<Instance> runningInstances = new ArrayList<>(); try { DescribeInstancesRequest request = new DescribeInstancesRequest() .withInstanceIds(instanceIds); DescribeInstancesResult result; do { // DescribeInstancesResponse is a paginated response, so use tokens with multiple requests. result = ec2.describeInstances(request); request.setNextToken(result.getNextToken()); // Prepare request for next page. for (final Reservation r : result.getReservations()) { for (final Instance instance : r.getInstances()) { LOGGER.info("Examining instanceId: "+ instance.getInstanceId()); // if instance is in a running state, add it to runningInstances list. if (RUNNING_STATES.contains(instance.getState().getName())) { runningInstances.add(instance); } } } } while (result.getNextToken() != null); } catch (final AmazonEC2Exception exception) { // if instance isn't found, assume its terminated and continue. if (exception.getErrorCode().equals(NOT_FOUND_ERROR_CODE)) { LOGGER.info("Instance probably terminated; moving on."); } else { throw exception; } } return runningInstances; }

1. 添加 V2 的 Maven 的 BOM

將適用於 Java 2.x 的 SDK 的 Maven BOM 添加到該部分中的任何其他依賴項的聚甲醛。dependencyManagement如果您的 POM 文件具有 SDK 第 1 版的 BOM,請立即保留它。它將在稍後的步驟中刪除。

<dependencyManagement> <dependencies> <dependency> <groupId>org.example</groupId> <!--Existing dependency in POM. --> <artifactId>bom</artifactId> <version>1.3.4</version> <type>pom</type> <scope>import</scope> </dependency> ... <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-bom</artifactId> <!--Existing v1 BOM dependency. --> <version>1.11.1000</version> <type>pom</type> <scope>import</scope> </dependency> ... <dependency> <groupId>software.amazon.awssdk</groupId> <!--Add v2 BOM dependency. --> <artifactId>bom</artifactId> <version>2.24.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

2. 搜索 V1 類導入語句的文件

在應用程式的程式碼中搜尋的唯一出現次數import com.amazonaws.services。這有助於我們確定項目使用的 v1 依賴關係。如果您的應用程序具有列出 v1 依賴關係的 Maven POM 文件,則可以使用此信息。

在這個範例中,我們使用 ripgrep(rg) 命令來搜尋程式碼庫。

從代碼庫的根目錄中,執行以下ripgrep命令。ripgrep找到匯入陳述式之後,會將它們傳送至cutsort、和uniq指令以隔離 Service_ID。

rg --no-filename 'import\s+com\.amazonaws\.services' | cut -d '.' -f 4 | sort | uniq

對於此應用程序,以下 Service_ID 會記錄到控制台。

autoscaling cloudformation ec2 identitymanagement

這表示在import語句中使用的以下每個包名稱中至少有一次出現。我們的四個目的,個別的班級名稱並不重要。我們只需要找到所使用的服務 ID。

com.amazonaws.services.autoscaling.* com.amazonaws.services.cloudformation.* com.amazonaws.services.ec2.* com.amazonaws.services.identitymanagement.*

3. 從 V1 導入語句確定 V2 Maven 的依賴關係

我們autoscaling與步驟 2(例如,例如,)隔離的 v1 的 Service_ID cloudformation 可以映射到大多數情況下相同的 v2 SERVICE_ID。由於 v2 Maven 文 artifactId ID 在大多數情況下匹配 SERVICE_ID,因此您擁有將依賴塊添加到 POM 文件所需的信息。

下表顯示了我們如何確定 v2 的依賴關係。

V1 服務識別碼對應至...

套件名稱

v2 服務識別碼對應至...

套件名稱

V2 的 Maven 依賴

ec2

com.amazonaws.services.ec2.*

ec2

software.amazon.awssdk.services.ec2.*

<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>ec2</artifactId> </dependency>

自動調度

com.amazonaws.services.autoscaling.*

自動調度

software.amazon.awssdk.services.autoscaling.*

<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>autoscaling</artifactId> </dependency>
cloudformation

com.amazonaws.services.cloudformation.*

cloudformation

software.amazon.awssdk.cloudformation.*

<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>cloudformation</artifactId> </dependency>
身分識別管理 *

com.amazonaws.services.identitymanagement.*

我的 *

software.amazon.awssdk.iam.*

<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>iam</artifactId> </dependency>

* identitymanagementiam對應是一個例外狀況,其中不同版本的 SERVICE_ID 不同。如果 Maven 或搖籃無法解析 v2 依賴關係,請參閱異常。Package 名稱至 MartifactId 對應

4. 將 v2 依賴元素添加到 POM 文件

在步驟 3 中,我們確定了需要添加到 POM 文件的四個依賴塊。我們不需要新增版本,因為我們已在步驟 1 中指定 BOM。導入添加後,我們的 POM 文件具有以下依賴元素。

... <dependencies> ... <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>autoscaling</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>iam</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>cloudformation</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>ec2</artifactId> </dependency> ... </dependencies> ...

5. 在 Java 文件中,逐步更改 V1 類到 v2 類

在我們正在遷移的方法中,我們看到

  • 來自的 EC2 服務用戶端com.amazonaws.services.ec2.AmazonEC2Client

  • 使用了幾個 EC2 模型類別。例如DescribeInstancesRequestDescribeInstancesResult.

import com.amazonaws.ClientConfiguration; import com.amazonaws.regions.Region; import com.amazonaws.regions.RegionUtils; import com.amazonaws.services.ec2.AmazonEC2Client; import com.amazonaws.services.ec2.model.AmazonEC2Exception; import com.amazonaws.services.ec2.model.CreateTagsRequest; import com.amazonaws.services.ec2.model.DescribeInstancesRequest; import com.amazonaws.services.ec2.model.DescribeInstancesResult; import com.amazonaws.services.ec2.model.Instance; import com.amazonaws.services.ec2.model.InstanceStateName; import com.amazonaws.services.ec2.model.Reservation; import com.amazonaws.services.ec2.model.Tag; import com.amazonaws.services.ec2.model.TerminateInstancesRequest; ... private static List<Instance> getRunningInstances(AmazonEC2Client ec2, List<String> instanceIds) List<Instance> runningInstances = new ArrayList<>(); try { DescribeInstancesRequest request = new DescribeInstancesRequest() .withInstanceIds(instanceIds); DescribeInstancesResult result; do { // DescribeInstancesResponse is a paginated response, so use tokens with multiple re result = ec2.describeInstances(request); request.setNextToken(result.getNextToken()); // Prepare request for next page. for (final Reservation r : result.getReservations()) { for (final Instance instance : r.getInstances()) { LOGGER.info("Examining instanceId: "+ instance.getInstanceId()); // if instance is in a running state, add it to runningInstances list. if (RUNNING_STATES.contains(instance.getState().getName())) { runningInstances.add(instance); } } } } while (result.getNextToken() != null); } catch (final AmazonEC2Exception exception) { // if instance isn't found, assume its terminated and continue. if (exception.getErrorCode().equals(NOT_FOUND_ERROR_CODE)) { LOGGER.info("Instance probably terminated; moving on."); } else { throw exception; } } return runningInstances; } ...

我們的目標是用 v2 進口替換所有 v1 進口。我們一次進行一個課程。

a. 替換導入語句或類名

我們看到該describeRunningInstances方法的第一個參數是 v1 AmazonEC2Client 實例。執行以下任意一項:

  • 將匯入取代為,com.amazonaws.services.ec2.AmazonEC2Clientsoftware.amazon.awssdk.services.ec2.Ec2ClientAmazonEC2Client將其變更為Ec2Client

  • 將參數類型變更為,Ec2Client並讓 IDE 提示我們進行正確的匯入。我們的 IDE 將提示我們導入 v2 類,因為客戶端名稱不同-AmazonEC2ClientEc2Client。如果兩個版本中的類名相同,則此方法不起作用。

b. 用 v2 等效物替換 v1 模型類

更改到 V2 之後Ec2Client,如果我們使用 IDE,我們會在下面的語句中看到編譯錯誤。

result = ec2.describeInstances(request);

使用 v1 的執行個體DescribeInstancesRequest做為 v2 Ec2Client describeInstances 方法的參數所導致的編譯錯誤。要修復,請進行以下替換或導入語句。

取代 取代為
import com.amazonaws.services.ec2.model.DescribeInstancesRequest
import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest

c. 將 v1 構造函數更改為 v2 構建器。

我們仍然看到編譯錯誤,因為 v2 類上沒有構造函數。要修復,請進行以下更改。

變更
final DescribeInstancesRequest request = new DescribeInstancesRequest() .withInstanceIds(instanceIdsCopy);
final DescribeInstancesRequest request = DescribeInstancesRequest.builder() .instanceIds(instanceIdsCopy) .build();

d. 以 v2 對*Response等物件取代 v1 *Result 回應物件

v1 和 v2 之間的一致區別在於 v2 中的所有響應對象都以*Response而不是結束*Result。將 v1 DescribeInstancesResult 匯入取代為 v2 匯入DescribeInstancesResponse

d. 進行 API 變更

下面的語句需要一些改變。

request.setNextToken(result.getNextToken());

在 v2 中,設定器方法不會使用set或搭配prefix。前綴的吸氣方法也get在 Java 2.x 的 SDK 中消失了

模型類(例如request實例)在 v2 中是不可變的,因此我們需要使用構建器創建一DescribeInstancesRequest個新的。

在 v2 中,語句變成以下內容。

request = DescribeInstancesRequest.builder() .nextToken(result.nextToken()) .build();

d. 重複,直到方法與 v2 類編譯

繼續其餘的代碼。用 v2 導入替換 v1 導入並修復編譯錯誤。根據需要參考 v2 API 參考什麼是不同的參考

我們遷移這個單一的方法後,我們有下面的 V2 代碼。

import com.amazonaws.ClientConfiguration; import com.amazonaws.regions.Region; import com.amazonaws.regions.RegionUtils; import com.amazonaws.services.ec2.AmazonEC2Client; import com.amazonaws.services.ec2.model.AmazonEC2Exception; import com.amazonaws.services.ec2.model.CreateTagsRequest; import com.amazonaws.services.ec2.model.InstanceStateName; import com.amazonaws.services.ec2.model.Tag; import com.amazonaws.services.ec2.model.TerminateInstancesRequest; import software.amazon.awssdk.services.ec2.Ec2Client; import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest; import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse; import software.amazon.awssdk.services.ec2.model.Ec2Exception; import software.amazon.awssdk.services.ec2.model.Instance; import software.amazon.awssdk.services.ec2.model.Reservation; ... private static List<Instance> getRunningInstances(Ec2Client ec2, List<String> instanceIds) { List<Instance> runningInstances = new ArrayList<>(); try { DescribeInstancesRequest request = DescribeInstancesRequest.builder() .instanceIds(instanceIds) .build(); DescribeInstancesResponse result; do { // DescribeInstancesResponse is a paginated response, so use tokens with multiple re result = ec2.describeInstances(request); request = DescribeInstancesRequest.builder() // Prepare request for next page. .nextToken(result.nextToken()) .build(); for (final Reservation r : result.reservations()) { for (final Instance instance : r.instances()) { // if instance is in a running state, add it to runningInstances list. if (RUNNING_STATES.contains(instance.state().nameAsString())) { runningInstances.add(instance); } } } } while (result.nextToken() != null); } catch (final Ec2Exception exception) { // if instance isn't found, assume its terminated and continue. if (exception.awsErrorDetails().errorCode().equals(NOT_FOUND_ERROR_CODE)) { LOGGER.info("Instance probably terminated; moving on."); } else { throw exception; } } return runningInstances; } ...

因為我們正在遷移具有八種方法的 Java 文件中的單個方法,因此我們在處理文件時混合使用 v1 和 v2 導入。當我們執行這些步驟時,我們添加了最後六個 import 語句。

我們遷移所有的代碼後,將不會有更多的 v1 導入語句。

6. 從 POM 中刪除 v1 Maven 依賴關係,並從文件中導入 v1

我們遷移文件中的所有 v1 代碼後,我們有以下 v2 SDK 導入語句。

import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.ServiceMetadata; import software.amazon.awssdk.services.ec2.Ec2Client; import software.amazon.awssdk.services.ec2.model.CreateTagsRequest; import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest; import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse; import software.amazon.awssdk.services.ec2.model.Ec2Exception; import software.amazon.awssdk.services.ec2.model.Instance; import software.amazon.awssdk.services.ec2.model.InstanceStateName; import software.amazon.awssdk.services.ec2.model.Reservation; import software.amazon.awssdk.services.ec2.model.Tag; import software.amazon.awssdk.services.ec2.model.TerminateInstancesRequest;

遷移應用程序中的所有文件後,我們不再需要在我們的 POM 文件 v1 依賴關係。如果使用,請從區dependencyManagement段移除 v1 BOM,以及所有 v1 相依性區塊。

7. 重構代碼以使用 v2 API 增強功能

對於我們一直在遷移的片段,我們可以選擇使用 v2 分頁器,並讓 SDK 管理基於令牌的請求以獲取更多數據。

我們可以用以下內容替換整個do條款。

DescribeInstancesIterable responses = ec2.describeInstancesPaginator(request); responses.reservations().stream() .forEach(reservation -> reservation.instances() .forEach(instance -> { if (RUNNING_STATES.contains(instance.state().nameAsString())) { runningInstances.put(instance.instanceId(), instance); } }));