

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

# 处理 S3 事件通知
<a name="examples-s3-event-notifications"></a>

为了帮助您监控存储桶中的活动，Amazon S3 可以在某些事件发生时发送通知。《Amazon S3 用户指南》提供了有关[存储桶可以发送的通知](https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventNotifications.html#notification-how-to-overview)的信息。

您可以使用适用于 Java 的 SDK 设置存储桶，将事件发送到四个可能的目的地：
+ Amazon Simple Notification Service 主题
+ Amazon Simple Queue Service 队列
+ AWS Lambda 函数
+ Amazon EventBridge

当你设置要向其发送事件的存储桶时 EventBridge，你可以配置 EventBridge 一条规则，将同一个事件分散到多个目的地。将存储桶配置为直接发送到前三个目的地之一时，只能为每个事件指定一种目标类型。

在下一节中，您将了解如何使用适用于 Java 的 SDK 配置存储桶，以便通过两种方式发送 S3 事件通知：直接发送到 Amazon SQS 队列和发送到。 EventBridge

最后一部分说明了如何使用 S3 事件通知 API 来以面向对象的方式处理通知。

## 将存储桶配置为直接发送到目的地
<a name="s3-event-conf-bucket-direct"></a>

以下示例将存储桶配置为在针对存储桶发生*对象创建*事件或*对象标记*事件时发送通知。

```
static void processS3Events(String bucketName, String queueArn) {
    // Configure the bucket to send Object Created and Object Tagging notifications to an existing SQS queue.
    s3Client.putBucketNotificationConfiguration(b -> b
            .notificationConfiguration(ncb -> ncb
                    .queueConfigurations(qcb -> qcb
                            .events(Event.S3_OBJECT_CREATED, Event.S3_OBJECT_TAGGING)
                            .queueArn(queueArn)))
                    .bucket(bucketName)
    );
}
```

上面显示的代码设置了一个队列来接收两种类型的事件。方便的是，`queueConfigurations` 方法让您可以在需要时设置多个队列目的地。此外，在 `notificationConfiguration` 方法中，您可以设置其他目的地，例如一个或多个 Amazon SNS 主题或一个或多个 Lambda 函数。以下代码段展示的示例中包含两个队列和三种类型的目的地。

```
s3Client.putBucketNotificationConfiguration(b -> b
                .notificationConfiguration(ncb -> ncb
                        .queueConfigurations(qcb -> qcb
                                .events(Event.S3_OBJECT_CREATED, Event.S3_OBJECT_TAGGING)
                                .queueArn(queueArn), 
                                qcb2 -> qcb2.<...>)
                        .topicConfigurations(tcb -> tcb.<...>)
                        .lambdaFunctionConfigurations(lfcb -> lfcb.<...>))
                        .bucket(bucketName)
        );
```

代码示例 GitHub 存储库包含直接向队列发送 S3 事件通知的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/ProcessS3EventNotification.java)。

## 配置要发送到的存储桶 EventBridge
<a name="s3-event-conf-bucket-eventbridge"></a>

以下示例配置了要向其发送通知的存储桶。 EventBridge

```
public static String setBucketNotificationToEventBridge(String bucketName) {
    // Enable bucket to emit S3 Event notifications to EventBridge.
    s3Client.putBucketNotificationConfiguration(b -> b
            .bucket(bucketName)
            .notificationConfiguration(b1 -> b1
                    .eventBridgeConfiguration(SdkBuilder::build))
    .build());
```

配置要向其发送事件的存储桶时 EventBridge，您只需指明 EventBridge目的地，而不是事件的类型，也不是 EventBridge 要发送到的最终目的地。您可以使用 Java SDK 的 EventBridge客户端配置最终目标和事件类型。

以下代码显示了如何配置 EventBridge 以将*对象创建*的事件分散到主题和队列。

```
   public static String configureEventBridge(String topicArn, String queueArn) {
        try {
            // Create an EventBridge rule to route Object Created notifications.
            PutRuleRequest putRuleRequest = PutRuleRequest.builder()
                    .name(RULE_NAME)
                    .eventPattern("""
                            {
                              "source": ["aws.s3"],
                              "detail-type": ["Object Created"],
                              "detail": {
                                "bucket": {
                                  "name": ["%s"]
                                }
                              }
                            }
                            """.formatted(bucketName))
                    .build();

            // Add the rule to the default event bus.
            PutRuleResponse putRuleResponse = eventBridgeClient.putRule(putRuleRequest)
                    .whenComplete((r, t) -> {
                        if (t != null) {
                            logger.error("Error creating event bus rule: " + t.getMessage(), t);
                            throw new RuntimeException(t.getCause().getMessage(), t);
                        }
                        logger.info("Event bus rule creation request sent successfully. ARN is: {}", r.ruleArn());
                    }).join();

            // Add the existing SNS topic and SQS queue as targets to the rule.
            eventBridgeClient.putTargets(b -> b
                    .eventBusName("default")
                    .rule(RULE_NAME)
                    .targets(List.of (
                            Target.builder()
                                    .arn(queueArn)
                                    .id("Queue")
                                    .build(),
                            Target.builder()
                                    .arn(topicArn)
                                    .id("Topic")
                                    .build())
                            )
                    ).join();
            return putRuleResponse.ruleArn();
        } catch (S3Exception e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        return null;
    }
```

要在 Java 代码 EventBridge 中使用，请在 Maven `pom.xml` 文件中添加对`eventbridge`工件的依赖关系。

```
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>eventbridge</artifactId>
</dependency>
```

代码示例 GitHub 存储库包含向主题 EventBridge 和队列发送 S3 事件通知的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/PutBucketS3EventNotificationEventBridge.java)，然后向主题和队列发送。

## 使用 S3 事件通知 API 来处理事件
<a name="s3-event-notification-read"></a>

目的地收到 S3 通知事件后，您可以使用 S3 事件通知 API 以面向对象的方式处理这些事件。您可以使用 S3 事件通知 API 来处理直接发送到目标的事件通知（如[第一个示例](#s3-event-conf-bucket-direct)所示），但不能处理通过 EventBridge发送的通知。存储桶发送的 S3 事件通知 EventBridge 包含 S3 事件通知 API 当前无法处理的[不同结构](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ev-events.html#ev-events-list)。

### 添加依赖项
<a name="s3-event-notifications-dep"></a>

S3 事件通知 API 随适用于 Java 的 SDK 2.x 的 2.25.11 版本一起发布。

要使用 S3 事件通知 API，请将所需的依赖项元素添加到您的 Maven `pom.xml` 中，如以下代码段所示。

```
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.X.X1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3-event-notifications</artifactId>
    </dependency>
</dependencies>
```

1 [最新版本](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)。

### 使用 `S3EventNotification` 类
<a name="s3-event-notifications-use"></a>

#### 使用 JSON 字符串创建 `S3EventNotification` 实例
<a name="s3-event-notifications-use-from-json"></a>

要将 JSON 字符串转换为 `S3EventNotification` 对象，请使用 `S3EventNotification` 类的静态方法，如下例所示。

```
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotificationRecord
import software.amazon.awssdk.services.sqs.model.Message; 

public class S3EventNotificationExample {
    ...
    
    void receiveMessage(Message message) {
       // Message received from SQSClient.
       String sqsEventBody = message.body();
       S3EventNotification s3EventNotification = S3EventNotification.fromJson(sqsEventBody);
    
       // Use getRecords() to access all the records in the notification.                                                                                                       
       List<S3EventNotificationRecord> records = s3EventNotification.getRecords();   
    
        S3EventNotificationRecord record = records.stream().findFirst();
        // Use getters on the record to access individual attributes.
        String awsRegion = record.getAwsRegion();
        String eventName = record.getEventName();
        String eventSource = record.getEventSource();                                                                                                   
    }
}
```

在此示例中，`fromJson` 方法将 JSON 字符串转换为 `S3EventNotification` 对象。JSON 字符串中缺少字段会导致相应 Java 对象字段设置为 `null` 值，而 JSON 中的任何多余字段则会被忽略。

事件通知记录的其他 APIs 内容可在的 API 参考中找到`[S3EventNotificationRecord](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationRecord.html)`。

#### 将 `S3EventNotification` 实例转换为 JSON 字符串
<a name="s3-event-notifications-use-to-json"></a>

使用 `toJson`（或 `toJsonPretty`）方法将 `S3EventNotification` 对象转换为 JSON 字符串，如下例所示。

```
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification

public class S3EventNotificationExample {
    ...

    void toJsonString(S3EventNotification event) {

        String json = event.toJson();
        String jsonPretty = event.toJsonPretty();

        System.out.println("JSON: " + json);
        System.out.println("Pretty JSON: " + jsonPretty);
    }
}
```

`GlacierEventData`、`ReplicationEventData`、`IntelligentTieringEventData` 和 `LifecycleEventData` 的字段如果为 `null`，则会从 JSON 中排除。其他 `null` 字段将序列化为 `null`。

下面显示了 S3 对象标记事件的 `toJsonPretty` 方法示例输出。

```
{
  "Records" : [ {
    "eventVersion" : "2.3",
    "eventSource" : "aws:s3",
    "awsRegion" : "us-east-1",
    "eventTime" : "2024-07-19T20:09:18.551Z",
    "eventName" : "ObjectTagging:Put",
    "userIdentity" : {
      "principalId" : "AWS:XXXXXXXXXXX"
    },
    "requestParameters" : {
      "sourceIPAddress" : "XXX.XX.XX.XX"
    },
    "responseElements" : {
      "x-amz-request-id" : "XXXXXXXXXXXX",
      "x-amz-id-2" : "XXXXXXXXXXXXX"
    },
    "s3" : {
      "s3SchemaVersion" : "1.0",
      "configurationId" : "XXXXXXXXXXXXX",
      "bucket" : {
        "name" : "amzn-s3-demo-bucket",
        "ownerIdentity" : {
          "principalId" : "XXXXXXXXXXX"
        },
        "arn" : "arn:aws:s3:::XXXXXXXXXX"
      },
      "object" : {
        "key" : "akey",
        "size" : null,
        "eTag" : "XXXXXXXXXX",
        "versionId" : null,
        "sequencer" : null
      }
    }
  } ]
}
```

中提供了一个[完整的示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/75c3daadf750406156fc87fa30ee499a206b4a36/javav2/example_code/s3/src/main/java/com/example/s3/ProcessS3EventNotification.java#L117) GitHub ，其中显示了如何使用 API 来处理 Amazon SQS 队列收到的通知。

## 使用 Java 库在 Lambda 中处理 S3 事件：以及 AWS SDK for Java 2.x `aws-lambda-java-events`
<a name="s3-event-notif-processing-options"></a>

您可以使用 3.x.x 版本的库，而不是使用`[aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-events)`适用于 Java 2.x 的 SDK 在 Lambda 函数中处理 Amazon S3 事件通知。 AWS 独立维护该`aws-lambda-java-events`库，并且它有自己的依赖要求。`aws-lambda-java-events` 库仅适用于 Lambda 函数中的 S3 事件，而适用于 Java 的 SDK 2.x 可处理 Lambda 函数、Amazon SNS 和 Amazon SQS 中的 S3 事件。

两种方法都以类似的面向对象的方式建模 JSON 事件通知有效负载。 APIs下表显示了使用这两种方法的显著差异。


****  

|  | 适用于 Java 的 AWS SDK | aws-lambda-java-events 图书馆 | 
| --- | --- | --- | 
| 软件包命名 |  `software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification`  | com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification | 
| RequestHandler 参数 |  编写您的 Lambda 函数的 `RequestHandler` 实现以接收 JSON 字符串： <pre>import com.amazonaws.services.lambda.runtime.Context;<br />import com.amazonaws.services.lambda.runtime.RequestHandler;<br />import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification;<br /><br />public class Handler implements RequestHandler<String, String> {<br /><br />    @Override<br />        public String handleRequest(String jsonS3Event, Context context) {<br />            S3EventNotification s3Event = S3EventNotification<br />                                             .fromJson(jsonS3Event);<br />            // Work with the s3Event object.        <br />            ...<br />    }<br />}</pre>  | 编写您的 Lambda 函数的 RequestHandler 实现以接收 S3Event 对象：<pre>import com.amazonaws.services.lambda.runtime.Context;<br />import com.amazonaws.services.lambda.runtime.RequestHandler;<br />import com.amazonaws.services.lambda.runtime.events.S3Event;<br /><br />public class Handler implements RequestHandler<S3Event, String> {<br /><br />    @Override<br />        public String handleRequest(S3Event s3event, Context context) {<br />            // Work with the s3Event object.        <br />            ...<br />    }<br />}</pre> | 
| Maven 依赖项 |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.X.X</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>s3-event-notifications</artifactId><br />    </dependency><br />    <!-- Add other SDK dependencies that you need. --><br /></dependencies></pre>  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.X.X</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <!-- The following two dependencies are for the <br />         aws-lambda-java-events library. --><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>aws-lambda-java-core</artifactId><br />        <version>1.2.3</version>     <br />    </dependency><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>aws-lambda-java-events</artifactId><br />        <version>3.15.0</version><br />    </dependency><br />    <!-- Add other SDK dependencies that you need. --><br /></dependencies></pre>  | 