SpringBoot实现网页消息推送的5种方法对比

 更新时间:2026年02月11日 09:20:05   作者:AI老李  
网页消息推送是现代 Web 应用的核心功能之一,Spring Boot 提供了非常成熟的支持,本文为大家整理了 5 种主流实现方式,有需要的小伙伴可以了解下

网页消息推送(实时通知、聊天、状态更新、订单提醒等)是现代 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网页消息推送内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java实现将PPT转为OFD过程详解

    Java实现将PPT转为OFD过程详解

    本文将通过Java后端程序代码展示如何实现将PPT幻灯片转成OFD格式,文中的示例代码讲解详细,对我们学习或工作有一定的帮助,需要的可以参考一下
    2022-01-01
  • Ajax实现省市区三级联动

    Ajax实现省市区三级联动

    这篇文章主要为大家详细介绍了jQuery ajax实现省市县三级联动的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能帮助到你
    2021-07-07
  • Mybatis-Plus sum聚合函数及按日期查询并求和的方式详解

    Mybatis-Plus sum聚合函数及按日期查询并求和的方式详解

    这篇文章主要介绍了Mybatis-Plus sum聚合函数及按日期查询并求和,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06
  • Java Heap Dump简介及使用举例

    Java Heap Dump简介及使用举例

    文章详解了Java堆转储(HeapDump)的概念、核心内容、生成方法及分析工具,强调其在诊断内存泄漏、溢出中的关键作用,推荐使用JVM参数自动触发,并指出EclipseMAT为最强大分析工具,同时提醒注意性能影响和数据安全,感兴趣的朋友跟随小编一起看看吧
    2022-12-12
  • Java获取用户IP属地模拟抖音详解

    Java获取用户IP属地模拟抖音详解

    细心的小伙伴可能会发现,抖音新上线了 IP 属地的功能,小伙伴在发表动态、发表评论以及聊天的时候,都会显示自己的 IP 属地信息,本篇文章我们来模拟实现这一功能
    2022-07-07
  • java读取csv文件示例分享(java解析csv文件)

    java读取csv文件示例分享(java解析csv文件)

    这篇文章主要介绍了java读取csv文件示例,这个java解析csv文件的例子很简单,下面直接上代码,大家参考使用吧
    2014-03-03
  • Java新手教程之ArrayList的基本使用

    Java新手教程之ArrayList的基本使用

    ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,这篇文章主要给大家介绍了关于Java新手教程之ArrayList基本使用的相关资料
    2021-06-06
  • Java实现排列组合算法的两种方案

    Java实现排列组合算法的两种方案

    Java排列组合算法是一种用于生成所有可能的排列和组合的算法,在Java中,可以使用递归或迭代的方式实现排列组合算法,本文给大家介绍了Java实现排列组合算法的两种方案,需要的朋友可以参考下
    2024-04-04
  • Sentinel整合Feign流程详细讲解

    Sentinel整合Feign流程详细讲解

    要想整合Feign,首先要了解Feign的使用以及执行过程,然后看 Sentinel如何整合进去,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • 利用java判断质数的3种方法代码示例

    利用java判断质数的3种方法代码示例

    这篇文章主要给大家介绍了关于利用java判断质数的3种方法,在大于1的整数中,如果只包含1和本身这两个约数,就被称为质数(素数),文中给出了详细的代码示例,需要的朋友可以参考下
    2023-07-07

最新评论