SpringBoot WebSocket Stomp

關注 “弋凡”(YiFan)微信公衆號吧 記錄簡單筆記 做你的最愛

websocket 是什麼?

是一種網絡通信協議,很多高級功能都需要它

爲什麼要使用websocket?

已經有了HTTP協議 爲撒還需要使用WebSocket 嘞?

HTTP 是客戶端請求服務端響應數據,但是我們如果想服務端給客戶端發送消息嘞?

於是乎就有了這種協議,客戶端,服務端可以雙向發送消息

最典型的就是聊天系統

stomp

stomp 既 Simple (or Streaming) Text Orientated Messaging Protocol

簡單(流)文本定向消息協議

爲什麼需要stomp?

常規的websocket連接和普通的TCP基本上沒區別

所以STOMP在websocket上提供了一中基於幀線路格式(frame-based wire format)

簡單一點,就是在我們的websocket(TCP)上面加了一層協議,使雙方遵循這種協議來發送消息
在這裏插入圖片描述
服務端:/app,這裏訪問服務端,前綴通過設定的方式訪問

用戶:/user,這裏針對的是用戶消息的傳遞,針對於當前用戶進行傳遞。

其他消息:/topic、/queue,這兩種方式。都是定義出來用於訂閱服務端

SpringBoot WebSocket 案例

導入pom依賴

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

websocket配置 - WebSocketConfig

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    // 基於STOMP協議的WebSocket

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 註冊一個websocket端點,客戶端將使用它連接到我們的websocket服務器。
        registry.addEndpoint("/socket").setAllowedOrigins("*").withSockJS();
    }
    
    // 註冊相關服務
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //定義了服務端接收地址的前綴,也即客戶端給服務端發消息的地址前綴
        registry.setApplicationDestinationPrefixes("/yifan");
        //定義了一個(或多個)客戶端訂閱地址的前綴信息,也就是客戶端接收服務端發送消息的前綴信息
        registry.enableSimpleBroker("/topic","/user");
        // 點對點使用的訂閱前綴(客戶端訂閱路徑上會體現出來),不設置的話,默認也是/user/
        registry.setUserDestinationPrefix("/user/");
    }
}

服務端 controller

@Controller
@RequestMapping("yifan")
public class ChatController {

    @Autowired
    private SocketService socketService;

    /* 接收消息     @SendToUser 誰發送的返回給誰  */
    @MessageMapping("/chat")
    public void broadCast(SocketMessage message){
        socketService.sendToMsg(message);
    }

    /* 發送給個人*/
    @MessageMapping("/chatTo")
    public void serverSendUesrMsg(SocketMessage message){
        socketService.sendToUserMsg(message);
    }
}

客戶端 網頁

需要準備

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" content="width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=no" name="viewport">
    <title>YF 頻道</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="/css/mycss.css">
</head>
<body>

<div style="background: #6777ef;width: 100vw ;height: 100px;text-align: center;  margin-bottom: 50px;">
    <p style="font-weight: bold;color: white;font-size: 24px;  padding-top: 15px  ">YFTOOLS</p>
    <input type="hidden" th:value="${session.user.uname}" class="uname">
    <div class="container tools-top-page">弋凡 聊天頻道 </div>
</div>

<div class="container" id="app">
    <div class="row" style="border: 1px solid #000000">
        <div class="col col-sm-8" id="msg" style="border-right: 2px solid #6777ef;height: 500px;overflow:auto; " ></div>
        <div class="col col-sm-4">
            <ul id="ras">
                <li  v-for="(item,i) in users"><input type="radio" :value="item.uname" name="redio"> {{item.uname}}</li>
            </ul>
        </div>
    </div>
    <div class="row">
        <div class="col-8">
            <textarea class="form-control" id="texts"style="position: absolute;left: 0px"></textarea>
        </div>
        <div class="col-4">
            <button class="btn btn-info one">個人</button>
            <button class="btn btn-info all">羣發</button>
        </div>
    </div>
</div>
</body>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<script src="/js/chat/sockjs.min.js"></script>
<script src="/js/chat/stomp.js"></script>
<script src="/js/vue.min.js"></script>
<script src="/js/axios.min.js"></script>
<script>
    new Vue({
        el:'#app',
        data:{
            users:[],
        },
        mounted(){
            this.chat();
        },
        methods:{
            chat(){
                axios.get('/user/All').then(res=>{
                    this.users = res.data;
                })
            }
        }
    });

    var name ='';
    // 連接
    var socket = new SockJS("http://126.75.109.85:81/socket");
    stompClient = Stomp.over(socket);
    stompClient.connect( {}, function (frame) {
        //訂閱廣播
        stompClient.subscribe('/topic/message', function (res) {
            $("#msg").append("<p class='text-center' ><span>"+JSON.parse(res.body).name +"</span>" + "<span style='color: red'> (全體消息) : </span>" +  JSON.parse(res.body).message  +  " </p>");
        });

        // 個人  == > 接收的消息 (訂閱自己)
        name = $(".uname").val();
        stompClient.subscribe('/user/'+name+'/ptp', function (res) {
            console.log(name+"---------");
            // showGreeting(JSON.parse(data.body).content);
            console.log("res => "+res);
            $("#msg").append(
              "  <div class='media text-left'> <img src='https://q4.qlogo.cn/g?b=qq&amp;[email protected]&amp;s=3?d=retro' alt='null'  class='rounded-circle mr-1' width='40px'>" +
                " <div class='media-body'><h5 class='mt-0'> "+JSON.parse(res.body).name+" </h5>"+JSON.parse(res.body).message +"</div>  </div>  "
            );
        });

    },function (error) {
        console.log('連接失敗【' + error + '】');
    });

    // 斷開連接
    $("#disconnect").click(function () {
        if (stompClient !== null) {
            stompClient.disconnect();
            alert('用戶: '+name+'   ...斷開連接...');
            $("#msg").html("");
        }
    });
    
    // 單個發送
    $(".one").click(function () {
        var info = {};
        info.toname = $('input:radio:checked').val();
        info.name = name ;
        info.message = $("#texts").val();
        info.date = "1212";
        if(info.toname != info.name && info.message != null && info.message!='' ){
            $("#msg").append(
                "  <div class='media text-right'>" +
                " <div class='media-body'><h5 class='mt-0'> "+ info.name+" </h5>"+info.message +"</div>  <img class='rounded-circle mr-1' width='40px' src='https://q4.qlogo.cn/g?b=qq&amp;[email protected]&amp;s=3?d=retro' alt='null'> </div>  "
            );
            stompClient.send("/yifan/chatTo", {}, JSON.stringify(info) );
        }else {
            alert("不能給自己發送消息,內容不能爲空~")
        }
        clearText();

    });

    // 羣發
    $(".all").click(function () {
        var info = {};
        info.name = name;
        info.message = $("#texts").val();
        info.date = "1212";
        stompClient.send("/yifan/chat", {}, JSON.stringify(info) );
        clearText();
    });

    // 清空輸入框
    function clearText(){
        $("#texts").val("");
    }

    //窗口關閉時,關閉連接
    window.οnbefοreunlοad=function() {
        socket.close();
    };
    
</script>
</html>

效果圖

在這裏插入圖片描述
end –

快來關注“弋凡”微信公衆號吧

快來關注“弋凡”微信公衆號把

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章