当前位置: 代码网 > it编程>编程语言>Java > Spring之SseEmitter实现让你的进度条实时更新

Spring之SseEmitter实现让你的进度条实时更新

2025年02月28日 Java 我要评论
在现代 web 应用中,实时数据传输已经成为一个不可忽视的需求,尤其是在聊天系统、实时数据展示、进度推送等场景中。spring 提供了 sseemitter 来支持服务器端推送事件(server-se

在现代 web 应用中,实时数据传输已经成为一个不可忽视的需求,尤其是在聊天系统、实时数据展示、进度推送等场景中。

spring 提供了 sseemitter 来支持服务器端推送事件(server-sent events, sse),它通过 http 协议允许服务器主动向客户端推送数据。与 websocket 不同,sse 是单向通信,但它也提供了一种轻量、高效的实时数据流解决方案。

本文将从原理、实际应用、客户端和服务端代码示例、扩展应用场景等方面详细介绍 spring sseemitter

1. 原理解析

1.1 server-sent events (sse)

sse 是一种基于 http 协议的单向数据流技术,允许服务器通过持久化的 http 连接将事件推送到客户端。其与 websocket 的主要区别是,sse 是单向通信(从服务器到客户端),而 websocket 是全双工通信(服务器和客户端都可以发送数据)。

在 sse 中,客户端通过 eventsource 对象与服务器建立连接,服务器将数据以流的方式推送到客户端。sse 使用标准的 http 协议,并且是基于文本的流,数据通常以 text/event-stream 类型的格式传输。

1.2 sseemitter

sseemitter 是 spring 提供的一个类,用于实现 sse 功能。它支持向客户端推送数据,并且能够处理长连接。sseemitter 的主要功能包括:

  • 异步发送数据:sse 是长连接,sseemitter 可以在服务器端异步发送数据。
  • 支持超时管理:sseemitter 可以设置超时,若客户端在指定时间内没有响应,连接会自动关闭。
  • 异常处理:如果发生错误,可以通过 sseemitter 完成错误通知和连接关闭。

2. 服务端代码实现

2.1 创建 sse 连接

使用 spring 的 sseemitter 来向客户端推送实时事件非常简单。

我们通过 @getmapping 注解来映射一个请求路径,返回一个 sseemitter 实例。

@restcontroller
public class ssecontroller {

    @getmapping(value = "/sync/stream", produces = mediatype.text_event_stream_value)
    public sseemitter syncstream() {
        sseemitter emitter = new sseemitter();

        // 模拟异步任务,发送实时数据
        new thread(() -> {
            try {
                for (int i = 0; i <= 100; i++) {
                    emitter.send("data: " + i + "% complete\n\n");
                    thread.sleep(1000);  // 模拟任务处理
                }
                emitter.complete();  // 任务完成,结束 sse 流
            } catch (exception e) {
                emitter.completewitherror(e);  // 出现异常时结束流
            }
        }).start();

        return emitter;
    }
}

在上面的代码中,syncstream 方法创建了一个 sseemitter 实例,并使用一个线程模拟了一个处理任务的过程。

每秒钟将当前进度推送给客户端,直到进度达到 100%。当任务完成时,通过 emitter.complete() 关闭连接。

  • sseemitter.send(data): 用于向客户端推送数据。
  • sseemitter.complete(): 用于标记推送完成,关闭连接。
  • sseemitter.completewitherror(exception): 如果发生异常,可以通过此方法结束连接并发送错误信息。

2.2 超时设置

sse 连接可能会因为网络问题或其他原因被中断,spring 提供了超时设置,确保连接不被无限期阻塞。

@getmapping(value = "/sync/stream", produces = mediatype.text_event_stream_value)
public sseemitter syncstream() {
    sseemitter emitter = new sseemitter(30000l);  // 设置超时时间为30秒
    // 发送数据的代码同上...
    return emitter;
}

3. 客户端代码实现

在客户端,我们可以使用原生的 javascript eventsource 对象来接收 sse 流数据。eventsource 会自动管理连接,包括重试和重新连接等操作。

let eventsource = new eventsource("/sync/stream");

eventsource.onmessage = function(event) {
    console.log("received message: ", event.data);
};

eventsource.onerror = function(error) {
    console.error("eventsource failed: ", error);
};
  • new eventsource("/sync/stream"): 创建一个连接到指定 url 的 eventsource 实例。
  • onmessage: 每当服务器发送一个事件时,会触发该事件。
  • onerror: 当发生错误时,会触发该事件。

4. 扩展应用场景

4.1 实时任务进度推送

可以利用 sseemitter 来推送后台任务的实时进度。

例如,在执行一个需要时间的任务时,可以定期向客户端推送进度更新。

@getmapping("/task/progress")
public sseemitter streamtaskprogress() {
    sseemitter emitter = new sseemitter();
    new thread(() -> {
        try {
            for (int i = 0; i <= 100; i++) {
                emitter.send("data: " + i + "% complete\n\n");
                thread.sleep(1000);  // 模拟任务处理
            }
            emitter.complete();  // 任务完成,结束 sse 流
        } catch (exception e) {
            emitter.completewitherror(e);  // 出现异常时结束流
        }
    }).start();
    return emitter;
}

4.2 实时聊天系统

在实时聊天应用中,可以使用 sse 向所有连接的客户端推送消息。

@getmapping("/chat/{roomid}")
public sseemitter streamchatmessages(@pathvariable string roomid) {
    sseemitter emitter = new sseemitter();
    chatservice.addlistener(roomid, message -> {
        try {
            emitter.send("data: " + message + "\n\n");
        } catch (ioexception e) {
            emitter.completewitherror(e);
        }
    });
    return emitter;
}

在这个例子中,

chatservice.addlistener(roomid, message -> {...}) 

是监听指定聊天室消息的逻辑,所有聊天信息都会通过 sseemitter.send() 推送到客户端。

4.3 动态数据显示

sse 适用于动态显示数据更新的场景,比如股票价格、天气预报等实时数据。

@getmapping("/live-stock/{symbol}")
public sseemitter streamstockprice(@pathvariable string symbol) {
    sseemitter emitter = new sseemitter();
    stockservice.addpricelistener(symbol, price -> {
        try {
            emitter.send("data: " + price + "\n\n");
        } catch (ioexception e) {
            emitter.completewitherror(e);
        }
    });
    return emitter;
}

在这个例子中,

stockservice.addpricelistener(symbol, price -> {...})

监听股票的实时价格变化,并通过 sseemitter.send() 将最新价格推送到客户端。

5. 总结

spring 的 sseemitter 提供了一种简洁且高效的方式来实现服务器向客户端推送实时事件。通过 sse,我们可以轻松地在后台执行长时间任务,并将实时数据推送给前端应用。

sse 适用于许多场景,如任务进度推送、实时消息通知、动态数据展示等。相较于 websocket,sse 实现简单,且不需要额外的协议支持,适合轻量级的实时应用。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com