简单的websocket demo

使用websocket有两种方式:1是使用sockjs,2是使用h5的标准。使用Html5标准自然更方便简单,所以记录的是配合h5的使用方法。

  1. pom

    <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
  2. 使用@ServerEndpoint创立websocket endpoint
      首先要注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。要注意,如果使用独立的servlet容器,而不是直接使用springboot的内置容器,就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理。

    @Configuration
    public class WebSocketConfig {
    
     @Bean
     public ServerEndpointExporter serverEndpointExporter(){
         return new ServerEndpointExporter();
     }
    }

    接下来就是写websocket的具体实现类,直接上代码:

    @Component
    @ServerEndpoint("/websocket")
    public class MyWebSocket {
     //与某个客户端的连接会话,需要通过它来给客户端发送数据
     private Session session;
     //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
     private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<MyWebSocket>();
    
     @OnOpen
     public void onOpen(Session session){
         this.session = session;
         webSocketSet.add(this);
         System.out.println("创建连接:第"+webSocketSet.size());
     }
    
     @OnClose
     public void onClose(){
         webSocketSet.remove(this);
         System.out.println("关闭连接");
     }
    
     @OnMessage
     public void onMessage(String message){
         System.out.println("接受客户端消息:"+message);
     }
    
     /**
      * 群发消息
      */
     public void sendMessage(String message){
         for (MyWebSocket myWebSocket : webSocketSet){
             try {
                 myWebSocket.session.getBasicRemote().sendText(message);
             } catch (IOException e) {
                 e.printStackTrace();
             }
         }
     }
     //单发消息可以在群发的基础上改造
    }

    使用springboot的唯一区别是要@Component声明下,而使用独立容器是由容器自己管理websocket的,但在springboot中连容器都是spring管理的。
    虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。

  3. 前端代码

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
     <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" />
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>主页</title>
    </head>
    <body>
    <script type="text/javascript" th:inline="javascript">
     var websocket = null;
     if('WebSocket' in window){
         //127.0.0.1:8080 是的项目请求地址 websocket是对应@ServerEndpoint("/websocket")里的值 合起来就是请求websocket地址
         websocket = new WebSocket('ws://127.0.0.1:8080/websocket');
     }else{
         alert("该浏览器不支持websocket!")
     }
     websocket.onopen = function (event) {
         console.log("建立连接");
     }
     websocket.onclose = function (event) {
         console.log("关闭连接");
     }
     websocket.onmessage = function (event) {
         console.log("接受消息:"+event.data);
         //模拟发送信息给服务端
         websocket.send("我已经接受到信息啦!")
     }
     websocket.onerror = function (event) {
         console.log("出现了错误")
     }
     window.onbeforeunload = function () {
         websocket.onclose();
     }
    </script>
    </body>
    </html>
  4. 测试方法

    @RestController
    @RequestMapping("/testWebSocketSend")
    public class TestWebSocketSendController {
     @Autowired
     private MyWebSocket myWebSocket;
     @GetMapping("send")
     public String send(@RequestParam("message") String message){
         //todo 其他业务
         //websocket服务
         myWebSocket.sendMessage(message);
         return "成功";
     }
    }

    打开主页面 127.0.0.1:8080/index.html
    建立连接
    浏览器请求127.0.0.1:8080/testWebSocketSend/se... 我之前写的controller地址
    接受服务端发来的消息
    服务端接受客户端的消息打印
    服务端接受客户端的消息

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!