html5 sse推送指定用户,服务端通过SSE向前端推送消息

本文介绍如何在Spring项目中利用SSE (Server-Sent Events) 实现文件上传解析进度的实时推送,与WebSocket相比,SSE以更简洁代码展示其便捷性。通过定时任务每500毫秒发送一次进度,展示了SSE的高效与易用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SSE(Server-Sent Events)相比Websocket来说更加轻量,在代码书写时也更加的方便,所以今天来讲一下SSE的简单使用。

当时接到一个需求是上传word进行解析题目存储,并且前端要显示解析过程,当时首先想到的就是Websocket,后来仔细一想,有没有更轻量级的方法呢,果然还是有的

下面来讲一下具体的使用方法

我们使用Spring项目来进行讲解,所以需要引入的Spring依赖就不再说明了,然后我们可以惊奇的发现引入完Spring的一些依赖,我们竟然就可以使用SSE了。果然够轻量

通过以下简单的代码我们就完成了SSE消息的发送,一个方法通过sse监控解析进度,一个方法进行文件解析

/**

* sse

*/

@GetMapping("/sse")

public SseEmitter getSSE(

HttpServletRequest request) {

SseEmitter emitter;

String userId = UserUtils.getUserId(request);

if (userMap.containsKey(userId)) {

emitter = userMap.get(userId);

} else {

emitter = new SseEmitter();

userMap.put(userId, emitter);

emitter.onTimeout(() -> userMap.remove(userId));

}

return emitter;

}

@PostMapping("/submit")

public ResponseMessage submit(

HttpServletRequest request,

@RequestParam MultipartFile file,

@RequestParam String category,

@RequestParam String type,

@RequestParam(required = false, defaultValue = "") String year) {

String editor = UserUtils.getUserId(request);

return ResponseMessage.successMessage(uploadService.upload(file, category, type, year, editor));

}

返回数据

data:"文件开始解析"

event:upload_start

接下来说一下我们该如何进行解析操作

/**

* 存储解析进度key:userId,value:schedule

*/

private final Map scheduleMap = Maps.newConcurrentMap();

/**

* 是否已经完成解析key:userId,value:是否已经完成

*/

private final Map isFinishedMap = Maps.newConcurrentMap();

/**

* 解析完成后返回的数据

*/

private final Map> returnMap = Maps.newConcurrentMap();

@Scheduled(fixedRate = 500)

public void uploadSchedule() {

for (Map.Entry entry : UploadCtrl.userMap.entrySet()) {

try {

String userId = entry.getKey();

Boolean isFinished = isFinishedMap.get(userId);

if (isFinished == null) {

return;

}

if (!isFinished) {

SseEmitter.SseEventBuilder builder = SseEmitter

.event()

.data(scheduleMap.get(userId))

.name("upload_schedule");

entry.getValue().send(builder);

log.info("sse send" + userId + " schedule: " + scheduleMap.get(userId));

} else {

// 代表解析完毕

SseEmitter.SseEventBuilder builder = SseEmitter

.event()

.data(returnMap.get(userId))

.name("upload_end");

entry.getValue().send(builder);

log.info("sse send" + userId + " end: " + gson.toJson(returnMap.get(userId)));

// 解析完毕后从Map中移除

UploadCtrl.userMap.remove(userId);

isFinishedMap.remove(userId);

scheduleMap.remove(userId);

returnMap.remove(userId);

// 关闭emitter

entry.getValue().complete();

}

} catch (Exception e) {

log.warn("upload Error of " + entry.getKey(), e);

UploadCtrl.userMap.remove(entry.getKey());

}

}

}

可以看出我通过是否完成map,解析结果map,解析进度map来进行解析进度的存储,然后通过定时任务,每0.5s向前端发送一次进度。

我们可以发现,使用SSE推送消息是十分的方便快捷的,并且自身封装有一些失败重试,自动重连的机制,相比websocket来说,使用更加方便。

今天前端同事对接接口,才发现sse是没法使用post方法的,这一点大家要注意,所以对博客进行了更改

每当我们想要松懈时,就想想之前的汗水,那是我们今天所拥有的一切的源泉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值