核心代码:
后端:
创建连接后,可以通过一般的请求来访问"/sendMessage"接口让后端向前端发信息,也可以后端创建一个循环任务来主动发送信息。
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/sse")
public class IndexController {
private SseEmitter sseEmitter;
/**
* 创建SSE连接
*
* @return
*/
@GetMapping(path = "/connect")
public SseEmitter sse() {
sseEmitter = new SseEmitter();
return sseEmitter;
}
/**
* 广播消息
*
* @param message
*/
@PostMapping("/sendMessage")
public void sendMessage(@RequestBody Message message) throws IOException {
sseEmitter.send(message);
}
}
如果需要多个sse连接同时存在,那么就用list来存SseEmitter
前端:
<template>
<div>
<div id="result"></div>
<el-button @click="sendMessage">send</el-button>
</div>
</template>
<script setup>
import api from '@/api/common'
import { useRouter } from 'vue-router'
const router = useRouter()
// 连接服务器
var sseSource = new EventSource("http://localhost:8888/sse/connect");
// 连接打开
sseSource.onopen = function () {
console.log("连接打开");
}
// 连接错误
sseSource.onerror = function (err) {
console.log("连接错误:", err);
}
// 接收到数据
sseSource.onmessage = function (event) {
console.log("接收到数据:", event);
handleReceiveData(JSON.parse(event.data))
}
// 关闭链接
function handleCloseSse() {
sseSource.close()
}
// 处理服务器返回的数据
function handleReceiveData(data) {
let div = document.createElement('div');
div.innerHTML = data.data;
document.getElementById('result').appendChild(div);
}
// 通过http发送消息
function sendMessage() {
api.sendMessage({
data: new Date().toDateString(),
total: 0
})
}
</script>
如果发起sse连接时需要修改请求头来携带token,需要用使用第三方插件EventSourcePolyfill:
npm install event-source-polyfill
界面: