乐趣区

关于websocket:个人学习系列-WebSocket与Spring-Boot整合

WebSocket 是一种网络通信协定。它与 HTTP 协定最大的不同在于,HTTP 协定做不到服务器被动向客户端推送信息。

WebSocket

其最大的特点在于:服务器能够被动向客户端推送信息,客户端也能够被动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

Spring Boot 我的项目搭建

后面的步骤就不再赘述了,咱们间接从 pom.xml 外面增加的依赖开始吧。

1. pom.xml 文件配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

2. application.yml 配置

server:
  port: 8888
spring:
  freemarker:
    prefix: classpath:/templates/
    suffix: .html

3. index.html 页面

<!DOCTYPE html>
<html>
<head>
    <title>WebSoket Demo</title>
    <script type="text/javascript">
        // 验证浏览器是否反对 WebSocket 协定
        if (!window.WebSocket) {alert("WebSocket not supported by this browser!");
        }
        let ws;

        const log = function (s) {if (document.readyState !== "complete") {log.buffer.push(s);
            } else {document.getElementById("contentId").innerHTML += (s + "\n");
            }
        };

        function display() {ws = new WebSocket("ws://localhost:8888/websocket");
            ws.onmessage = function (event) {
                // 监听音讯
                log(event.data);
            };
            ws.onclose = function (event) {
                // 敞开 WebSocket
                console.log("ws close:" + event);
            };
            ws.onopen = function (event) {
                // 关上 WebSocket
                console.log("ws open:" + event);
                // 发送一个初始化音讯
                ws.send("Hello, Server!");
            };
            ws.onerror = function (event) {
                // WebSocket 异样
                console.log("ws error:" + event);
            };
        }


        function sendMsg() {
            // 发送音讯
            const msg = document.getElementById("messageId");
            ws.send(msg.value);
        }
    </script>
</head>
<body onload="display();">
    <div id="valueLabel"></div>
    <textarea rows="20" cols="30" id="contentId"></textarea>
    <br/>
    <input name="message" id="messageId"/>
    <button id="sendButton" onClick="sendMsg()">Send</button>
</body>
</html>

4. 管制层

/**
 * 测试控制器
 * @author zhouzhaodong
 */
@Controller
public class TestController {@RequestMapping("/")
    public String view(){return "index";}

}

5. WebSocket 配置类

/**
 * WebSocket 配置类
 * @author zhouzhaodong
 */
@Configuration
public class WebsocketConfiguration {

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

}

6. WebSocket 服务端

/**
 * WebSocket 服务端
 * @author zhouzhaodong
 */
@ServerEndpoint("/websocket")
@Component
@Slf4j
public class MyWebsocketServer {

    /**
     * 寄存所有在线的客户端
     */
    private static final Map<String, Session> CLIENTS = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session) {log.info("有新的客户端连贯了: {}", session.getId());
        // 将新用户存入在线的组
        CLIENTS.put(session.getId(), session);
    }

    /**
     * 客户端敞开
     * @param session session
     */
    @OnClose
    public void onClose(Session session) {log.info("有用户断开了, id 为:{}", session.getId());
        // 将掉线的用户移除在线的组里
        CLIENTS.remove(session.getId());
    }

    /**
     * 产生谬误
     * @param throwable e
     */
    @OnError
    public void onError(Throwable throwable) {throwable.printStackTrace();
    }

    /**
     * 收到客户端发来音讯
     * @param message  音讯对象
     */
    @OnMessage
    public void onMessage(String message) {log.info("服务端收到客户端发来的音讯: {}", message);
        this.sendAll(message);
    }

    /**
     * 群发音讯
     * @param message 音讯内容
     */
    private void sendAll(String message) {for (Map.Entry<String, Session> sessionEntry : CLIENTS.entrySet()) {sessionEntry.getValue().getAsyncRemote().sendText(message);
        }
    }

}

7. 启动我的项目,拜访 http://localhost:8888/ 查看我的项目:

输出信息,点击 send 按钮后就会发送信息啦。

后端控制台打印信息如下:

程序源码地址:

https://github.com/zhouzhaodo…

集体博客:

http://www.zhouzhaodong.xyz

退出移动版