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/查看项目:

图片.png

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

后端控制台打印信息如下:
图片.png

程序源码地址:

https://github.com/zhouzhaodong/springboot/tree/master/websocket

上一篇 下一篇