SSE实现后端向前页面推送实时数据,是长链接不是连接一次就断开
SSE实现后端向前页面推送实时数据-修改版欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入
·
新接触sse,从网上找了好多资料都是在后端retuen数据给页面,这样导致了页面的长链接就断开了,然后我就改了下它,如果有其他更简便的方式,请大佬们告诉我
直接上代码
后端接口:
后端我是集成了swagger页面,然后通过swagger调用接口给statusMap中更改用户Id的状态,前端页面就能实时显示了
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
/**
* @author Administrator
* @Title: SSEController
* @ProjectName project_back
* @Description: TODO
* @date 2019/10/249:38
*/
@RestController
@RequestMapping("/SSEController")
@Api(tags = "sse服务")
public class SSEController {
//produces = "text/event-stream;charset=UTF-8"一定要带上
static Map<String,HttpServletResponse> responseMap = new HashMap<>();
static Map<String,String> statusMap = new HashMap<>();
@ApiOperation("开启sse服务")
@GetMapping(value = "/get_data", produces = "text/event-stream;charset=UTF-8")
public void push(@RequestParam(name = "userId")String userId,HttpServletResponse response){
System.out.println("调用开启连接的接口!====");
responseMap.put(userId,response);
try {
while (true){
Thread.sleep(100);
//数据格式必须为下面这种格式,"data:"+你的数据+"\n\n"; "data"还有其他的格式, “data”, “event”, “id”,“retry”,
String data = "data:" + userId + "的状态为:"+ getStatus(userId) + "\n\n";
if (null != responseMap.get(userId)){
response.setHeader("Content-Type", "text/event-stream;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.print(data);
writer.flush();
}else {
break;
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
System.out.println("sse连接已断开");
}
@ApiOperation("发送数据")
@PostMapping("/send")
public void send(@RequestParam(name = "userId")String userId,@RequestParam(name = "status")String status) {
statusMap.put(userId,status);
}
@ApiOperation("关闭连接")
@GetMapping("/close")
public void close(@RequestParam(name = "userId")String userId) {
System.out.println("调用连接关闭接口!!!==============");
responseMap.remove(userId);
}
public String getStatus(String userId){
String status = statusMap.get(userId);
if (null == status){
status = "空";
}
return status;
}
}
前端页面使用的html:
运行的时候使用nginx代理的页面
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script type="text/javascript">
//需要判断浏览器支不支持,可以去w3c进行查看
//关闭页面时触发的方法,关闭长链接
window.onbeforeunload = function(){
closeo();
};
var source = new EventSource('http://localhost:8080/SSEController/get_data?userId=1111111111');
source.readyState;
// EventSource.CLOSED
source.onmessage = function (event) {
console.info(event.data);
document.getElementById('result').innerText = event.data
};
source.onopen = function () {
console.info("链接已经打开");
};
source.onerror = function () {
console.info("连接出错");
};
function openo(){
console.info("正在打开连接")
source = new EventSource('http://localhost:8080/SSEController/get_data?userId=1111111111');
};
function closeo(){
console.info("断开链接");
source.close();
$.ajax({
type: "GET",
url: "http://localhost:8080/SSEController/close?userId=1111111111",
data: '',
dataType: "JSON",
success: function(ret) {
}
});
};
</script>
</head>
<body>
<div id="result">
</div>
<div>
<button onclick="closeo()">断开</button>
<button onclick="openo()">重新连接</button>
</div>
</body>
</html>
页面效果:

我这种方式是根据前端调用接口来控制长链接的连接和断开,现在就是有个问题,我接口使用的HttpServletResponse给页面返回数据,但是我想写成异步的方式时HttpServletResponse就报空指针,大佬们有没有新的方式,我觉得这种方式比较low…
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)