服务器主动发送请求在开发中比较常用,早期使用ajax向服务器轮询消息,但这种方式会增加服务器负担,而且消息返回会有延迟。
-
解决方案一:websocket
-
解决方案二:sse
SSE:
原理:浏览器向服务器发送请求后,服务器抓住请求不放,等到数据更新时,服务器再把数据发送给浏览器,浏览器拿到响应后,再向服务器发送请求,如此循环
好处:只使用了一次请求,大大减小了服务器的请求数量,减轻服务器压力,只会在接收到数据更新后才返回响应。
栗子:
服务端 springboot接收请求
@RestController
@Slf4j
public class PushController {
private int count;
/**
* 超时时间设置到最大,避免因为超时导致连接断开
*/
private SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);
@GetMapping(value = "/push")
public SseEmitter push() throws InterruptedException {
return emitter;
}
@GetMapping("/send")
public String send() {
try {
emitter.send("push " + count++);
return "success";
} catch (IOException e) {
e.printStackTrace();
}
return "failed";
}
}
客户端 js监听消息
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>服务器推送示例</title>
</head>
<body>
<div id="msg"></div>
</body>
<script>
var source = new EventSource("/springboot/push");
source.onmessage = function (e) {
console.info("收到信息");
document.getElementById("msg").innerHTML += `<p>${e.data}</p>`;
};
source.onopen = function (e) {
console.info("连接打开");
console.info(e);
};
source.onerror = function (e) {
console.info("连接错误");
console.info(e);
};
</script>
</html>
每次访问send,服务器就会向浏览器返回数据
可以看到一个push请求接收了来自服务器的多个数据