当前位置:   article > 正文

Js即时通讯技术 - SSE(SpringBoot实现)_js sse

js sse

目录

一、前言

二、SpringBoot实现

1.Controller

2.index.html

3.测试


一、前言

主流的Web端即时通讯方案大致有4种:传统Ajax短轮询、Comet技术、WebSocket技术、SSE(Server-sent Events)。

 Ajax短轮询CometWebSocketSSE
概念http端轮询是服务器收到请求不管是否有数据都直接响应 http 请求; 浏览器受到 http 响应隔一段时间在发送同样的http 请求查询是否有数据;http 长轮询是服务器收到请求后如果有数据, 立刻响应请求; 如果没有数据就会 hold 一段时间,这段时间内如果有数据立刻响应请求; 如果时间到了还没有数据, 则响应 http 请求;浏览器受到 http 响应后立在发送一个同样http 请求查询是否有数据;WebSocket的实现了一次连接,双方通信的功能。首先由客户端发出WebSocket请求,服务器端进行响应,实现类似TCP握手的动作。这个连接一旦建立起来,就保持在客户端和服务器之间,两者之间可以直接的进行数据的互相传送。在 sse 的场景下,客户端发起请求,连接一直保持,服务端有数据就可以返回数据给客户端,这个返回可以是多次间隔的方式。sse 是单通道,只能服务端向客户端发消息
协议httphttpwbSocket

http

 短轮询长轮询  

 

 

 

 

 

二、SpringBoot实现

1.Controller

使用接口模拟发送消息

  1. package com.asyf.demo.controller;
  2. import cn.hutool.core.date.DateUtil;
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RequestMethod;
  7. import org.springframework.web.bind.annotation.ResponseBody;
  8. import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
  9. import java.io.IOException;
  10. import java.util.Date;
  11. import java.util.Map;
  12. import java.util.concurrent.ConcurrentHashMap;
  13. @Controller
  14. @RequestMapping(path = "sse")
  15. public class SSEController {
  16. @GetMapping(path = "")
  17. public String index() {
  18. //index.html在static/index.html目录
  19. return "index.html";
  20. }
  21. @RequestMapping(value = "test", method = RequestMethod.GET)
  22. public Object test() {
  23. return DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
  24. }
  25. private static Map<String, SseEmitter> sseCache = new ConcurrentHashMap<>();
  26. @GetMapping(path = "subscribe")
  27. public SseEmitter push(String id) throws IOException {
  28. System.out.println(id);
  29. // 超时时间设置为1小时
  30. SseEmitter sseEmitter = new SseEmitter(3600_000L);
  31. // 设置前端的重试时间为1s
  32. sseEmitter.send(SseEmitter.event().reconnectTime(1000).data("连接成功"));
  33. sseCache.put(id, sseEmitter);
  34. sseEmitter.onTimeout(() -> sseCache.remove(id));
  35. sseEmitter.onCompletion(() -> System.out.println("完成!!!"));
  36. return sseEmitter;
  37. }
  38. @GetMapping(path = "push")
  39. @ResponseBody
  40. public String push(String id, String content) throws IOException {
  41. SseEmitter sseEmitter = sseCache.get(id);
  42. if (sseEmitter != null) {
  43. sseEmitter.send(content);
  44. }
  45. return "push over";
  46. }
  47. @GetMapping(path = "close")
  48. @ResponseBody
  49. public String over(String id) throws IOException {
  50. SseEmitter sseEmitter = sseCache.get(id);
  51. if (sseEmitter != null) {
  52. sseEmitter.send("close");
  53. sseEmitter.send(SseEmitter.event().name("close").id(id).data(""));
  54. sseEmitter.complete();
  55. sseCache.remove(id);
  56. }
  57. return "close over";
  58. }
  59. }

2.index.html

目录是resourses/static/index.html

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  5. <title>SSE测试</title>
  6. </head>
  7. <body>
  8. <div>sse测试</div>
  9. <div id="result"></div>
  10. </body>
  11. </html>
  12. <script>
  13. function msg(msg) {
  14. console.log(msg)
  15. var div = document.createElement('div');
  16. div.innerHTML = msg;
  17. document.getElementById('result').appendChild(div);
  18. }
  19. //判断浏览器是否支持SSE
  20. if (!!window.EventSource) {
  21. var source = new EventSource('http://localhost:8080/sse/subscribe?id=ssetest');
  22. //响应消息-实现方式1
  23. // source.onmessage = function (event) {
  24. // text = document.getElementById('result').innerText;
  25. // text += '\n' + event.data;
  26. // document.getElementById('result').innerText = text;
  27. // };
  28. //响应消息-实现方式2
  29. source.addEventListener('message', function (e) {
  30. msg(e.data);
  31. }, false);
  32. //响应open事件
  33. source.addEventListener('open', function (e) {
  34. msg("连接打开.");
  35. }, false);
  36. // 响应close事件,主动关闭EventSource
  37. //后端关闭SSE会执行error事件,在error事件中关闭SSE不友好,后端在关闭SSE发送close
  38. // 事件以友好的关闭SSE
  39. source.addEventListener('close', function (e) {
  40. source.close();
  41. console.log(e);
  42. msg("数据接收完毕,关闭EventSource");
  43. }, false);
  44. //响应error事件
  45. source.addEventListener('error', function (e) {
  46. if (e.readyState == EventSource.CLOSED) {
  47. msg("连接关闭");
  48. } else {
  49. console.log(e);
  50. }
  51. }, false);
  52. } else {
  53. console.log("你的浏览器不支持SSE");
  54. msg("你的浏览器不支持SSE");
  55. }
  56. </script>

3.测试

首页:http://localhost:8080/sse

发送消息:http://localhost:8080/sse/push?id=ssetest&content=%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE

关闭连接:http://localhost:8080/sse/close?id=ssetest

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/849924
推荐阅读
相关标签
  

闽ICP备14008679号