本文目录导读:

- 📚 目录导读
- 什么是站内消息推送?业务场景与价值
- Java实现站内消息的核心技术栈
- 案例1:基于消息队列的异步推送(RabbitMQ)
- 案例2:WebSocket实时推送 + Spring Boot整合
- 案例3:配合数据库轮询的离线消息补发
- 高频问答集锦(开发者必读)
- SEO优化建议 & 总结
📚 目录导读
- 什么是站内消息推送?业务场景与价值
- Java实现站内消息的核心技术栈
- 案例1:基于消息队列的异步推送(RabbitMQ/ Kafka)
- 案例2:WebSocket实时推送 + Spring Boot整合
- 案例3:配合数据库轮询的离线消息补发
- 高频问答集锦(开发者必读)
- SEO优化建议 & 总结
什么是站内消息推送?业务场景与价值
站内消息推送,是指用户在登录系统后,在平台内收到的通知、公告、提醒等非邮件/非短信的即时或延迟消息,常见场景包括:
- 电商:订单状态更新、物流提醒、优惠券到账
- 社交:点赞评论、好友申请、系统公告
- 企业系统:审批进度、任务指派、告警通知
价值:提升用户活跃度、降低通知延迟、增强用户体验,Java作为后端主力语言,必须掌握高效推送方案。
Java实现站内消息的核心技术栈
| 组件 | 推荐技术 | 说明 |
|---|---|---|
| 后端框架 | Spring Boot + Spring MVC | 提供REST API和WebSocket支持 |
| 消息中间件 | RabbitMQ / Apache Kafka | 解耦生产与消费,保证消息不丢 |
| 实时通信 | WebSocket / SSE | 双向实时推送 |
| 数据库 | MySQL + Redis | MySQL存储消息,Redis缓存未读数量 |
| 生命周期 | 生产者→消息队列→消费者→DB→推送 |
关键设计原则:异步、削峰、可靠、实时。
案例1:基于消息队列的异步推送(RabbitMQ)
场景
当用户完成支付后,系统需向用户推送“订单已支付”通知,若同步推送,高并发下可能阻塞下游服务。
实现步骤
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置队列
@Configuration
public class RabbitConfig {
@Bean
public Queue pushQueue() {
return new Queue("user.push.queue", true);
}
}
生产者(支付服务)
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void paySuccess(Long userId, String orderNo) {
// 业务逻辑 ...
PushMessage msg = new PushMessage(userId, "您的订单 " + orderNo + " 已支付成功");
rabbitTemplate.convertAndSend("user.push.queue", msg);
}
}
消费者(推送服务)
@Component
@RabbitListener(queues = "user.push.queue")
public class PushConsumer {
public void handlePush(PushMessage msg) {
// 1. 存储到数据库(MySQL)
pushMsgRepository.save(msg);
// 2. 通过WebSocket实时推送
webSocketService.sendToUser(msg.getUserId(), msg.getContent());
}
}
优势:解耦、抗压、支持失败重试。
案例2:WebSocket实时推送 + Spring Boot整合
场景
用户在线时,需立刻收到消息,而非HTTP轮询。
实现步骤
WebSocket配置
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(chatHandler(), "/ws/push")
.setAllowedOrigins("*");
}
}
处理器逻辑
public class PushWebSocketHandler extends TextWebSocketHandler {
private static final Map<Long, WebSocketSession> sessions = new ConcurrentHashMap<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
Long userId = extractUserId(session); // 从token获取
sessions.put(userId, session);
}
public void sendToUser(Long userId, String message) {
WebSocketSession session = sessions.get(userId);
if (session != null && session.isOpen()) {
session.sendMessage(new TextMessage(message));
}
}
}
前端连接
let ws = new WebSocket("wss://your-domain.com/ws/push?token=xxx");
ws.onmessage = (event) => {
// 更新通知栏
};
注意:需配合Spring Security拦截器做权限校验。
案例3:配合数据库轮询的离线消息补发
场景
用户离线期间,WebSocket无法推送,需在用户重新上线时,通过数据库轮询补发。
实现方案
-
消息表设计
CREATE TABLE `user_push` ( `id` bigint PRIMARY KEY, `user_id` bigint, `content` varchar(500), `status` tinyint DEFAULT 0, -- 0未读1已读 `created_at` datetime );
-
上线时批量拉取
@EventListener public void onUserOnline(UserOnlineEvent event) { List<PushMessage> unread = pushMsgRepository.findByUserIdAndStatus( event.getUserId(), 0); for (PushMessage msg : unread) { webSocketService.sendToUser(msg.getUserId(), msg.getContent()); } // 标记已读 pushMsgRepository.updateStatusByUserId(event.getUserId(), 1); }
优化:使用Redis做未读计数热数据,减轻DB压力。
高频问答集锦(开发者必读)
Q1:什么时候用RabbitMQ,什么时候用Kafka?
A:RabbitMQ适合轻量级、路由灵活、实时性高的站内推送;Kafka适合海量日志、高吞吐、数据持久化需求,小规模团队优先选择RabbitMQ。
Q2:WebSocket断线重连怎么处理?
A:前端监听 onclose,使用指数退避策略重连(如1s→2s→4s...),服务端维护心跳(ping/pong)检测死连接。
Q3:如何保证消息不丢?
A:生产者开启confirm模式,消费者手动ack,未确认消息重新入队列,同时数据库写入作为兜底。
Q4:推送消息体包含敏感信息怎么办?
A:使用AES或HTTPS加密传输,服务端只推送消息ID,前端通过HTTP接口拉取详情并加密展示。
Q5:十万级用户并发推送怎么设计?
A:采用Redis消息队列 + 多消费者组 + WebSocket集群,配合Nginx+Sticky Session路由用户到相同节点。
SEO优化建议 & 总结
SEO关键词布局
- 核心词:Java站内消息推送、Spring Boot WebSocket、RabbitMQ推送案例
- 长尾词:Java实时通知系统架构、离线消息补发方案、高并发消息队列设计
策略
- 整理知乎/CSDN/掘金同主题热门文章,提取高频代码片段并注释详细
- 将本文拆分为3篇系列文章:《基础篇:队列与存储》《进阶篇:WebSocket实战》《高并发篇:集群与离线》
通过本文的三个案例,你可以构建一个完整的站内消息推送系统:
- RabbitMQ异步解耦保证高可用
- WebSocket实时推送提升即时性
- 数据库+Redis轮询确保离线消息不丢失
实际项目中,建议根据用户并发量、团队技术栈灵活组合,初创项目直接用Spring Event + WebSocket即可,百万级用户则需中间件+分片。
📌 代码示例已去掉具体域名,部署时请替换为实际的WebSocket端点地址和MQ连接配置。