Spring 整合 WebSocket

朱雀 2020-10-18 12:11 1155阅读 0赞

WebSocket是什么?

WebSocket 是基于TCP的一种网络通信协议。它实现了浏览器与服务器全双工通信——允许服务器主动发送信息给客户端。

为什么需要WebSocket ?

HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理,无法实现服务器主动向客户端发起消息。注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数 Web 应用程序将通过频繁的异步AJAX请求实现长轮询。轮询的效率低,非常浪费资源。

WebSocket如何工作?

Web浏览器和服务器都必须实现 WebSocket协议来建立和维护连接。由于WebSocket连接长期存在,与典型的HTTP连接不同,对服务器有重要的影响。

WebSocket服务端

采用javax.websocket实现

添加maven依赖

  1. <dependency>
  2. <groupId>javax.websocket</groupId>
  3. <artifactId>javax.websocket-api</artifactId>
  4. <version>1.1</version>
  5. <scope>provided</scope>
  6. </dependency>

定义websocket服务器端

  1. import java.io.IOException;
  2. import java.util.concurrent.CopyOnWriteArraySet;
  3. import javax.websocket.OnClose;
  4. import javax.websocket.OnError;
  5. import javax.websocket.OnMessage;
  6. import javax.websocket.OnOpen;
  7. import javax.websocket.Session;
  8. import javax.websocket.server.ServerEndpoint;
  9. /** * The Apache License 2.0 * Copyright (c) 2018 sep6th * * @ServerEndpoint 注解是一个类层次的注解, * 它的功能主要是将目前的类定义成一个websocket服务器端, * 注解的值将被用于监听用户连接的终端访问URL地址, * 客户端可以通过这个URL来连接到WebSocket服务器端 */
  10. @ServerEndpoint("/websocket")
  11. public class WebSocketServe {
  12. //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
  13. private static int onlineCount = 0;
  14. //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
  15. //若要实现服务端与单一客户端通信的话,可以使用Map(ConcurrentMap)来存放,其中Key可以为用户标识
  16. public static CopyOnWriteArraySet<WebSocketServe> webSocketSet = new CopyOnWriteArraySet<WebSocketServe>();
  17. //与某个客户端的连接会话,需要通过它来给客户端发送数据
  18. private Session session;
  19. /** * 连接建立成功调用的方法 * * @param session 可选的参数。 * session为与某个客户端的连接会话,需要通过它来给客户端发送数据 */
  20. @OnOpen
  21. public void onOpen(Session session) {
  22. this.session = session;
  23. webSocketSet.add(this); //加入set中
  24. addOnlineCount(); //在线数加1
  25. System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
  26. }
  27. /** * 连接关闭调用的方法 */
  28. @OnClose
  29. public void onClose() {
  30. webSocketSet.remove(this); //从set中删除
  31. subOnlineCount(); //在线数减1
  32. System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
  33. }
  34. /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息 * @param session 可选的参数 */
  35. @OnMessage
  36. public void onMessage(String message, Session session) {
  37. System.out.println("来自客户端的消息:" + message);
  38. //群发消息
  39. for (WebSocketServe item : webSocketSet) {
  40. try {
  41. item.sendMessage(message);
  42. } catch (IOException e) {
  43. e.printStackTrace();
  44. continue;
  45. }
  46. }
  47. }
  48. /** * 发生错误时调用 */
  49. @OnError
  50. public void onError(Session session, Throwable error) {
  51. System.out.println("发生错误");
  52. error.printStackTrace();
  53. }
  54. /** * 发送消息 */
  55. public void sendMessage(String msg) throws IOException {
  56. this.session.getBasicRemote().sendText(msg);
  57. }
  58. /** * 自定义消息发送 */
  59. public void sendMsg(String msg) {
  60. for (WebSocketServe item : webSocketSet) {
  61. try {
  62. item.sendMessage(msg);
  63. } catch (IOException e) {
  64. e.printStackTrace();
  65. continue;
  66. }
  67. }
  68. }
  69. public static synchronized int getOnlineCount() {
  70. return onlineCount;
  71. }
  72. public static synchronized void addOnlineCount() {
  73. WebSocketServe.onlineCount++;
  74. }
  75. public static synchronized void subOnlineCount() {
  76. WebSocketServe.onlineCount--;
  77. }
  78. }

WebSocket客户端

  1. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  3. <html>
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  6. <title>Insert title here</title>
  7. <body>
  8. Welcome<br/><input id="text" type="text"/>
  9. <button onclick="send()">发送消息</button>
  10. <hr/>
  11. <button onclick="closeWebSocket()">关闭WebSocket连接</button>
  12. <hr/>
  13. <div id="message"></div>
  14. <table id="tb" class="altrowstable">
  15. <th align="center" colspan="9">实时信息监控</th>
  16. </table>
  17. </body>
  18. <script type="text/javascript"> var websocket = null; //判断当前浏览器是否支持WebSocket if ('WebSocket' in window) { websocket = new WebSocket("ws://localhost:8090/websocket"); } else { alert('当前浏览器 Not support websocket') } //连接发生错误的回调方法 websocket.onerror = function () { setMessageInnerHTML("WebSocket连接发生错误"); }; //连接成功建立的回调方法 websocket.onopen = function () { setMessageInnerHTML("WebSocket连接成功"); } //接收到消息的回调方法 websocket.onmessage = function (event) { setMessageInnerHTML(event.data); } //连接关闭的回调方法 websocket.onclose = function () { setMessageInnerHTML("WebSocket连接关闭"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function () { closeWebSocket(); } //将消息显示在网页上 function setMessageInnerHTML(innerHTML) { var msg=innerHTML.split(" - ") var table=document.getElementById("tb"); var row; row=table.insertRow(1); for(var i=0;i<msg.length;i++){ var cell = row.insertCell(i); cell.appendChild(document.createTextNode(msg[i])); } if(table.rows.length>50){ table.deleteRow(table.rows.length-1); } } //关闭WebSocket连接 function closeWebSocket() { websocket.close(); } //发送消息 function send() { var message = document.getElementById('text').value; websocket.send(message); } </script>
  19. </html>

拓展——http协议

HTTP是一个基于TCP/IP通信协议来传递数据,是一种无状态的无连接的单向的应用层协议。
主要特点
1.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
2.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
3.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
4.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
5.支持B/S及C/S模式

发表评论

表情:
评论列表 (有 0 条评论,1155人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Spring 整合 WebSocket

    WebSocket是什么? WebSocket 是基于TCP的一种网络通信协议。它实现了浏览器与服务器全双工通信——允许服务器主动发送信息给客户端。 为什么需要WebS...