前言
在前台页面需要不停获取服务器端的数据时,无非有两种操作,一种是通过前台页面使用轮询的方式,定时向服务器后台发送请求,以获取最新的数据;另一种就是在前台页面和后台服务之间建立长连接,服务器端一有数据产生就向前端页面推送。
这里的SSE是服务器发送事件(Server-Sent Events) 的缩写,在WebFlux框架里,服务器端是如何向前端(或调用端)实现服务器发送事件的呢?在有前端页面的情况下,又是如何实现的呢?
带着上面的这些疑问,来了解WebFlux框架,WebFlux框架是一款响应式编程web框架,什么是响应式编程呢,根据wikipedia上的定义:
响应式编程是就是对于数据流和传播改变的一种声明式的编程规范。这意味着可以通过编程语言轻松地表达静态(例如数组)或动态(例如事件发射器)数据流,并且存在相关执行模型内的推断依赖性,这有助于自动传播数据流涉及的变化。
围绕着WebFlux框架的,有这么几个关键字,异步的、非阻塞的、响应式的,那么是不是能够实现数据一有变化,就通知到对应的调用端呢,这些还有待证实。
基于WebFlux框架的SSE应用
首先,在pom文件中,引入webflux框架;
org.springframework.boot
spring-boot-starter-webflux
org.springframework.boot
spring-boot-starter-thymeleaf
第二,html代码,共有四个页面;
sse.html页面代码:
服务器推送事件//服务器推送事件
if (typeof (EventSource) !== "undefined") {
//第一种写法
//接收服务器倒计时时间推送,使用HTML5 服务器发送事件(Server-Sent Events),参考资料:https://www.runoob.com/html/html5-serversentevents.html
var source = new EventSource("/sse/countDown");
console.log(source);
source.addEventListener("countDown", function(e) {
document.getElementById("result").innerHTML = e.data;
}, false);//使用false表示在冒泡阶段处理事件,而不是捕获阶段。
//第二种写法
//随机数获取
var source1 = new EventSource("/sse/retrieve");
//当抓取到消息时
source1.onmessage = function (evt) {
document.getElementById("data").innerHTML = "股票行情:" + evt.data;
};
} else {
//注意:ie浏览器不支持
document.getElementById("result").innerHTML = "抱歉,你的浏览器不支持 server-sent 事件...";
var xhr;
var xhr2;
if (window.XMLHttpRequest){
//IE7+, Firefox, Chrome, Opera, Safari浏览器支持该方法
xhr=new XMLHttpRequest();
xhr2=new XMLHttpRequest();
}else{
//IE6, IE5 浏览器不支持,使用ActiveXObject方法代替
xhr=new ActiveXObject("Microsoft.XMLHTTP");
xhr2=new ActiveXObject("Microsoft.XMLHTTP");
}
console.log(xhr);
console.log(xhr2);
xhr.open('GET', '/sse/countDown');
xhr.send(null);//发送请求
xhr.onreadystatechange = function() {
console.log("s响应状态:" + xhr.readyState);
//2是空响应,3是响应一部分,4是响应完成
if (xhr.readyState > 2) {
//这儿可以使用response(对应json)与responseText(对应text)
var newData = xhr.response.substr(xhr.seenBytes);
newData = newData.replace(/\n/g, "#");
newData = newData.substring(0, newData.length - 1);
var data = newData.split("#");
console.log("获取到的数据:" + data);
document.getElementById("result").innerHTML = data;
//长度重新赋值,下次截取时需要使用
xhr.seenBytes = xhr.response.length;
}
}
xhr2.open('GET', '/sse/retrieve');
xhr2.send(null);//发送请求
xhr2.onreadystatechange = function() {
console.log("s响应状态:" + xhr2.readyState);
//0: 请求未初始化,2 请求已接收,3 请求处理中,4 请求已完成,且响应已就绪
if (xhr2.readyState > 2) {
//这儿可以使用response(对应json)与responseText(对应text)
var newData1 = xhr2.response.substr(xhr2.seenBytes);
newData1 = newData1.replace(/\n/g, "#");
newData1 = newData1.substring(0, newData1.length - 1);
var data1 = newData1.split("#");
console.log("获取到的数据:" + data1);
document.getElementById("data").innerHTML = data1;
//长度重新赋值,下次截取时需要使用
xhr2.seenBytes = xhr2.response.length;
}
}<