[关闭]
@File 2019-10-29T01:05:58.000000Z 字数 4381 阅读 142

spring-websocket 长连接

java


服务器搭建

一、依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-websocket</artifactId>
  4. </dependency>

二、config 配置

  1. @Configuration
  2. public class WebSocketConfig {
  3. @Bean
  4. public ServerEndpointExporter serverEndpointExporter() {
  5. return new ServerEndpointExporter();
  6. }
  7. }

三、websocket 服务器配置

  1. @Component
  2. // 指定 websocker 映射的url路径
  3. @ServerEndpoint("/webSocket")
  4. public class MyWebSocket {
  5. /**
  6. * 记录当前在线连接数。
  7. */
  8. private static final AtomicInteger onlineCount = new AtomicInteger(0);
  9. /**
  10. * 存放每个客户端对应的MyWebSocket对象。
  11. */
  12. private static ConcurrentHashMap<String,MyWebSocket> webSocketMap = new ConcurrentHashMap<>();
  13. /**
  14. * 当前客户端的连接对象
  15. */
  16. private Session session;
  17. /**
  18. * 连接建立成功调用的方法
  19. * @param session 连接的客户端信息
  20. */
  21. @OnOpen
  22. public void onOpen(Session session) {
  23. this.session = session;
  24. // 加入set中
  25. webSocketMap.put(session.getId(), this);
  26. // 在线数加1
  27. addOnlineCount();
  28. // 广播通知
  29. sendAll("有新用户连接,id:"+session.getId());
  30. }
  31. /**
  32. * 连接关闭调用的方法
  33. * @param session 断开连接的客户端信息
  34. */
  35. @OnClose
  36. public void onClose(Session session) {
  37. // 从map中删除
  38. webSocketMap.remove(session.getId());
  39. // 在线数减1
  40. subOnlineCount();
  41. // 广播退出信息
  42. sendAll("id:"+session.getId()+" 用户退出了");
  43. }
  44. /**
  45. * 收到客户端消息后调用的方法
  46. * @param message 客户端发送过来的消息
  47. * @param session 发信息的客户端信息
  48. */
  49. @OnMessage
  50. public void onMessage(String message, Session session) {
  51. // 客户端发信息逻辑
  52. // 信息中是否带冒号
  53. int index = message.indexOf(':');
  54. if(index > 0){
  55. String sendId = message.substring(0, index);
  56. if(sendId != ""){
  57. try {
  58. // 带冒号时根据冒号前的id单独发送
  59. sendToId(sendId, message.substring(index+1));
  60. return;
  61. }catch (Exception e){
  62. }
  63. }
  64. }
  65. // 没带冒号就广播
  66. sendAll(message);
  67. }
  68. /**
  69. * 发生错误时调用
  70. * @param error 错误信息
  71. * @param session 客户端信息
  72. */
  73. @OnError
  74. public void onError(Throwable error, Session session) {
  75. error.printStackTrace();
  76. }
  77. /**
  78. * 当前客户端发布消息
  79. * @param message 消息
  80. * @throws IOException
  81. */
  82. public void sendMessage(String message) throws IOException {
  83. session.getBasicRemote().sendText(message);
  84. }
  85. /**
  86. * 群发自定义消息
  87. * @param message 广播
  88. */
  89. public static void sendAll(String message) {
  90. webSocketMap.forEach((key, myWebSocket) -> {
  91. try {
  92. myWebSocket.sendMessage(message);
  93. } catch (IOException e) {
  94. e.printStackTrace();
  95. }
  96. });
  97. }
  98. /**
  99. * 发送给指定id的客户端
  100. * @param id 客户端id
  101. * @param message 消息
  102. */
  103. public static void sendToId(String id, String message) {
  104. try {
  105. webSocketMap.get(id).sendMessage(message);
  106. } catch (IOException e) {
  107. e.printStackTrace();
  108. }
  109. }
  110. /**
  111. * 获取总连接数
  112. * @return 总连接数
  113. */
  114. public static synchronized int getOnlineCount() {
  115. return onlineCount.get();
  116. }
  117. /**
  118. * 连接数 +1
  119. * @return +1 后的连接数
  120. */
  121. public static synchronized int addOnlineCount() {
  122. return onlineCount.addAndGet(1);
  123. }
  124. /**
  125. * 连接数 -1
  126. * @return -1 后的连接数
  127. */
  128. public static synchronized int subOnlineCount() {
  129. return onlineCount.decrementAndGet();
  130. }
  131. }

四、前端测试页面(可用客户端代替)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>My WebSocket Test</title>
  6. </head>
  7. <body>
  8. Welcome<br/>
  9. <input id="text" type="text" />
  10. <button onclick="send()">Send</button>
  11. <button onclick="closeWebSocket()">Close</button>
  12. <div id="message">
  13. </div>
  14. </body>
  15. <script type="text/javascript">
  16. var websocket = null;
  17. //判断当前浏览器是否支持WebSocket
  18. if('WebSocket' in window){
  19. websocket = new WebSocket("ws://localhost:8080/webSocket");
  20. }
  21. else{
  22. alert('Not support websocket')
  23. }
  24. //连接发生错误的回调方法
  25. websocket.onerror = function(){
  26. setMessageInnerHTML("error");
  27. };
  28. //连接成功建立的回调方法
  29. websocket.onopen = function(event){
  30. setMessageInnerHTML("open");
  31. }
  32. //接收到消息的回调方法
  33. websocket.onmessage = function(event){
  34. setMessageInnerHTML(event.data);
  35. }
  36. //连接关闭的回调方法
  37. websocket.onclose = function(){
  38. setMessageInnerHTML("close");
  39. }
  40. //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
  41. window.onbeforeunload = function(){
  42. websocket.close();
  43. }
  44. //将消息显示在网页上
  45. function setMessageInnerHTML(innerHTML){
  46. document.getElementById('message').innerHTML += innerHTML + '<br/>';
  47. }
  48. //关闭连接
  49. function closeWebSocket(){
  50. websocket.close();
  51. }
  52. //发送消息
  53. function send(){
  54. var message = document.getElementById('text').value;
  55. websocket.send(message);
  56. }
  57. </script>
  58. </html>

客户端搭建

一、依赖

  1. <dependency>
  2. <groupId>org.java-websocket</groupId>
  3. <artifactId>Java-WebSocket</artifactId>
  4. <version>1.3.8</version>
  5. </dependency>

二、重写 WebSocketClient

  1. public class MyWebSocketClient extends WebSocketClient {
  2. public MyWebSocketClient(String serverUri) throws URISyntaxException {
  3. // 配置连接地址
  4. super(new URI(serverUri));
  5. // 实例化时立即创建连接
  6. this.connect();
  7. }
  8. /**
  9. * 连接成功时
  10. * @param serverHandshake
  11. */
  12. @Override
  13. public void onOpen(ServerHandshake serverHandshake) {
  14. // 成功连接逻辑
  15. }
  16. /**
  17. * 接收到信息时
  18. * @param s 信息内容
  19. */
  20. @Override
  21. public void onMessage(String s) {
  22. // 收信息时逻辑
  23. }
  24. /**
  25. * 关闭连接是
  26. * @param i
  27. * @param s
  28. * @param b
  29. */
  30. @Override
  31. public void onClose(int i, String s, boolean b) {
  32. // 断开时逻辑
  33. }
  34. /**
  35. * 出现错误时
  36. * @param e 错误对象
  37. */
  38. @Override
  39. public void onError(Exception e) {
  40. // 异常处理逻辑
  41. }
  42. }

三、发消息

  1. // 实例化刚重写的类,这里有个异常需要处理
  2. WebSocketClient webSocketClient = new MyWebSocketClient("ws://localhost:8080/webSocket");
  3. // 向服务器发送消息
  4. webSocketClient.send("发送信息");

参考连接:https://blog.csdn.net/ffj0721/article/details/82630134

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注