本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
带示例的迁移 step-by-step 说明
本节提供了将当前使用适用SDK于 Java v1.x 的应用程序迁移到适用于 Java 2.x 的应用程序SDK的 step-by-step 指南。第一部分概述了各个步骤,然后是迁移的详细示例。
此处介绍的步骤描述了正常用例的迁移,即应用程序 Amazon Web Services 服务 使用模型驱动的服务客户端进行调用。如果您需要迁移使用更高级别的代码,APIs例如 S3 传输管理器或CloudFront预签名,请参阅Amazon SDK for Java 1.x 和 2.x 有什么区别目录下的部分。
此处描述的方法是一个建议。您可以使用其他技术并利用自己的IDE代码编辑功能来达到相同的结果。
步骤概述
1. 首先添加SDK适用于 Java 2.x 的 BOM
通过将适用于 Java 2.x 的 MavenBOM(材料清单)元素添加到您的POM文件中,可以确保所需的所有版本 v2 依赖项都来自同一个版本。SDKPOM你可以同时包含 v1 和 v2 依赖关系。这允许您以增量方式迁移代码,而不必一次全部更改。
<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>
2.27.21
</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
您可以在 Maven 中央存储库中找到最新版本
2. 在文件中搜索 v1 类的导入语句
通过扫描应用程序中的文件,找到 v1 导入中IDs使用的 SERVICE _,你会发现IDs使用了唯一的 SERVICE _。SERVICE_ID 是一个简短、唯一的 Amazon Web Services 服务名称。例如,Amazon cognitoidentity
Cognito Identity 的 SERVICE _ID。
3. 从 v1 的导入语句中确定 v2 Maven 的依赖关系
找到所有唯一的 v1 SERVICE _ 之后IDs,您可以通过参考来确定 v2 依赖项的相应的 Maven 工件。Package 名称到 Maven 映射关系 artifactId
4. 将 v2 依赖项元素添加到文件中 POM
使用步骤 3 中确定的依赖元素更新 Maven POM 文件。
5. 在 Java 文件中,逐渐将 v1 类更改为 v2 类
当你用 v2 类替换 v1 类时,请进行必要的更改以支持 v2,API例如使用构建器而不是构造函数,以及使用流畅的 getter 和 setter。
6. 从文件中移除 v1 Maven 依赖关系,POM从文件中移除 v1 的依赖关系
将代码迁移到使用 v2 类后,请从文件中移除所有剩余的 v1 导入,并从构建文件中移除所有依赖项。
7. 重构代码以使用 v API 2 增强功能
在代码成功编译并通过测试后,您可以利用 v2 增强功能,例如使用不同的HTTP客户端或分页器来简化代码。此为可选步骤。
迁移示例
在此示例中,我们迁移了一个使用 for Java v1 并访问多个应用程序的应用程序。SDK Amazon Web Services 服务我们在步骤 5 中详细研究了以下 v1 方法。这是包含八个方法的类中的一个方法,应用程序中有 32 个类。
下面仅列出了 Java 文件中的 v1 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
将BOM适用于 Java 2.x SDK 的 Maven 添加到本POM节中的任何其他依赖项旁边。dependencyManagement
如果您的POM文件有 v1 BOM 的SDK,请暂时将其保留。它将在以后的步骤中删除。
<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.27.21
</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 _ IDs。
rg --no-filename 'import\s+com\.amazonaws\.services' | cut -d '.' -f 4 | sort | uniq
对于此应用程序,将以下 SERVICE _ IDs 记录到控制台。
autoscaling cloudformation ec2 identitymanagement
这表明import
语句中使用的以下每个软件包名称至少出现一次。我们的目的有四,各个类名无关紧要。我们只需要找到IDs使用的 SERVICE _。
com.amazonaws.services.autoscaling.* com.amazonaws.services.cloudformation.* com.amazonaws.services.ec2.* com.amazonaws.services.identitymanagement.*
3. 从 v1 的导入语句中确定 v2 Maven 的依赖关系
我们从步骤 2 中分离出来的 v1 的 SERVICE _IDs(例如autoscaling
和cloudformation
)在大多数情况下可以映射到相同的 v2 SERVICE _ID。由于 v2 Maven 在大多数情况下都与 SERVICE _ID artifactId 匹配,因此您拥有向文件添加依赖块所需的信息。POM
下表显示了我们如何确定 v2 依赖关系。
v1 SERVICE _ID 映射到... 包名 |
v2 SERVICE _ID 映射到... 包名 |
v2 Maven 依赖关系 |
---|---|---|
ec2
|
ec2
|
|
自动缩放
|
自动缩放
|
|
cloudformation
|
cloudformation
|
|
身份管理*
|
我*
|
|
* to identitymanagement
iam
映射是一个例外,其中 SERVICE _ID 因版本而异。如果 Maven 或 Gradle 无法解析 v2 依赖关系,请参阅了解例外情况。Package 名称到 Maven 映射关系 artifactId
4. 将 v2 依赖项元素添加到文件中 POM
在步骤 3 中,我们确定了需要添加到POM文件中的四个依赖块。我们不需要添加版本,因为我们已经BOM在步骤 1 中指定了。添加导入后,我们的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. 将 v1 模型类替换为 v2 等效项
在 v2 更改之后Ec2Client
,如果我们使用IDE,则会在以下语句中看到编译错误。
result = ec2.describeInstances(request);
编译错误是由于使用 v1 的实例DescribeInstancesRequest
作为 v2 Ec2Client
describeInstances
方法的参数而导致的。要修复此问题,请使用以下替换语句或导入语句。
replace | 替换为 |
---|---|
|
|
c. 将 v1 构造函数更改为 v2 构建器。
我们仍然会看到编译错误,因为 v2 类上没有构造函数。要修复此问题,请进行以下更改。
更改 | 到 |
---|---|
|
|
d. 将 v1 *Result
响应对象替换为 v *Response
2 等效对象
v1 和 v2 之间的一致区别是,v2 中的所有响应对象都以而不是结*Response尾。*Result
将 v1 DescribeInstancesResult
导入替换为 v2 导入,。DescribeInstancesResponse
d. 做出API改变
以下语句需要进行一些修改。
request.setNextToken(result.getNextToken());
在 v2 中,setter 方法不使用set
或 with。prefix
前缀为前缀的 Getter 方法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. 从文件中移除 v1 Maven 依赖关系,POM从文件中移除 v1 的依赖关系
迁移文件中的所有 v1 代码后,我们有以下 v2 SDK import 语句。
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 依赖项。BOM从该dependencyManagement
部分中删除 v1(如果使用)以及所有 v1 依赖块。
7. 重构代码以使用 v API 2 增强功能
对于我们一直在迁移的片段,我们可以选择使用 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); } }));
Package 名称到 Maven 映射关系 artifactId
当你将 Maven 或 Gradle 项目从 Java 版的 v1 迁移到 v2 时,你需要弄清楚要将哪些依赖项添加到你的构建文件中。SDK带示例的迁移 step-by-step 说明(步骤 3)中描述的方法使用导入语句中的软件包名称作为起点来确定要添加到构建文件中的依赖关系。artifactIds
您可以使用本主题中的信息将 v1 软件包名称映射到 v artifactIds 2。
软件包名称和 Maven 中使用的常见命名约定 artifactIds
下表显示了用于给定 SERVICE _ID 的常SDKs用命名约定。SERVICE_ID 是的唯一标识符。 Amazon Web Services 服务例如,亚马逊 S3 服务的 SERVICE _ID 是亚马逊 Cognito Identity 的 _ID,也是s3
亚马逊 cognitoidentity
Cognito Identity 的 SERVICE _ID。
v1 软件包名称(导入语句) | v1 artifactId | v2 artifactId | v2 软件包名称(导入语句) |
---|---|---|---|
com.amazonaws.servic SERVICE_ID | aws-java-sdk-SERVICE _ID | SERVICE_ID | 软件.amazon.awssdk.services。 SERVICE_ID |
亚马逊 Cognito 身份示例 (SERVICE_ID:) cognitoidentity |
|||
com.amazonaws.servic 认知身份 | aws-java-sdk-认知身份 | 认知身份 | 软件.amazon.awssdk.services。 认知身份 |
SERVICE_ID 差异
在 v1 中
在某些情况下,软件包名称和相同服务的包名称之间 artifactId 的 SERVICE _ID 会有所不同。例如,下表的 “ CloudWatch 指标” 行显示软件包名称中的 SERVICE _ID 但却cloudwatchmetrics
artifactId是 SERVICE _ID。metrics
在 v2 中
软件包名称中使用的 SERVICE _ID 和artifactIds没有区别。
在 v1 和 v2 之间
对于大多数服务,v2 中的 SERVICE _ID 与软件包名称和 v1 的 SERVICE _ID 相同。artifactIds这方面的一个例子是 cognitoedentity
SERVICE _ID,如上表所示。但是,两者之间有一些 SERVICE _ IDs 有所不同,如下表所示。SDKs
v1 中任一列中的粗SERVICE体 _ID 表示它与 v2 中使用的 SERVICE _ID 不同。
服务名称 | v1 软件包名称 | v1 artifactId | v2 artifactId | v2 软件包名称 |
---|---|---|---|---|
所有软件包名称都以开头 |
所有 artifactIds 内容都包含在标签中,如第一行所示。 |
所有 artifactIds 内容都包含在标签中,如第一行所示。 |
所有软件包名称都以开头 |
|
API网关 | com.amazonaws.services.apigatewa | < artifactId > aws-java-sdk-api-gatew ay </ > artifactId | < artifactId >ap artifactId igateway</ > | 软件.amazon.awssdk.services.apigateway |
应用程序注册表 | 鉴定登记 | 鉴定登记 | servicecatalogappregistry | servicecatalogappregistry |
Application Discovery | 应用程序发现 | discovery | 应用程序发现 | 应用程序发现 |
增强型 AI 运行时 | 增强空中运行时间 | 增强空中运行时间 | sagemakera2iRuntime | sagemakera2iRuntime |
Certificate Manager | 证书管理器 | acm | acm | acm |
CloudControl API | 云控制 api | 云控制 api | 云控制 | 云控制 |
CloudSearch | cloudsearch | cloudsearch | cloudsearch | cloudsearch |
CloudSearch 域名 | 云搜索域名 | 云端搜索 | 云搜索域名 | 云搜索域名 |
CloudWatch 大事记 | 云监视活动 | 事件 | cloudwatcheVent | cloudwatcheVent |
CloudWatch 显然 | cloudwatchevice | cloudwatchevice | evidently | evidently |
CloudWatch 日志 | 日志 | 日志 | 云监视日志 | 云监视日志 |
CloudWatch 指标 | 指标 | 云监视指标 | cloudwatch | cloudwatch |
CloudWatch 朗姆酒 | cloudwatc | cloudwatc | rum | rum |
Cognito 身份提供商 | cognitoidp | cognitoidp | 认知身份提供者 | 认知身份提供者 |
Connect 广告系列 | 连接活动 | 连接活动 | connect广告系列 | connect广告系列 |
Connect Wis | 连接智慧 | 连接智慧 | wisdom | wisdom |
Database Migration Service | 数据库迁移服务 | dms | 数据库迁移 | 数据库迁移 |
DataZone | datazone | 数据区外部 | datazone | datazone |
DynamoDB | dynamodbv2 | dynamodb | dynamodb | dynamodb |
弹性文件系统 | 弹性文件系统 | efs | efs | efs |
弹性地图缩小 | elasticmapreduce | emr | emr | emr |
Glue DataBrew | gluedatabrew | gluedatabrew | databrew | databrew |
IAM角色随处可见 | 我在任何地方都扮演角色 | 我在任何地方都扮演角色 | rolesanywhere | rolesanywhere |
身份管理 | 身份管理 | IAM | IAM | IAM |
物联网数据 | iotdata | iot | 物联网数据平面 | 物联网数据平面 |
Kinesis Analytics | kinesisanalytics | kinesis | kinesisanalytics | kinesisanalytics |
Kinesis Firehose | kinesisis fire | kinesis | firehose | firehose |
Kinesis 视频信令频道 | kinesis 视频信号频道 | kinesis 视频信号频道 | kinesis 视频信号 | kinesis 视频信号 |
Lex | lexrunt | lex | lexrunt | lexrunt |
警惕视力 | 留意视力 | 留意视力 | lookoutvision | lookoutvision |
大型机现代化 | 大型机现代化 | 大型机现代化 | m2 | m2 |
市场计量 | 市场计量 | 市场计量服务 | 市场计量 | 市场计量 |
托管 Grafana | managedgrafana | managedgrafana | grafana | grafana |
Mechanical Turk | mturk | 机械火鸡请求者 | mturk | mturk |
Migration Hub Strategy Recommendations | 迁移中心策略建议 | 迁移中心策略建议 | 迁移中心策略 | 迁移中心策略 |
Nimble Studio | 灵活的工作室 | 灵活的工作室 | nimble | nimble |
专用 5G | 私密的 5g | 私密的 5g | 私有网络 | 私有网络 |
Prometheus | 普罗米修斯 | 普罗米修斯 | 放大器 | 放大器 |
回收站 | 回收箱 | 回收箱 | rbin | rbin |
Redshift 数据 API | redshiftdataap | redshiftdataap | 红移数据 | 红移数据 |
Route 53 | route53 个域名 | route53 | route53 个域名 | route53 个域名 |
Sage Maker 边缘管理 | sagemakeredgeManager | sagemakeredgeManager | sagemakeredge | sagemakeredge |
安全令牌 | 安全令牌 | sts | sts | sts |
服务器迁移 | 服务器迁移 | 服务器迁移 | sms | sms |
简单电子邮件 | 简单电子邮件 | ses | ses | ses |
简单电子邮件 V2 | simpleemailv2 | sesv2 | sesv2 | sesv2 |
简单的系统管理 | 简化系统管理 | ssm | ssm | ssm |
简单的工作流程 | 简单的工作流程 | 简单的工作流程 | swf | swf |
Step Functions | 阶梯函数 | 阶梯函数 | sfn | sfn |