news 2026/9/25 5:21:37

Amazon SNS 实战指南(AWS SDK for Java 2.x):从 Hello SNS 到 FIFO 主题与 SNS 到 SQS 扇出

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Amazon SNS 实战指南(AWS SDK for Java 2.x):从 Hello SNS 到 FIFO 主题与 SNS 到 SQS 扇出
  • 示例工程
  • 教程
  • 后端

【免费下载链接】aws-doc-sdk-examples

Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below.

项目地址:https://gitcode.com/gh_mirrors/aw/aws-doc-sdk-examples
点击查看免费下载

本文基于 aws-doc-sdk-examples 仓库中 javav2/example_code/sns/README.md 整理与扩写,完整覆盖 Amazon SNS 在 Java 2.x SDK 下的入门示例、全部单接口操作、多接口组合场景与本地运行/测试方式,并结合 源码实现 深入讲解 FIFO 主题、消息过滤策略与 SQS 队列订阅等关键细节。读完本文,你可以独立完成从创建主题、订阅端点、发布消息到清理资源的完整 SNS 工作流,并理解每个示例背后的 SDK 调用方式。

一、示例集合定位与工程结构

Amazon SNS(Simple Notification Service,简单通知服务)是允许应用、终端用户和设备从云端即时收发通知的 Web 服务。本目录中的示例展示了如何使用 AWS SDK for Java 2.x 操作 SNS 的各类 API,示例分为三类:

  • 入门示例(Get started):HelloSNS.java,通过ListTopics列出账号下的所有主题,作为第一个跑通的 SNS 程序;
  • 单接口示例(Single actions):15 个独立示例,每个对应一次服务 API 调用;
  • 多接口场景(Scenarios):跨多个 API 完成完整任务的组合示例,例如创建并投递 FIFO 主题消息、向队列发布消息等。

从目录结构看,所有 Java 源文件位于包com.example.sns下(src/main/java/com/example/sns),测试位于 src/test/java/com/example/sns,构建配置由 pom.xml、Makefile 和 run_example.sh 共同支撑。

计费与权限提醒(来自原文档的 Important 章节):

  • 运行这些代码可能对你的 AWS 账户产生费用,运行测试同样可能产生费用;
  • 建议遵循最小权限原则,只授予代码完成任务所需的最小 IAM 权限;
  • 这些代码并非在每一个 AWS Region 都经过测试,使用前请确认你的 Region 支持相应服务。

二、前置条件与构建环境

2.1 运行前提

按照 javav2 根目录 README 的要求,运行本目录示例需要:

  • Apache Maven(>3.0);
  • 所有 Java 2.x 示例都假设 SDK 能通过默认凭据提供器链获取 AWS 凭据(例如~/.aws/config中的 SSO 配置或~/.aws/credentials中的临时凭据);
  • 默认 Region 配置:若未显式设置,默认 Region 为us-east-1。本目录所有示例在构造SnsClient时也都显式指定了Region.US_EAST_1,例如 HelloSNS.java 第 14–16 行。

2.2 关键依赖(来自 pom.xml)

依赖版本/说明
software.amazon.awssdk:bom2.35.10,统一管理 SDK 各模块版本
software.amazon.awssdk:snsSNS 服务客户端
software.amazon.awssdk:sqsSQS 服务客户端(FIFO 场景与队列扇出场景使用)
software.amazon.sns:sns-extended-client2.1.0,SNS 扩展客户端
software.amazon.awssdk:iam-policy-builder用于在代码中构建 IAM 策略 JSON(见 4.2 节)
software.amazon.awssdk:sts用于获取当前账号 ID(getCallerIdentity)
com.google.code.gson:gson2.10.1,交互场景中的 JSON 解析
org.junit.jupiter:junit-jupiter5.11.4,JUnit 5 测试
log4j-core/slf4j-api日志支持

工程目标 Java 版本为21(pom.xml中java.version=21,maven-compiler-plugin 3.11.0)。

三、入门示例:Hello Amazon SNS

HelloSNS.java 是“第一个 SNS 程序”,其核心逻辑是用**分页器(paginator)**遍历列出账号中的所有 SNS 主题并打印主题 ARN:

public static void listSNSTopics(SnsClient snsClient) { try { ListTopicsIterable listTopics = snsClient.listTopicsPaginator(); listTopics.stream() .flatMap(r -> r.topics().stream()) .forEach(content -> System.out.println(" Topic ARN: " + content.topicArn())); } catch (SnsException e) { System.err.println(e.awsErrorDetails().errorMessage()); System.exit(1); } }

从源码结构看,它使用的是listTopicsPaginator()(返回ListTopicsIterable)而非单次listTopics()——因为 SNS 的ListTopics是分页 API,主题数量多时单次调用可能只返回一部分结果,分页器会自动处理nextToken。错误处理遵循本目录所有示例的统一模式:捕获SnsException,打印awsErrorDetails().errorMessage()后以退出码 1 结束。

四、单接口示例(Single Actions)逐类解析

原文档列出的 15 个单接口示例如下表,每一行对应一次独立的 SNS API 调用,命令行参数均定义在各文件的usage文本块中:

示例类文件主要参数
CheckIfPhoneNumberIsOptedOutCheckOptOut.java手机号码
ConfirmSubscriptionConfirmSubscription.javasubscriptionToken、topicArn
CreateTopicCreateTopic.javatopicName
DeleteTopicDeleteTopic.javatopicArn
GetSMSAttributesGetSMSAtrributes.java手机号码
GetTopicAttributesGetTopicAttributes.javatopicArn
ListPhoneNumbersOptedOutListOptOut.java无
ListSubscriptionsListSubscriptions.java无
ListTopicsListTopics.java无
PublishPublishTopic.javamessage、topicArn
SetSMSAttributesSetSMSAttributes.java手机号码及 SMS 属性
SetSubscriptionAttributesUseMessageFilterPolicy.javasubscriptionArn
SetTopicAttributesSetTopicAttributes.javaattribute、topicArn、value
TagResourceAddTags.java资源 ARN 与标签
UnsubscribeUnsubscribe.javasubscriptionArn

4.1 主题生命周期:创建、查询与属性管理

创建主题。CreateTopic.java 第 24–48 行 接收一个topicName参数(如mytopic),构造CreateTopicRequest后调用snsClient.createTopic(request),并将返回的主题 ARN 打印出来:

CreateTopicRequest request = CreateTopicRequest.builder() .name(topicName) .build(); result = snsClient.createTopic(request); return result.topicArn();

这里体现的是 SDK 2.x 的Builder 模式:请求对象通过CreateTopicRequest.builder().name(...).build()构造,响应对象的字段通过topicArn()等 getter 方法读取。

获取与设置主题属性。GetTopicAttributes.java 传入topicArn后调用getTopicAttributes并打印result.attributes()映射;SetTopicAttributes.java 第 26–34 行 则接收三个参数,其中属性名(attribute)的有效取值为Policy、DisplayName、DeliveryPolicy,对应主题策略、显示名称与投递策略三种主题级属性。

4.2 订阅管理:ConfirmSubscription 与过滤策略

确认订阅。对于需要确认的订阅类型(如 email),Subscribe操作会向端点发送一个短生命周期 token;ConfirmSubscription.java 第 49–64 行 用token与topicArn调用confirmSubscription,成功后返回正式的订阅 ARN。

消息过滤策略(Filter Policy)是本目录最有深度的单接口示例。UseMessageFilterPolicy.java 通过SetSubscriptionAttributes将一条 JSON 过滤策略挂到指定订阅上,演示了五种过滤条件:

SNSMessageFilterPolicy fp = new SNSMessageFilterPolicy(); // 单值字符串匹配 fp.addAttribute("store", "example_corp"); fp.addAttribute("event", "order_placed"); // 前缀匹配 fp.addAttributePrefix("customer_interests", "bas"); // anything-but 匹配 fp.addAttributeAnythingBut("customer_interests", "baseball"); // 值列表匹配 ArrayList<String> attributeValues = new ArrayList<>(); attributeValues.add("rugby"); attributeValues.add("soccer"); attributeValues.add("hockey"); fp.addAttribute("customer_interests", attributeValues); // 数值等值与数值区间 fp.addAttribute("price_usd", "=", 0); fp.addAttributeRange("price_usd", ">", 0, "<=", 100); // 应用到订阅 fp.apply(snsClient, subscriptionArn);

辅助类 SNSMessageFilterPolicy.java 展示了过滤策略 JSON 是如何生成的:内部用Map<String, Attribute>收集条件,Attribute.toString()按类型(String/Prefix/AnythingBut/List/Numeric)序列化为{"prefix":"..."}、{"anything-but":"..."}、["0","<=",100]等片段,formatFilterPolicy()将其拼接为完整的策略 JSON,最后apply()方法构造SetSubscriptionAttributesRequest,属性名固定为FilterPolicy,属性值为拼好的 JSON 字符串(第 71–80 行)。也就是说,这个类把“手写 FilterPolicy JSON”这件容易出错的活抽象成了类型安全的 API。

4.3 发布消息:主题发布与 SMS 文本消息

主题发布。PublishTopic.java 第 48–63 行 接收message与topicArn两个参数:

PublishRequest request = PublishRequest.builder() .message(message) .topicArn(topicArn) .build(); PublishResponse result = snsClient.publish(request); System.out.println(result.messageId() + " Message sent. Status is " + result.sdkHttpResponse().statusCode());

返回值中的messageId()是消息的全局唯一标识,sdkHttpResponse().statusCode()是底层 HTTP 状态码,两者一起可用于验证发布成功。

直接发布 SMS 文本消息。PublishTextSMS.java 的参数为message与phoneNumber(格式如+1XXX5550100)。与主题发布不同,PublishRequest这里用的是.phoneNumber(...)而非.topicArn(...)——同一 API 的两种发布目标。

配套地,SubscribeTextSMS.java 演示了把手机号订阅到主题的完整写法:protocol("sms")+endpoint(phoneNumber)+returnSubscriptionArn(true),注意returnSubscriptionArn(true)只在sms、sns、application协议下有效,源码用result.subscriptionArn()直接打印订阅 ARN。SMS 属性读写则分别由 GetSMSAtrributes.java 与 SetSMSAttributes.java 覆盖(例如国际启用状态SNS_OPT_OUT之外的开发者 SMS 属性),CheckOptOut.java 与 ListOptOut.java 分别检查单个号码是否退订、列出账号内所有退订号码。

4.4 推送通知:创建平台端点

RegistrationExample.java 演示为移动端推送创建平台端点(platform endpoint),参数为:

  • token:设备令牌或注册 ID——由设备平台(iOS 的 APNs、Android 的 FCM)在应用注册推送时提供的唯一标识;
  • platformApplicationArn:平台应用的 ARN,需要先通过 AWS 管理控制台创建平台应用获得。

核心调用为 第 60–74 行:

CreatePlatformEndpointRequest endpointRequest = CreatePlatformEndpointRequest.builder() .token(token) .platformApplicationArn(platformApplicationArn) .build(); CreatePlatformEndpointResponse response = snsClient.createPlatformEndpoint(endpointRequest); System.out.println("The ARN of the endpoint is " + response.endpointArn());

源码注释明确指出:若未先在控制台创建平台应用,此示例无法工作;后续向该endpointArn发布消息即可触达设备。

五、多接口组合场景(Scenarios)

5.1 创建并发布到 FIFO 主题:PriceUpdateExample

PriceUpdateExample.java 是最完整的场景示例,模拟“价格更新”业务:创建两个 FIFO 队列(wholesale、retail)与一个标准队列(analytics),创建一个 FIFO 主题,让三个队列订阅该主题,发布一条带消息属性的价格更新,最后清理全部资源。

命令行用法(来自源码中的usage文本):

Usage: <topicName> <wholesaleQueueFifoName> <retailQueueFifoName> <analyticsQueueName>

FIFO 主题的关键在创建时的一组属性(第 90–114 行):

Map<String, String> topicAttributes = Map.of( "FifoTopic", "true", "ContentBasedDeduplication", "false", "FifoThroughputScope", "MessageGroup"); CreateTopicRequest topicRequest = CreateTopicRequest.builder() .name(topicName) // FIFO 主题名必须以 .fifo 结尾 .attributes(topicAttributes) .build();
  • FifoTopic=true声明这是一个 FIFO 主题(主题名也需以.fifo结尾,测试用例中即MyTestTopic.fifo);
  • ContentBasedDeduplication=false表示不按消息内容自动去重,而是显式提供去重 ID;
  • FifoThroughputScope=MessageGroup将吞吐量作用域限定在消息组级别。

发布到 FIFO 主题时必须携带两个标识(第 133–167 行):

MessageAttributeValue msgAttValue = MessageAttributeValue.builder() .dataType("String") .stringValue("wholesale") .build(); attributes.put("business", msgAttValue); PublishRequest pubRequest = PublishRequest.builder() .topicArn(topicArn) .subject("Price Update") .message(payload) // {"product": 214, "price": 79.99} .messageGroupId(groupId) // FIFO 必填:消息组 ID,同组内保序 .messageDeduplicationId(UUID.randomUUID().toString()) // FIFO 必填:去重 ID .messageAttributes(attributes) .build();

messageGroupId决定消息的保序分组,messageDeduplicationId用于 5 分钟去重窗口内丢弃重复消息;messageAttributes中的business=wholesale属性可供订阅端配合过滤策略使用。

队列侧的访问策略是易被忽略的一步。FIFO 主题的消息只会被 SQS 队列消费(源码注释明确说明“只有 SQS 队列可以接收来自 SNS FIFO 主题的通知”)。addAccessPolicyToQueuesFINAL(第 192–219 行)用iam-policy-builder为每个队列生成两段策略:

  1. 允许本账号内的主体执行SQS:*(便于测试轮询与删除);
  2. 允许任意主体对队列执行SQS:SendMessage,但附加条件aws:SourceArn等于主题 ARN(IamConditionOperator.ARN_LIKE)——即只有这个新主题才有权向队列投递消息,这是 SNS 到 SQS 集成安全模型的核心。

生成的策略 JSON 通过setQueueAttributes写入队列的POLICY属性。

自动化测试印证了完整链路。PriceUpdateExampleTest.java 是一个 JUnit 5 集成测试(@Tag("IntegrationTest")),它依次调用createQueues→createFIFOTopic("MyTestTopic.fifo")→subscribeQueues→ 附加访问策略 →publishPriceUpdate,随后对每个队列执行receiveMessage并断言消息非空,最后依次deleteSubscriptions、deleteQueues、deleteTopic完成清理。这验证了“发布一条消息、三个订阅队列都能收到”的扇出(fan-out)行为。

5.2 向主题发布 SMS 消息(群发)

原文档描述的该场景包含三步:创建一个 SNS 主题;把若干手机号订阅到该主题;向主题发布一条消息,所有订阅手机号同时收到。对应实现即 4.3 节的 CreateTopic.java、SubscribeTextSMS.java 与 PublishTopic.java 的组合——先为每个号码调用一次subscribe(protocol="sms"),再向主题发布一次即可实现“一次发布、批量送达”。

5.3 向队列发布消息:交互式 SNSWorkflow

README 引用的第五个场景是 javav2/usecases/topics_and_queues 下的 SNSWorkflow.java,这是一个控制台交互程序,覆盖完整生命周期(见其类注释):

  1. 给用户三个配置选项(主题/队列类型等);
  2. 创建 SNS 主题;
  3. 创建 SQS 队列;
  4. 获取队列 ARN 属性;
  5. 为队列附加 IAM 策略;
  6. 将队列订阅到主题;
  7. 向主题发布消息;
  8. 显示队列中的消息;
  9. 删除已接收的消息;
  10. 取消订阅;
  11. 删除 SNS 主题。

从源码看,它与 PriceUpdateExample 的差异在于:显式通过EnvironmentVariableCredentialsProvider.create()从环境变量读取凭据(第 86–94 行),支持在交互中选择 FIFO 或非 FIFO 主题、是否设置去重与过滤,并用Gson处理消息内容 JSON。运行入口要求传入一个参数(账户 ID)。

六、构建、运行与测试

6.1 构建

在 javav2/example_code/sns 目录下,两种等价方式:

# 方式一:直接 Maven mvn package # 方式二:Makefile 包装(make 会执行 mvn package) make

Makefile 只有一条有效目标:all: target/sdk-sns-examples-1.0.jar,其依赖规则即mvn package;另提供clean目标执行mvn clean。

6.2 运行单个示例

run_example.sh 是推荐的运行入口,用法为:

# 第一个参数是类名,其余参数加引号原样传给该类 ./run_example.sh PublishTopic "Hello SNS" "arn:aws:sns:us-east-1:123456789012:mytopic"

脚本内部把类名拼成com.example.sns.<className>,然后执行:

mvn exec:java -Dexec.mainClass="com.example.sns.$className" -Dexec.args="$@"

也就是说,实际运行由Maven exec 插件完成,不需要手动维护 classpath。如果参数不符合示例的usage定义,程序会打印用法说明并以退出码 1 结束——所有单接口示例都遵循这一参数校验模式。

6.3 测试

本目录提供两个测试类:

  • PriceUpdateExampleTest.java:如 5.1 节所述,端到端验证 FIFO 主题 + SQS 扇出链路;
  • AWSSNSTest.java:针对单接口示例的 JUnit 测试。

按 javav2 根 README 的通用说明,测试基于 JUnit 5,在命令行执行mvn test(或在 IntelliJ 等 IDE 中直接运行)。原文档特别警告:这些测试会操作真实的 AWS 资源并可能产生费用,建议在专门的测试账号/测试资源中运行。

七、小结:这套示例给出的 SDK 2.x 编程模式

综合全部源码,可以归纳出本目录沉淀的四条可复用经验:

  1. 客户端构建:SnsClient.builder().region(Region.US_EAST_1).build(),用完后close()(PriceUpdateExample 则用SnsClient.create()静态工厂并复用静态客户端,适用于长流程);
  2. 请求构造:一律使用请求对象的 Builder,字段通过类型化 getter(如topicArn()、messageId())读取;
  3. 统一错误处理:捕获SnsException,输出awsErrorDetails().errorMessage();
  4. 安全与清理:SNS 到 SQS 集成必须为队列附加带aws:SourceArn条件的SQS:SendMessage策略;场景示例都在末尾主动执行取消订阅、删队列、删主题,避免残留资源持续计费。

配合 javav2 根 README 中的凭据与构建说明,以及本目录 15 个单接口示例与 5 个场景示例,这套代码可以作为在 Java 项目中集成 Amazon SNS 的完整参考起点。

  • 示例工程
  • 教程
  • 后端

【免费下载链接】aws-doc-sdk-examples

Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below.

项目地址:https://gitcode.com/gh_mirrors/aw/aws-doc-sdk-examples
点击查看免费下载
上一篇:Browserslist 项目推荐
下一篇:Stylelint配置与自定义指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 5:14:40

LS-DYNA多节点计算的许可证配置与故障排查实战

1. 先搞清楚问题&#xff1a;为什么LS-DYNA多节点计算老是卡在许可证上这些年我经手过不少LS-DYNA的部署和算例优化&#xff0c;发现一个特别普遍的现象&#xff1a;很多工程师拿到一套新配置&#xff0c;第一反应是把求解器的关键字文件调好、把CPU核数拉到满&#xff0c;然后…

作者头像 李华
网站建设 2026/9/25 5:12:51

Atlas 300V 24G推理加速卡实测:YOLOv5部署全链路与调优

接到手这块Atlas 300V 24G的时候&#xff0c;我第一反应也是去查它到底算运算加速卡还是别的什么卡。等真正把YOLOv5跑起来&#xff0c;又折腾了一阵驱动和模型转换之后&#xff0c;才发现网上一堆帖子说得云里雾里。这篇文章就围绕两个高频问题来写&#xff1a;Atlas 300V 24G…

作者头像 李华
网站建设 2026/9/25 5:12:26

JNA 版本演进全览:从 2.4 到 5.19 的变更日志深度解读

系统编程后端 【免费下载链接】jna Java Native Access 项目地址&#xff1a; https://gitcode.com/gh_mirrors/jn/jna 点击查看 免费下载 本篇指南以 JNA&#xff08;Java Native Access&#xff09;官方仓库的 CHANGES.md 为核心骨架&#xff0c;系统梳理 JNA 从 2.4 到 5.1…

作者头像 李华
网站建设 2026/9/25 5:11:36

ADAU1701音频DSP实战:从SigmaStudio到硬件设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华