1. 简介

短信(SMS)在现代应用中扮演着重要角色,应用场景非常广泛:✅ 两步验证(2FA)、✅ 实时告警、✅ 聊天机器人、✅ 用户通知等。

本文将带你用 Java 快速实现一个基于 Twilio 的短信发送功能。

市面上支持短信服务的平台不少,比如 VonagePlivo、AWS 的 SNSZapier 等。但 Twilio 的 SDK 设计简洁,几行代码就能发短信,开发体验非常友好。

2. Twilio 账号配置

要使用 Twilio,首先得注册一个账号。✅ 官方提供免费试用账号,足够用于功能测试。

注册后,你需要做两件事:

  1. 获取一个 Twilio 提供的虚拟手机号(即发送方号码)
  2. 将你自己的手机号添加为“已验证号码”(仅试用账号需要)

⚠️ 注意:试用账号只能给已验证的号码发短信,正式账号则无此限制。

Twilio 官方提供了 Java 快速入门指南,跟着走一遍就能完成配置。

3. 初识 TwiML

在写代码前,先了解下 Twilio 的核心通信格式 —— TwiML(Twilio Markup Language)。

TwiML 是基于 XML 的专用标记语言,用来描述通信行为,比如:打电话、发短信、录音等。它的结构非常直观,由“动词”和“名词”组成。

发送短信的 TwiML 示例

<Response>
    <Message>
        <Body>Sample Twilio SMS</Body>
    </Message>
</Response>

拨打电话的 TwiML 示例

<Response>
    <Dial>
        <Number>415-123-4567</Number>
    </Dial>
</Response>

虽然我们不会手动写 TwiML(SDK 会自动处理),但了解其结构有助于理解底层逻辑。

4. 使用 Twilio Java SDK 发送短信

Twilio 提供了功能完整的 Java SDK,无需手动拼 TwiML,直接调 API 即可

4.1 依赖引入

pom.xml 中添加以下依赖:

<dependency>
    <groupId>com.twilio.sdk</groupId>
    <artifactId>twilio</artifactId>
    <version>7.20.0</version>
</dependency>

最新版本可查看 Maven Central

4.2 发送普通短信(SMS)

核心代码如下:

Twilio.init("ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "your_auth_token");
Message message = Message.creator(
    new PhoneNumber("+12225559999"),
    new PhoneNumber("+15017122661"),
    "Hello from Twilio via Java!")
.create();

关键点解析:

  • Twilio.init():全局初始化,传入你的 Account SID 和 Auth Token(在 Twilio 控制台获取)
  • Message.creator():构造短信,参数依次是:接收方号码、发送方号码(即 Twilio 分配的号码)、消息内容
  • create():执行发送动作,同步阻塞调用

接收方号码必须是已验证号码(试用账号限制)

4.3 发送多媒体短信(MMS)

Twilio 也支持发送图片等多媒体内容,只需额外设置 mediaUrl

Twilio.init("ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "your_auth_token");
Message message = Message.creator(
    new PhoneNumber("+12225559999"),
    new PhoneNumber("+15017122661"),
    "Check out this image!")
.setMediaUrl(
    Promoter.listOfOne(URI.create("https://example.com/image.jpg")))
.create();

⚠️ 注意:

  • 接收设备需支持 MMS
  • 图片链接必须可公开访问
  • Promoter.listOfOne() 是 Guava 的工具方法,用于创建单元素列表

5. 短信状态跟踪

发出去不等于收到。Twilio 提供了完整的消息状态追踪机制,帮你判断短信是否成功送达。

5.1 短信状态码说明

状态 说明
queued 消息已入队,等待发送
sending 正在发送到运营商
sent 运营商已接收
delivered 已送达目标手机(理想状态)
failed 发送失败
undelivered 运营商反馈未送达

failedundelivered 通常附带错误码,可用于排查问题(如号码无效、运营商拒收等)。

5.2 同步查询状态

通过 Message.reader().read() 获取历史消息状态:

Twilio.init("ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "your_auth_token");
ResourceSet messages = Message.reader().read();
for (Message message : messages) {
    System.out.println(message.getSid() + " : " + message.getStatus());
}

⚠️ 注意:

  • 该方法会发起远程调用,不要频繁使用
  • 默认返回所有消息,可通过 .setTo().setDateSent() 等方法过滤

5.3 异步查询状态(推荐)

为避免阻塞主线程,推荐使用异步方式:

Twilio.init("ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "your_auth_token");
ListenableFuture<ResourceSet<Message>> future = Message.reader().readAsync();

Futures.addCallback(future, new FutureCallback<ResourceSet<Message>>() {
    @Override
    public void onSuccess(ResourceSet<Message> messages) {
        for (Message msg : messages) {
            System.out.println(msg.getSid() + " : " + msg.getStatus());
        }
    }

    @Override
    public void onFailure(Throwable t) {
        System.out.println("Failed to get message status: " + t.getMessage());
    }
}, MoreExecutors.directExecutor());

✅ 使用了 Guava 的 ListenableFuture,回调在独立线程执行,不影响主流程。

6. 总结

本文演示了如何在 Java 项目中集成 Twilio 实现短信和彩信发送,并介绍了状态追踪的最佳实践。

虽然底层基于 TwiML,但 Twilio 的 Java SDK 封装得非常到位,几行代码就能上线功能,适合快速迭代项目。

完整示例代码已上传至 GitHub:https://github.com/your-repo/twilio-java-demo(mock 地址)


原始标题:Sending SMS in Java with Twilio