在用户活跃度提升、系统告警提醒、业务流转协作等场景中,“通知推送”是不可缺少的一环。一个优秀的通知系统不仅支持多渠道推送,还应具备模板管理、用户配置、异步发送、重试机制等功能。
本文将基于“统一通知中心”的思想,带你实现站内信 + 邮件 + 短信的灵活推送机制。
一、通知推送常见场景
场景 | 推送渠道 |
---|---|
用户注册成功 | 邮件 / 站内信 |
密码找回 | 短信 / 邮件 |
审批待处理提醒 | 站内信 / 钉钉 |
定时任务执行失败 | 邮件 / 微信机器人 |
系统公告 | 站内信 |
二、数据库表结构设计
CREATE TABLE notify_message (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT,
title VARCHAR(100),
content TEXT,
channel VARCHAR(20), -- email/sms/inbox
status TINYINT DEFAULT 0, -- 0待发送 1已发送 2失败
send_time DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
三、发送流程设计
步骤:
- 插入一条待发送通知记录
- 通知服务扫描状态为“待发送”的记录
- 根据 channel 类型分发到具体发送器(如邮件服务)
- 更新发送状态(成功/失败)
通道封装建议:
- 每种通道实现统一接口
Notifier.send(user, title, content)
- 使用策略模式或注册表动态调用对应通道
四、Java 示例代码结构
通道接口
public interface Notifier {
void send(Long userId, String title, String content);
}
邮件实现
@Component("email")
public class EmailNotifier implements Notifier {
public void send(Long userId, String title, String content) {
// 调用 JavaMailSender 或 3rd SDK
}
}
短信实现
@Component("sms")
public class SmsNotifier implements Notifier {
public void send(Long userId, String title, String content) {
// 调用云短信API
}
}
通知调度器
@Component
public class NotifyScheduler {
@Autowired private Map<String, Notifier> notifierMap;
@Scheduled(fixedRate = 30000)
public void dispatch() {
List<NotifyMessage> list = dao.findUnsent();
for (var msg : list) {
Notifier notifier = notifierMap.get(msg.getChannel());
try {
notifier.send(msg.getUserId(), msg.getTitle(), msg.getContent());
msg.setStatus(1);
} catch (Exception e) {
msg.setStatus(2);
}
dao.update(msg);
}
}
}
五、Python 示例结构(简化)
class Notifier:
def send(self, user_id, title, content): pass
class EmailNotifier(Notifier):
def send(self, user_id, title, content):
# 使用smtplib发送邮件
pass
def dispatch():
rows = db.query("SELECT * FROM notify_message WHERE status=0")
for row in rows:
notifier = notifier_registry[row['channel']]
try:
notifier.send(row['user_id'], row['title'], row['content'])
db.update_status(row['id'], 1)
except:
db.update_status(row['id'], 2)
六、前端展示站内信(Vue)
<template>
<el-table :data="messages">
<el-table-column prop="title" label="标题" />
<el-table-column prop="send_time" label="时间" />
<el-table-column prop="status" label="状态" />
</el-table>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
const messages = ref([])
onMounted(async () => {
const res = await axios.get('/notify/inbox')
messages.value = res.data.list
})
</script>
七、接口文档模板
POST /notify/send
- 参数:user_id, title, content, channel
- 响应:{ code: 200, msg: “已入队” }
GET /notify/inbox
- 查询当前用户站内信列表
八、扩展建议
功能 | 推荐做法 |
---|---|
模板管理 | 支持富文本模板与变量替换 |
用户配置 | 每人可设置偏好推送渠道 |
失败重试 | 设置重试次数,失败入死信队列 |
报警渠道接入 | 钉钉/飞书机器人、自定义 webhook |
九、总结
层级 | 主要职责 |
---|---|
数据库 | 存储通知内容与状态记录 |
后端 | 路由分发通道、发送结果更新 |
前端 | 展示站内消息列表、状态标识 |
统一的通知推送系统是支撑大型系统用户交互、监控预警、业务驱动的核心模块之一。灵活设计、多通道组合、可配置模板,将显著提升系统的响应能力与用户体验。