当前位置:   article > 正文

springboot(十一)WebSocket实现前后端消息推送_websocket 推送消息前后端

websocket 推送消息前后端

概述:

         WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocketAPI也被W3C定为标准。

          WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。 

 

优点:

  • 较少的控制开销。在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小。在不包含扩展的情况下,对于服务器到客户端的内容,此头部大小只有2至10字节(和数据包长度有关);对于客户端到服务器的内容,此头部还需要加上额外的4字节的掩码。相对于HTTP请求每次都要携带完整的头部,此项开销显著减少了。

  • 更强的实时性。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少;即使是和Comet等类似的长轮询比较,其也能在短时间内更多次地传递数据。

  • 保持连接状态。与HTTP不同的是,Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。而HTTP请求可能需要在每个请求都携带状态信息(如身份认证等)。

  • 更好的二进制支持。Websocket定义了二进制帧,相对HTTP,可以更轻松地处理二进制内容。

  • 可以支持扩展。Websocket定义了扩展,用户可以扩展协议、实现部分自定义的子协议。如部分浏览器支持压缩等。

  • 更好的压缩效果。相对于HTTP压缩,Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率。

 

握手协议:

      WebSocket 是独立的、创建在 TCP 上的协议。

      Websocket 通过HTTP/1.1 协议的101状态码进行握手。

      为了创建Websocket连接,需要通过浏览器发出请求,之后服务器进行回应,这个过程通常称为“握手”(handshaking)。

 

springboot集成websocket:

  新建项目:springboot-webservice,pom.xml

  1. <dependencies>
  2. <!--websocket-->
  3. <dependency>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-starter-websocket</artifactId>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-starter-test</artifactId>
  10. <scope>test</scope>
  11. </dependency>
  12. <!--thymeleaf-->
  13. <dependency>
  14. <groupId>org.springframework.boot</groupId>
  15. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  16. </dependency>
  17. <!--lombok-->
  18. <dependency>
  19. <groupId>org.projectlombok</groupId>
  20. <artifactId>lombok</artifactId>
  21. <version>1.16.22</version>
  22. </dependency>
  23. </dependencies>

新建配置类, 开启WebSocket支持:WebSocketConfig.java

  1. /**
  2. * 开启WebSocket支持
  3. **/
  4. @Configuration
  5. public class WebSocketConfig {
  6. @Bean
  7. public ServerEndpointExporter serverEndpointExporter() {
  8. return new ServerEndpointExporter();
  9. }
  10. }

新建WebSocketServer服务端:WebSocket.java

  1. @ServerEndpoint("/websocket")
  2. @Component
  3. @Slf4j
  4. public class WebSocket {
  5. //与某个客户端的连接会话,需要通过它来给客户端发送数据
  6. private Session session;
  7. //concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。
  8. private static CopyOnWriteArraySet<WebSocket> webSocketSet=new CopyOnWriteArraySet<>();
  9. /**
  10. * 建立连接成功
  11. * @param session
  12. */
  13. @OnOpen
  14. public void onOpen(Session session){
  15. this.session=session;
  16. webSocketSet.add(this);
  17. log.info("【websocket消息】 有新的连接,总数{}",webSocketSet.size());
  18. }
  19. /**
  20. * 连接关闭
  21. */
  22. @OnClose
  23. public void onClose(){
  24. this.session=session;
  25. webSocketSet.remove(this);
  26. log.info("【websocket消息】 连接断开,总数{}",webSocketSet.size());
  27. }
  28. /**
  29. * 接收客户端消息
  30. * @param message
  31. */
  32. @OnMessage
  33. public void onMessage(String message){
  34. log.info("【websocket消息】 收到客户端发来的消息:{}",message);
  35. }
  36. /**
  37. * 发送消息
  38. * @param message
  39. */
  40. public void sendMessage(String message){
  41. log.info("【websocket消息】 发送消息:{}",message);
  42. for (WebSocket webSocket:webSocketSet){
  43. try {
  44. webSocket.session.getBasicRemote().sendText(message);
  45. } catch (IOException e) {
  46. e.printStackTrace();
  47. }
  48. }
  49. }
  50. }

         注:@ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端。注解的值将被用于监听用户连接的终端访问URL地址。

                onOpen 和 onClose 方法分别被@OnOpen和@OnClose 所注解。这两个注解的作用不言自明:他们定义了当一个新用户连接和断开的时候所调用的方法。

                onMessage 方法被@OnMessage所注解。这个注解定义了当服务器接收到客户端发送的消息时所调用的方法。

 

编写index.html文件来测试通讯:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <title></title>
  6. </head>
  7. <body>
  8. <input type="text" id="name" /><button onclick="send()">发送消息</button>
  9. </body>
  10. <script>
  11. var websocket = null;
  12. //判断浏览器是否支持websocket
  13. if('WebSocket' in window) {
  14. //实现化WebSocket对象
  15. websocket = new WebSocket("ws://localhost:8080/websocket");
  16. } else {
  17. alert('该浏览器不支持websocket')
  18. }
  19. //打开事件
  20. websocket.onopen = function(event) {
  21. console.log('建立连接');
  22. }
  23. //关闭事件
  24. websocket.onclose = function(event) {
  25. console.log("连接关闭");
  26. }
  27. //获得消息事件
  28. websocket.onmessage = function(event) {
  29. console.log("收到消息:" + event.data);
  30. }
  31. //发生了错误事件
  32. websocket.onerror = function(event) {
  33. console.log("websocket 通信发生错误");
  34. }
  35. window.onbeforeunload = function(event) {
  36. websocket.close();
  37. }
  38. //发送消息
  39. function send() {
  40. var message = document.getElementById('name').value;
  41. websocket.send(message);
  42. }
  43. </script>
  44. </html>

编写访问接口模仿服务端消息推送场景:

  1. @Controller
  2. public class TestController {
  3. @Resource
  4. private WebSocket webSocket;
  5. /**
  6. * 页面文件入口
  7. */
  8. @GetMapping("/index")
  9. public String index(){
  10. return "index";
  11. }
  12. /**
  13. * 发送场景模拟
  14. * @param msg
  15. * @return
  16. */
  17. @GetMapping("/test")
  18. @ResponseBody
  19. public String sendMessage(String msg){
  20. //如果访问的地址中msg参数不为空值,发送msg的值给前端
  21. if(!StringUtils.isEmpty(msg)){
  22. webSocket.sendMessage(msg);
  23. return "服务端发送消息msg:"+msg;
  24. }
  25. return "服务端未发送消息msg:"+msg;
  26. }
  27. }

 

测试:

    启动项目。首先我们先测试客户端发送消息。访问:localhost:8080/index,浏览器控制台与后台控制台:

如果你再开浏览器窗口访问,连接总数就会跟着变话。接下来我们发送一条消息:

 

测试服务端发送消息:访问:localhost:8080/test,未带msg参数,websocket无变化:

带入msg参数访问(注意你的页面别关闭哦!)

最后具体应用场景还得根据业务来定!

 

源码地址https://gitee.com/xu0123/springboot2

上一篇:springboot(十)集成CXF发布webservice以及客户端调用

下一篇:springboot(十二)AOP的使用

 

 

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

闽ICP备14008679号