前言:

近日,项目开发中需要用到客户端扫码登录,第一时间想到了几种方案:

  1. Ajax轮询
  2. 长连接
  3. WebSocket

其中的优缺点想必我不用多说小伙伴们也清楚,既然来到这里,一定是想找到SpringBoot使用WebSocket的解决方案,首先说下我的环境:JDK 1.8,Tomcat 8.5,Spring Boot 2.0.1。好了,话不多说,开始吧!


后端:



第一步:添加依赖

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

第二步:编写WebSocket配置类

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {

        // 注册一个 stomp 终端(这个路径待会js里面会用到)
        // 如果需要跨域,在addEndpoint后面调用 setAllowedOrigins("*")
        registry.addEndpoint("/myEndpoint").withSockJS();

    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {

        // 注册多个(参数是可变参数)服务端接收消息前缀(这个路径待会js里面也会用到)
        registry.setApplicationDestinationPrefixes("/receiver");

        // 注册多个(参数是可变参数)服务端发送消息前缀(这个路径待会js里面会结合实现类路径用到)
        registry.enableSimpleBroker("/queueSender", "/topicSender");

    }

}

第三步:编写消息接收/发送实现类

@Slf4j
@Controller
public class WebSocketTestController {

    /**
     * 收到消息并推送给 发送人
     *
     * @param message 浏览器端发送的参数
     * @return 浏览器端接收的内容
     */
    @MessageMapping("/testQueueSend")
    @SendToUser("/queueSender/queueSend")
    public String testReceiveAndQueueSend(String message) {
        log.debug("{} 收到消息: {}", "testReceiveAndQueueSend", message);
        return "收到了消息" + message + ",并且发送给了发送人";
    }

    /**
     * 收到消息并推送给 所有人
     *
     * @param message 浏览器端发送的参数
     * @return 浏览器端接收的内容
     */
    @MessageMapping("/testTopicSend")
    @SendTo("/topicSender/topicSend")
    public String testReceiveAndTopicSend(String message) {
        log.debug("{} 收到消息: {}", "testReceiveAndTopicSend", message);
        return "收到了消息" + message + ",并且发送给了所有人";
    }

}
前端:

第一步及最后一步:ctrl+c, ctrl+v,请看代码

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>WebSocket测试</title>
    <script src="http://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
    <script src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
    <script src="http://code.jquery.com/jquery-3.3.1.min.js"></script><!-- 请注意IE浏览器兼容性 -->
</head>
<body>

<input id="input_queue_send" type="text" placeholder="输入消息进行发送"/>
<button οnclick="queueSend()">发送(将收到一对一消息)</button>
<br/>

<input id="input_topic_send" type="text" placeholder="输入消息进行发送"/>
<button οnclick="topicSend()">发送(将收到广播消息)</button>
<br/>

<button οnclick="unSubscription()">取消消息订阅</button>
<button οnclick="disconnectWebSocket()">关闭连接</button>
<br/>
<hr/>
<div id="message_box">
</div>
<script type="application/javascript">

    // 定义一个sock连接(并没有进行连接),url和服务端定义的stomp终端是一致的
    var _sockJS = new SockJS("/myEndpoint");

    // 创建一个客户端对象
    var _stompClient = Stomp.over(_sockJS);

    // 连接服务端(参数依次为 header,success,error)
    _stompClient.connect({}, function () {
        printLog("WebSocket已连接!");
        // 订阅服务端发送的消息,用于接收消息
        doSubscribeQueue();
    }, function () {
        printLog("WebSocket连接失败!")
    });

    // 订阅消息对象,用于关闭订阅
    var _subscribeQueue, _subscribeTopic;

    // 参数依次为 订阅地址,收到消息做什么,header
    function doSubscribeQueue() {
        // 一对一消息(注意url前面需要加上/user)
        _subscribeQueue = _stompClient.subscribe("/user/queueSender/queueSend", function (data) {
            printLog("收到 一对一消息 " + data.body);
        }, {});
        printLog("已订阅 一对一消息");

        // 广播消息
        _subscribeTopic = _stompClient.subscribe("/topicSender/topicSend", function (data) {
            printLog("收到 广播消息 :" + data.body);
        }, {});
        printLog("已订阅 广播消息");
    }

    // 断开WebSocket连接
    function disconnectWebSocket() {
        if (_stompClient != null) {
            _stompClient.disconnect();
            printLog("WebSocket连接已断开!")
        }
    }

    // 取消订阅消息
    function unSubscription() {
        if (_subscribeQueue) {
            _subscribeQueue.unsubscribe();
        }
        if (_subscribeTopic) {
            _subscribeTopic.unsubscribe();
        }
        printLog("取消订阅消息");
    }

    // 向服务器发送消息(服务器将发送给发送者)
    function queueSend() {
        var message = $("#input_queue_send").val();
        // 参数依次为 发送地址,header,消息
        _stompClient.send("/receiver/testQueueSend", {}, message);
        printLog("发送 一对一消息 " + message);
    }

    // 向服务器发送消息(服务器将广播给所有客户端)
    function topicSend() {
        var message = $("#input_topic_send").val();
        // 参数依次为 发送地址,header,消息
        _stompClient.send("/receiver/testTopicSend", {}, message);
        printLog("发送 广播消息 " + message);
    }

    function printLog(log) {
        console.log(log);
        $("#message_box").append("<div>" + log + "</div>");
    }

</script>
</body>
</html>

好了,文章到此结束,快去试下吧!