本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
遷移 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
找到匯入陳述式之後,會將它們傳送至cut
sort
、和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
|
ec2
|
|
自動調度
|
自動調度
|
|
cloudformation
|
cloudformation
|
|
身分識別管理 *
|
我的 *
|
|
* identitymanagement
到iam
對應是一個例外狀況,其中不同版本的 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 模型類別。例如
DescribeInstancesRequest
和DescribeInstancesResult
.
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.AmazonEC2Client
software.amazon.awssdk.services.ec2.Ec2Client
並AmazonEC2Client
將其變更為Ec2Client
。 -
將參數類型變更為,
Ec2Client
並讓 IDE 提示我們進行正確的匯入。我們的 IDE 將提示我們導入 v2 類,因為客戶端名稱不同-AmazonEC2Client
和Ec2Client
。如果兩個版本中的類名相同,則此方法不起作用。
b. 用 v2 等效物替換 v1 模型類
更改到 V2 之後Ec2Client
,如果我們使用 IDE,我們會在下面的語句中看到編譯錯誤。
result = ec2.describeInstances(request);
使用 v1 的執行個體DescribeInstancesRequest
做為 v2 Ec2Client
describeInstances
方法的參數所導致的編譯錯誤。要修復,請進行以下替換或導入語句。
取代 | 取代為 |
---|---|
|
|
c. 將 v1 構造函數更改為 v2 構建器。
我們仍然看到編譯錯誤,因為 v2 類上沒有構造函數。要修復,請進行以下更改。
變更 | 至 |
---|---|
|
|
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); } }));