

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用提出 AWS 服务 请求 AWS SDK for Java 2.x
<a name="work-witih-clients"></a>

## 使用服务客户端发出请求
<a name="using-service-client"></a>

完成[设置软件开发工具包](setup.md)中的步骤并了解如何[配置服务客户端](configuring-service-clients.md)后，就可以向诸如 Amazon S3、Amazon DynamoDB AWS Identity and Access Management、Amazon EC2 等 AWS 服务提出请求了。

### 创建服务客户端
<a name="work-with-clients-create"></a>

要向发出请求 AWS 服务，必须先使用静态工厂方法为该服务实例化服务客户端。`builder()`该 `builder()` 方法返回一个允许您自定义服务客户端的 `builder` 对象。常用的 setter 方法会返回 `builder` 对象，由此可以将方法调用组合起来，这样不仅方便而且代码更加便于阅读。在配置了所需属性后，可以调用 `build()` 方法创建客户端。

例如，以下代码段将 `Ec2Client` 对象实例化为 Amazon EC2 的服务客户端。

```
Region region = Region.US_WEST_2;
Ec2Client ec2Client = Ec2Client.builder()
        .region(region)
        .build();
```

**注意**  
开发工具包中的服务客户端是线程安全的。为了获得最佳性能，应将其作为永久对象。每个客户端自己有连接池资源，当客户端收集到垃圾时相应资源会释放。  
服务客户端对象是不可变的，因此您必须为向其发出请求的每个服务创建一个新的客户端，或者，如果您希望使用不同的配置向同一服务发出请求，也需要创建一个新的客户端。  
并非所有 AWS 服务都需要`Region`在服务客户端生成器中指定；但是，最佳做法是为在应用程序中进行的 API 调用设置区域。有关更多信息，请参阅 [AWS 区域选择](region-selection.md)。

### 默认客户端配置
<a name="using-default-client"></a>

客户端生成器包含名为 `create()` 的另一个工厂方法。此方法将使用默认配置创建服务客户端。它使用[默认提供者链](credentials-chain.md)来加载凭证和[默认 AWS 区域 提供者链](region-selection.md#automatically-determine-the-aws-region-from-the-environment)。如果不能根据运行应用程序的环境确定凭证或区域，则对 `create` 的调用失败。有关 SDK 如何确定要使用的凭证和区域的更多信息，请参阅[使用凭证](credentials.md)和[区域选择](region-selection.md)。

例如，以下代码段将 `DynamoDbClient` 对象实例化为 Amazon DynamoDB 的服务客户端。

```
DynamoDbClient dynamoDbClient = DynamoDbClient.create();
```

### 配置服务客户端
<a name="using-configure-service-clients"></a>

有关如何配置服务客户端的详细信息，请参阅[通过外部方式配置客户端](configuring-service-clients-ext.md)和[代码中的客户端配置](configuring-service-clients-code.md)。

### 关闭服务客户端
<a name="using-closing-client"></a>

作为最佳实践，您应该在应用程序的生命周期内使用服务客户端进行多个 API 服务调用。但是，如果您需要一次性使用服务客户端，或者不再需要该服务客户端，请将其关闭。

当不再需要服务客户端时，请调用 `close()` 方法，以释放资源。

```
ec2Client.close();
```

如果您需要一次性使用服务客户端，则可以通过 `try`-with-resources 语句将服务客户端实例化为资源。服务客户端将实现 `[Autoclosable](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/AutoCloseable.html)` 接口，因此 JDK 会在语句末尾自动调用 `close()` 方法。

以下示例演示如何使用服务客户端进行一次性调用。调用`StsClient` AWS Security Token Service 的，将在返回账户 ID 后关闭。

```
import software.amazon.awssdk.services.sts.StsClient;

String getAccountID() {
    try (StsClient stsClient = StsClient.create()) {
       return stsClient.getCallerIdentity().account();
    }
}
```

## 提出请求
<a name="using-making-requests"></a>

使用服务客户端向对应的发出请求 AWS 服务。

例如，以下代码段演示如何创建 `RunInstancesRequest` 对象以创建新的 Amazon EC2 实例：

```
// Create the request by using the fluid setter methods of the request builder.
RunInstancesRequest runInstancesRequest = RunInstancesRequest.builder()
        .imageId(amiId)
        .instanceType(InstanceType.T1_MICRO)
        .maxCount(1)
        .minCount(1)
        .build();

// Use the configured request with the service client.
RunInstancesResponse response = ec2Client.runInstances(runInstancesRequest);
```

SDK 并不创建请求并在实例中传递，而是提供可用于创建请求的 fluent API。借助 fluent API，您可以使用 Java lambda 表达式创建请求“内联”。

以下示例使用通过[生成器创建请求的 `runInstances` 方法](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#runInstances(java.util.function.Consumer))版本重写了前面的示例。

```
// Create the request by using a lambda expression.
RunInstancesResponse response = ec2.runInstances(r -> r
                .imageId(amiId)
                .instanceType(InstanceType.T1_MICRO)
                .maxCount(1)
                .minCount(1));
```

### 使用请求来覆盖客户端配置
<a name="using-override-client-config-request"></a>

尽管服务客户端是不可变的，但您可以在请求级别覆盖它的许多设置。在构建请求时，您可以提供一个[AwsRequestOverrideConfiguration](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/AwsRequestOverrideConfiguration.html)实例来提供被覆盖的设置。可以用来覆盖客户端设置的一些方法包括：
+ `apiCallAttemptTimeout`
+ `apiCallTimeout`
+ `credentialProvider`
+ `compressionConfiguration`
+ `putHeader`

查看使用请求覆盖客户端设置的示例时，假设您有以下使用默认设置的 S3 客户端。

```
S3Client s3Client = S3Client.create();
```

您想下载一个大文件，并希望确保在下载完成之前请求不会超时。为此，请仅增大单个 `GetObject` 请求的超时值，如以下代码所示。

------
#### [ Standard API ]

```
AwsRequestOverrideConfiguration overrideConfiguration = AwsRequestOverrideConfiguration.builder()
    .apiCallTimeout(Duration.ofSeconds(100L))
    .apiCallAttemptTimeout(Duration.ofSeconds(25L))
    .build();

GetObjectRequest request = GetObjectRequest.builder()
    .bucket("amzn-s3-demo-bucket")
    .key("demo-key")
    .overrideConfiguration(overrideConfiguration)
    .build();

s3Client.getObject(request, myPath);
```

------
#### [ Fluent API ]

```
s3Client.getObject(b -> b
        .bucket("amzn-s3-demo-bucket")
        .key("demo-key")
        .overrideConfiguration(c -> c
            .apiCallTimeout(Duration.ofSeconds(100L))
            .apiCallAttemptTimeout(Duration.ofSeconds(25L))),
    myPath);
```

------

## 处理回复
<a name="using-handling-responses"></a>

对于大多数服务操作，SDK 会返回响应对象。您的代码可以根据需求处理响应对象中的信息。

例如，以下代码段输出上一个请求中随 [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/RunInstancesResponse.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/RunInstancesResponse.html) 对象返回的第一个实例 ID。

```
RunInstancesResponse runInstancesResponse = ec2Client.runInstances(runInstancesRequest);
System.out.println(runInstancesResponse.instances().get(0).instanceId());
```

但是，并非所有操作都会返回包含服务特定数据的响应对象。在这些情况下，您可以查询 HTTP 响应状态以了解操作是否成功。

例如，以下代码段中的代码会检查 HTTP 响应，以查看 Amazon Simple Email Service 的 [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sesv2/SesV2Client.html#deleteContactList(software.amazon.awssdk.services.sesv2.model.DeleteContactListRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sesv2/SesV2Client.html#deleteContactList(software.amazon.awssdk.services.sesv2.model.DeleteContactListRequest)) 操作是否成功。

```
SesV2Client sesv2Client = SesV2Client.create();

DeleteContactListRequest request = DeleteContactListRequest.builder()
    .contactListName("ExampleContactListName")
    .build();

DeleteContactListResponse response = sesv2Client.deleteContactList(request);
if (response.sdkHttpResponse().isSuccessful()) {
    System.out.println("Contact list deleted successfully");
} else {
    System.out.println("Failed to delete contact list. Status code: " + response.sdkHttpResponse().statusCode());
}
```