一、概述
服务端主动推送:SSE (Server Send Event)
html5新标准,用来从服务端实时推送数据到浏览器端,
直接建立在当前http连接上,本质上是保持一个http长连接,轻量协议
客户端发送一个请求到服务端 ,服务端保持这个请求直到一个新的消息准备好,将消息返回至客户端,此时不关闭连接,仍然保持它,供其它消息使用。SSE的一大特色就是重复利用一个连接来处理每一个消息(又称event)。
二、与WebSocket区别
服务端主动推送:WebSocket
全双工的,本质上是一个额外的tcp连接,建立和关闭时握手使用http协议,其他数据传输不使用http协议
更加复杂一些,适用于需要进行复杂双向数据通讯的场景
三、代码
1.普通请求
@PostMapping("/readData")
public R<Map> readData(@RequestBody IndustryReadRequest industryReadRequest) throws Exception {
Map res = iDeviceService.readData(industryReadRequest);
return R.success(null, res);
}
2.String返回
@ApiOperation("return-String")
@GetMapping(value = "/readDataWithSse", produces = "text/event-stream;charset=UTF-8")
public String readDataWithSSE(@RequestHeader String industryReadRequest) throws Exception {
IndustryReadRequest irr = JsonUtils.parseObject(industryReadRequest, IndustryReadRequest.class);
Map res = iDeviceService.readData(irr);
return "data:" + JsonUtils.toJsonString(res) + "\nretry:100\n\n";
}
3.SseEmitter返回
@ApiOperation("return-SseEmitter")
@GetMapping(value = "/readDataWithSseEmitter",produces = "text/event-stream;charset=UTF-8")
public SseEmitter readDataWithSseEmitter(@RequestHeader String industryReadRequest) throws Exception {
IndustryReadRequest irr = JsonUtils.parseObject(industryReadRequest, IndustryReadRequest.class);
Map res = iDeviceService.readData(irr);
SseEmitter emitter = new SseEmitter();
emitter.send(SseEmitter.event().data(JsonUtils.toJsonString(res)).reconnectTime(100));
return emitter;
}
四、前端访问
导入前端访问依赖,用这个的原因是需要自定义请求头。
也可以选择使用EventSource来发送sse请求
import { EventSourcePolyfill } from 'event-source-polyfill'
const eventSource = new EventSourcePolyfill(process.env.VUE_APP_BASE_API + '/url', {
headers: {
'xxx': "value"
}
})
eventSource.addEventListener('open', function(e) {
console.log('open successfully')
})
eventSource.addEventListener('message', function(e) {
console.log('messagesuccessfully')
})
eventSource.addEventListener('error', function(err) {
that.$message.error('当前浏览器不支持服务器发送的事件')
})
// 关闭sse
eventSource.close()