网页消息推送(实时通知、聊天、状态更新、订单提醒等)是现代 web 应用的核心功能之一。spring boot 提供了非常成熟的支持,下面整理出目前最常用、最实用的 5 种实现方式,从简单到高级排序,并标注适用场景、优缺点和核心代码要点。
1. 短轮询(short polling) + ajax / fetch
原理:前端定时(每 3–10 秒)通过 ajax / fetch 向后端拉取新消息。
适用场景:对实时性要求不高、开发周期短、兼容性极强
优点:实现最简单,无需额外依赖,兼容所有浏览器
缺点:服务器压力大(大量无效请求)、延迟高、不够“实时”
核心代码(后端):
@restcontroller
public class notificationcontroller {
@getmapping("/notifications")
public responseentity<list<string>> getnotifications() {
// 查询是否有新消息(数据库 / redis / 内存队列)
list<string> newmsgs = notificationservice.pollnewmessages();
return responseentity.ok(newmsgs);
}
}
前端(vue/react 通用):
setinterval(async () => {
const res = await fetch('/notifications');
const data = await res.json();
if (data.length > 0) addnotifications(data);
}, 5000);
2. 长轮询(long polling)
原理:客户端发起请求,后端如果没有新消息就挂起请求(不返回),有新消息立即返回;前端收到后立即再发起下一次请求。
适用场景:实时性要求较高,但不想引入 websocket/sse
优点:比短轮询节省资源,实现相对简单
缺点:连接频繁建立/断开,服务器需维护大量长连接
后端实现(使用 deferredresult):
@getmapping("/long-poll")
public deferredresult<list<string>> longpoll() {
deferredresult<list<string>> result = new deferredresult<>(30000l); // 30秒超时
// 异步监听新消息(可使用消息队列或 blockingqueue)
messagequeue.addlistener(msg -> {
if (!result.issetorexpired()) {
result.setresult(collections.singletonlist(msg));
}
});
result.ontimeout(() -> result.setresult(collections.emptylist()));
return result;
}
3. server-sent events(sse)
原理:基于 http 的单向服务器推送,客户端使用 eventsource 建立持久连接,服务端通过 text/event-stream 推送事件。
适用场景:服务器 → 客户端单向推送(如通知、进度、股票价格、日志监控)
优点:实现简单、自动重连、基于标准 http、资源消耗比 websocket 低
缺点:单向(客户端不能主动发消息)、不支持二进制
后端核心代码(spring boot 推荐方式):
@getmapping(value = "/sse", produces = mediatype.text_event_stream_value)
public flux<serversentevent<string>> ssenotifications() {
return flux.interval(duration.ofseconds(1))
.map(seq -> serversentevent.<string>builder()
.id(string.valueof(seq))
.event("message")
.data("服务器推送:" + localdatetime.now())
.build());
}
或使用 sseemitter(更灵活,支持断开重连):
@getmapping("/notifications")
public sseemitter stream() {
sseemitter emitter = new sseemitter(long.max_value);
// 在其他地方调用 emitter.send() 推送
return emitter;
}
前端:
const source = new eventsource('/sse');
source.onmessage = e => console.log('收到:', e.data);
4. websocket(原生 / @serverendpoint)
原理:全双工通信通道,浏览器和服务器建立持久 tcp 连接。
适用场景:需要双向实时通信(聊天、协作编辑、游戏)
优点:真正的实时双向、低延迟
缺点:实现稍复杂、需处理断线重连、心跳
spring boot 简单实现:
@serverendpoint("/ws/{userid}")
@component
public class websocketendpoint {
private static final map<string, session> sessions = new concurrenthashmap<>();
@onopen
public void onopen(session session, @pathparam("userid") string userid) {
sessions.put(userid, session);
}
@onmessage
public void onmessage(string message, session session) {
// 广播或点对点
}
public static void sendtouser(string userid, string msg) {
session session = sessions.get(userid);
if (session != null && session.isopen()) {
session.getasyncremote().sendtext(msg);
}
}
}
配置:
@configuration
@enablewebsocket
public class websocketconfig implements websocketconfigurer {
@override
public void registerwebsockethandlers(websockethandlerregistry registry) {
registry.addhandler(new mywebsockethandler(), "/my-ws").setallowedorigins("*");
}
}
5. websocket + stomp(最推荐的生产方式)
原理:在 websocket 上层使用 stomp 协议(类似 http 的消息协议),支持订阅主题、点对点、广播等。
适用场景:几乎所有中大型实时应用(聊天、通知、实时仪表盘、订单状态)
优点:功能强大(订阅/取消订阅、断线重连、消息确认)、易于管理用户会话、支持广播/点对点
依赖:
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-websocket</artifactid>
</dependency>
配置:
@configuration
@enablewebsocketmessagebroker
public class websocketconfig implements websocketmessagebrokerconfigurer {
@override
public void configuremessagebroker(messagebrokerregistry config) {
config.enablesimplebroker("/topic", "/queue"); // 订阅前缀
config.setapplicationdestinationprefixes("/app"); // 发送前缀
config.setuserdestinationprefix("/user"); // 点对点前缀
}
@override
public void registerstompendpoints(stompendpointregistry registry) {
registry.addendpoint("/ws")
.setallowedoriginpatterns("*")
.withsockjs(); // 支持降级
}
}
发送消息(广播):
@autowired
private simpmessagingtemplate messagingtemplate;
public void sendnotification(string message) {
messagingtemplate.convertandsend("/topic/notifications", message);
}
点对点(需结合 spring security 或自定义 principal):
messagingtemplate.convertandsendtouser(username, "/queue/notifications", message);
前端(使用 stomp.js 或 @stomp/stompjs):
const client = new client({
brokerurl: 'ws://localhost:8080/ws',
onconnect: () => {
client.subscribe('/topic/notifications', msg => console.log(msg.body));
client.subscribe('/user/queue/notifications', msg => console.log(msg.body));
}
});
client.activate();
总结对比表
| 方式 | 实时性 | 方向性 | 复杂度 | 资源消耗 | 推荐场景 |
|---|---|---|---|---|---|
| 短轮询 | ★☆☆☆☆ | 双向 | 最低 | 高 | 原型、兼容性要求极高 |
| 长轮询 | ★★☆☆☆ | 双向 | 低 | 中 | 中等实时性 |
| sse | ★★★★☆ | 服务器→客户端 | 低 | 低 | 服务器单向推送首选 |
| 原生 websocket | ★★★★★ | 双向 | 中 | 中 | 简单双向场景 |
| websocket + stomp | ★★★★★ | 双向 | 中高 | 中 | 生产级实时应用首选 |
2026 年推荐优先级:
- 大多数场景 → websocket + stomp
- 纯服务器推送、资源敏感 → sse
- 简单/原型 → 轮询
到此这篇关于springboot实现网页消息推送的5种方法对比的文章就介绍到这了,更多相关springboot网页消息推送内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论