国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring Boot整合WebSocket

這篇具有很好參考價(jià)值的文章主要介紹了Spring Boot整合WebSocket。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

Spring Boot整合WebSocket

在HTTP協(xié)議中,所有的請(qǐng)求都是由客戶端發(fā)起的,由服務(wù)端進(jìn)行響應(yīng),服務(wù)端無(wú)法向客戶端推送消息,但是在一些需要即時(shí)通信的應(yīng)用中,又不可避免地需要服務(wù)端向客戶端推送消息,傳統(tǒng)的解決方案主要有如下幾種。

1. 為什么需要WebSocket

  1. 輪詢

輪詢是最簡(jiǎn)單的一種解決方案,所謂輪詢,就是客戶端在固定的時(shí)間間隔下不停地向服務(wù)端發(fā)送請(qǐng)求,查看服務(wù)端是否有最新的數(shù)據(jù),若服務(wù)端有最新的數(shù)據(jù),則返回給客戶端,若服務(wù)端沒(méi)有,則返回一個(gè)空的JSON或者XML文檔。輪詢對(duì)開發(fā)人員而言實(shí)現(xiàn)方便,但是弊端也很明顯:客戶端每次都要新建HTTP請(qǐng)求,服務(wù)端要處理大量的無(wú)效請(qǐng)求,在高并發(fā)場(chǎng)景下會(huì)嚴(yán)重拖慢服務(wù)端的運(yùn)行效率,同時(shí)服務(wù)端的資源被極大的浪費(fèi)了,因此這種方式并不可取。

  1. 長(zhǎng)輪詢

長(zhǎng)輪詢是傳統(tǒng)輪詢的升級(jí)版,當(dāng)聰明的工程師看到輪詢所存在的問(wèn)題后,就開始解決問(wèn)題,于是有了長(zhǎng)輪詢。不同于傳統(tǒng)輪詢,在長(zhǎng)輪詢中,服務(wù)端不是每次都會(huì)立即響應(yīng)客戶端的請(qǐng)求,只有在服務(wù)端有最新數(shù)據(jù)的時(shí)候才會(huì)立即響應(yīng)客戶端的請(qǐng)求,否則服務(wù)端會(huì)持有這個(gè)請(qǐng)求而不返回,直到有新數(shù)據(jù)時(shí)才返回。這種方式可以在一定程度上節(jié)省網(wǎng)絡(luò)資源和服務(wù)器資源,但是也存在一些問(wèn)題,例如:

  • 如果瀏覽器在服務(wù)器響應(yīng)之前有新數(shù)據(jù)要發(fā)送,就只能創(chuàng)建-一個(gè)新的并發(fā)請(qǐng)求,或者先嘗試斷掉當(dāng)前請(qǐng)求,再創(chuàng)建新的請(qǐng)求。
  • TCP和HTTP規(guī)范中都有連接超時(shí)一說(shuō),所以所謂的長(zhǎng)輪詢并不能一直持續(xù), 服務(wù)端和客戶端的連接需要定期的連接和關(guān)閉再連接,這又增大了程序員的工作量,當(dāng)然也有一些技術(shù)能夠延長(zhǎng)每次連接的時(shí)間,但畢竟是非主流解決方案。
  1. Applet和Flash

Applet和Flash都已經(jīng)是明日黃花,不過(guò)在這兩個(gè)技術(shù)存在的歲月里,除了可以讓我們的HTML頁(yè)面更加絢麗之外,還可以解決消息推送問(wèn)題。開發(fā)者可以使用Applet和Flash來(lái)模擬全雙工通信,通過(guò)創(chuàng)建一一個(gè)只有 1個(gè)像素點(diǎn)大小的透明的Applet或者Flash,然后將之內(nèi)嵌在網(wǎng)頁(yè)中,再?gòu)腁pplet或者Flash的代碼中創(chuàng)建一一個(gè)Socket連接進(jìn)行雙向通信。這種連接方式消除了HTTP協(xié)議中的諸多限制,當(dāng)服務(wù)器有消息發(fā)送到客戶端的時(shí)候,開發(fā)者可以在Applet或者Flash中調(diào)用JavaScript函數(shù)將數(shù)據(jù)顯示在頁(yè)面上,當(dāng)瀏覽器有數(shù)據(jù)要發(fā)送給服務(wù)器時(shí)也一樣,通過(guò)Applet或者Flash來(lái)傳遞。這種方式真正地實(shí)現(xiàn)了全雙工通信,不過(guò)也有問(wèn)題,說(shuō)明如下:

  • 瀏覽器必須能夠運(yùn)行Java或者Flash。
  • 無(wú)論是Applet還是Flash 都存在安全問(wèn)題。
  • 隨著HTML 5標(biāo)準(zhǔn)被各瀏覽器廠商廣泛支持,F(xiàn)lash 下架已經(jīng)被提上日程( Adobe宣布2020年正式停止支持Flash)。

其實(shí),傳統(tǒng)的解決方案不止這三種,但是無(wú)論哪種解決方案都有自身的缺陷,于是有了WebSocket。

2. WebSocket簡(jiǎn)介

WebSocket是一種在單個(gè)TCP連接.上進(jìn)行全雙工通信的協(xié)議,已被W3C定為標(biāo)準(zhǔn)。使用WebSocket可以使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單,它允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)。在WebSocket協(xié)議中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就可以直接創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。

WebSocket使用了HTTP/1.1的協(xié)議升級(jí)特性,一個(gè)WebSocket請(qǐng)求首先使用非正常的HTTP請(qǐng)求以特定的模式訪問(wèn)一個(gè)URL,這個(gè)URL有兩種模式,分別是ws和wss,對(duì)應(yīng)HTTP協(xié)議中的HTTP和HTTPS,在請(qǐng)求頭中有一個(gè)Connection:Upgrade字段,表示客戶端想要對(duì)協(xié)議進(jìn)行升級(jí),另外還有一個(gè)Upgrade:websocket字段,表示客戶端想要將請(qǐng)求協(xié)議升級(jí)為WebSocket協(xié)議。這兩個(gè)字段共同告訴服務(wù)器要將連接升級(jí)為WebSocket這樣一種全雙工協(xié)議,如果服務(wù)端同意協(xié)議升級(jí),那么在握手完成之后,文本消息或者其他二進(jìn)制消息就可以同時(shí)在兩個(gè)方向上進(jìn)行發(fā)送,而不需要關(guān)閉和重建連接。此時(shí)的客戶端和服務(wù)端關(guān)系是對(duì)等的,它們可以互相向?qū)Ψ街鲃?dòng)發(fā)送消息。和傳統(tǒng)的解決方案相比,WebSocket主要有如下特點(diǎn):

  • WebSocket使用時(shí)需要先創(chuàng)建連接,這使得WebSocket成為一種有狀態(tài)的協(xié)議,在之后的通信過(guò)程中可以省略部分狀態(tài)信息( 例如身份認(rèn)證等)。
  • WebSocket連接在端口80 (ws)或者443 (wss)上創(chuàng)建,與HTTP使用的端口相同,這樣,基本上所有的防火墻都不會(huì)阻止WebSocket連接。
  • WebSocket使用HTTP協(xié)議進(jìn)行握手,因此它可以自然而然地集成到網(wǎng)絡(luò)瀏覽器和HTTP服務(wù)器中,而不需要額外的成本。
  • 心跳消息(ping 和pong)將被反復(fù)的發(fā)送,進(jìn)而保持WebSocket連接一直處于活躍狀態(tài)。
  • 使用該協(xié)議,當(dāng)消息啟動(dòng)或者到達(dá)的時(shí)候,服務(wù)端和客戶端都可以知道。
  • WebSocket連接關(guān)閉時(shí)將發(fā)送一個(gè)特殊的關(guān)閉消息。
  • WebSocket支持跨域,可以避免Ajax的限制。
  • HTTP規(guī)范要求瀏覽器將并發(fā)連接數(shù)限制為每個(gè)主機(jī)名兩個(gè)連接,但是當(dāng)我們使用WebSocket的時(shí)候,當(dāng)握手完成之后,該限制就不存在了,因?yàn)榇藭r(shí)的連接已經(jīng)不再是HTTP連接了。
  • WebSocket協(xié)議支持?jǐn)U展,用戶可以擴(kuò)展協(xié)議,實(shí)現(xiàn)部分自定義的子協(xié)議。
  • 更好的二進(jìn)制支持以及更好的壓縮效果。

WebSocket既然具有這么多優(yōu)勢(shì),使用場(chǎng)景當(dāng)然也是非常廣泛的,例如:

  • 在線股票網(wǎng)站。
  • 即時(shí)聊天。
  • 多人在線游戲。
  • 應(yīng)用集群通信。
  • 系統(tǒng)性能實(shí)時(shí)監(jiān)控。

在了解了這么多WebSocket的基本信息后,接下來(lái)看看在Spring Boot中如何使用WebSocket。

3. Spring Boot整合WebSocket

Spring Boot 對(duì)WebSocket 提供了非常友好的支持,可以方便開發(fā)者在項(xiàng)目中快速集成WebSocket功能,實(shí)現(xiàn)單聊或者群聊。

3.1 消息群發(fā)

3.1.1 創(chuàng)建項(xiàng)目

首先創(chuàng)建一個(gè)Spring Boot項(xiàng)目,添加如下依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>webjars-locator-core</artifactId>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>sockjs-client</artifactId>
    <version>1.1.2</version>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>stomp-websocket</artifactId>
    <version>2.3.4</version>
</dependency>
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.6.0</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

spring-bot-starter-websocket依賴是Web Socket相關(guān)依賴,其他的都是前端庫(kù),使用jar包的形式對(duì)這些前端庫(kù)進(jìn)行統(tǒng)一管理, 使用webjar添加到項(xiàng)目中的前端庫(kù),在Spring Boot項(xiàng)目中已經(jīng)默認(rèn)添加了靜態(tài)資源過(guò)濾,因此可以直接使用。

3.1.2 配置WebSocket

Spring框架提供了基于WebSocket的STOMP支持,STOMP是一個(gè)簡(jiǎn)單的可互操作的協(xié)議,

通常被用于通過(guò)中間服務(wù)器在客戶端之間進(jìn)行異步消息傳遞。WebSocket 配置如下:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // 設(shè)置消息代理的前綴,如果消息的前綴為"/topic",就會(huì)將消息轉(zhuǎn)發(fā)給消息代理(broker)
        // 再由消息代理廣播給當(dāng)前連接的客戶端
        config.enableSimpleBroker("/topic");
        // 下面方法可以配置一個(gè)或多個(gè)前綴,通過(guò)這些前綴過(guò)濾出需要被注解方法處理的消息。
        // 例如這里表示前綴為"/app"的destination可以通過(guò)@MessageMapping注解的方法處理
        // 而其他 destination(例如"/topic""/queue")將被直接交給 broker 處理
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 定義一個(gè)前綴為"/chart"的endpoint,并開啟 sockjs 支持。
        // sockjs 可以解決瀏覽器對(duì)WebSocket的兼容性問(wèn)題,客戶端將通過(guò)這里配置的URL建立WebSocket連接
        registry.addEndpoint("/chat").withSockJS();
    }
}

代碼解釋:

  • 自定義類WebSocketConfig 繼承自WebSocketMessageBrokerConfigurer 進(jìn)行WebSocket配置,然后通過(guò)@EnableWebSocketMessageBroker注解開啟WebSocket消息代理。
  • config.enableSimpleBroker(“/topic”)表示設(shè)置消息代理的前綴,即如果消息的前綴是“/topic" ,就會(huì)將消息轉(zhuǎn)發(fā)給消息代理( broker),再由消息代理將消息廣播給當(dāng)前連接的客戶端。
  • config.setApplicationDestinationPrefixes(“/app”)表示配置一個(gè)或多個(gè)前綴,通過(guò)這些前綴過(guò)濾出需要被注解方法處理的消息。例如,前綴為“/app”的destination可以通過(guò)@MessageMapping注解的方法處理,而其他destination(例如“/topic”“/queue”)將被直接交給broker處理。
  • regitry.addEndpoint(“/chat”).withSockJS()則表示定義一個(gè)前綴為“/chat” 的endPoint,并開啟sockjs支持,sockjs 可以解決瀏覽器對(duì)WebSocket的兼容性問(wèn)題,客戶端將通過(guò)這里配置的URL來(lái)建立WebSocket連接。
3.1.3 定義Controller

定義一個(gè)Controller用來(lái)實(shí)現(xiàn)對(duì)消息的處理,代碼如下:

@Controller
public class GreetingController {
    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Message greeting(Message message) throws Exception {
        return message;
    }
}

自定義的Message對(duì)象代碼如下:

@Data
public class Message {
    private String name;
    private String content;
}

根據(jù)第2步的配置,@MessageMapping(“hello”)注解的方法將用來(lái)接收“/apphello"路徑發(fā)送來(lái)的消息,在注解方法中對(duì)消息進(jìn)行處理后,再將消息轉(zhuǎn)發(fā)到@SendTo定義的路徑上,而@SendTo路徑是一個(gè)前綴為“/topic” 的路徑,因此該消息將被交給消息代理broker,再由broker 進(jìn)行廣播。

3.1.4 構(gòu)建聊天頁(yè)面

在resources/static目錄下創(chuàng)建chat.html 頁(yè)面作為聊天頁(yè)面,代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>群聊</title>
    <script src="/webjars/jquery/jquery.min.js"></script>
    <script src="/webjars/sockjs-client/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/stomp.min.js"></script>
    <script>
    var stompClient = null;

    // 根據(jù)是否已連接設(shè)置頁(yè)面元素狀態(tài)
    function setConnected(connected) {
        $("#connect").prop("disabled", connected);
        $("#disconnect").prop("disabled", !connected);
        if (connected) {
            $("#conversation").show();
            $("#chat").show();
        }
        else {
            $("#conversation").hide();
            $("#chat").hide();
        }
        $("#greetings").html("");
    }

    // 建立一個(gè)WebSocket連接
    function connect() {
        // 用戶名不能為空
        if (!$("#name").val()) {
            return;
        }
        // 首先使用 SockJS 建立連接
        var socket = new SockJS("/chat");
        // 然后創(chuàng)建一個(gè)STOMP實(shí)例發(fā)起連接請(qǐng)求
        stompClient = Stomp.over(socket);
        // 連接成功回調(diào)
        stompClient.connect({}, function (frame) {
            // 進(jìn)行頁(yè)面設(shè)置
            setConnected(true);
            // 訂閱服務(wù)端發(fā)送回來(lái)的消息
            stompClient.subscribe('/topic/greetings', function (greeting) {
                // 將服務(wù)端發(fā)送回來(lái)的消息展示出來(lái)
                showGreeting(JSON.parse(greeting.body));
            });
        });
    }

    // 斷開WebSocket連接
    function disconnect() {
        if (stompClient !== null) {
            stompClient.disconnect();
        }
        setConnected(false);
    }

    // 發(fā)送消息
    function sendName() {
        stompClient.send("/app/hello",
            {},
            JSON.stringify({'name': $("#name").val(),'content':$("#content").val()}));
    }

    // 將服務(wù)端發(fā)送回來(lái)的消息展示出來(lái)
    function showGreeting(message) {
        $("#greetings")
            .append("<div>" + message.name+":"+message.content + "</div>");
    }

    // 頁(yè)面加載后進(jìn)行初始化動(dòng)作
    $(function () {
        $( "#connect" ).click(function() { connect(); });
        $( "#disconnect" ).click(function() { disconnect(); });
        $( "#send" ).click(function() { sendName(); });
    });
</script>
</head>
<body>
<div>
    <label for="name">請(qǐng)輸入用戶名:</label>
    <input type="text" id="name" placeholder="用戶名">
</div>
<div>
    <button id="connect" type="button">連接</button>
    <button id="disconnect" type="button" disabled="disabled">斷開連接</button>
</div>
<div id="chat" style="display: none;">
    <div>
    <label for="name">請(qǐng)輸入聊天內(nèi)容:</label>
    <input type="text" id="content" placeholder="聊天內(nèi)容">
    </div>
    <button id="send" type="button">發(fā)送</button>
    <div id="greetings">
    <div id="conversation" style="display: none">群聊進(jìn)行中...</div>
    </div>
</div>
</body>
</html>

代碼解釋:

  • connect 方法表示建立一個(gè)WebSocket連接,在建立WebSocket連接時(shí),用戶必須先輸入用戶名,然后才能建立連接。
  • 第19~26行首先使用SockJS建立連接,然后創(chuàng)建一個(gè)STOMP實(shí)例發(fā)起連接請(qǐng)求,在連接成功的回調(diào)方法中,首先調(diào)用setConnected(true);方 法進(jìn)行頁(yè)面的設(shè)置,然后調(diào)用STOMP中的subscribe方法訂閱服務(wù)端發(fā)送回來(lái)的消息,并將服務(wù)端發(fā)送來(lái)的消息展示出來(lái)(使用showGreeting方法)。
  • 調(diào)用STOMP中的disconnect 方法可以斷開一個(gè)WebSocket連接。
3.1.5 測(cè)試

接下來(lái)啟動(dòng)Spring Boot 項(xiàng)目進(jìn)行測(cè)試,在瀏覽器中輸入htp:/ocalhost:8080/chat.html,顯示結(jié)果如圖所示。

Spring Boot整合WebSocket

用戶首先輸入用戶名,然后單擊“連接”按鈕,結(jié)果如圖所示。

Spring Boot整合WebSocket

然后換一個(gè)瀏覽器,或者使用Chrome瀏覽器的多用戶(注意不是多窗口),重復(fù)剛才的步驟,這樣就有兩個(gè)用戶連接上了,接下來(lái)就可以開始群聊了(當(dāng)然也可以有更多的用戶連接上來(lái)),如圖所示。

Spring Boot整合WebSocket

3.2 消息點(diǎn)對(duì)點(diǎn)發(fā)送

在3.1小節(jié)中介紹的消息發(fā)送使用到了@SendTo注解,該注解將方法處理過(guò)的消息轉(zhuǎn)發(fā)到broker,再由broker進(jìn)行消息廣播。除了@SendTo注解外, Spring 還提供了SimpMessagingTemplate類來(lái)讓開發(fā)者更加靈活地發(fā)送消息。

3.2.1 添加依賴

既然是點(diǎn)對(duì)點(diǎn)發(fā)送,就應(yīng)該有用戶的概念,因此,首先在項(xiàng)目中加入Spring Security的依賴,代碼如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
3.2.2 配置Spring Security

對(duì)Spring Security進(jìn)行配置,添加兩個(gè)用戶,同時(shí)配置所有地址都認(rèn)證后才能訪問(wèn),代碼如下:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    // 指定密碼的加密方式
    @SuppressWarnings("deprecation")
    @Bean
    PasswordEncoder passwordEncoder(){
        // 不對(duì)密碼進(jìn)行加密
        return NoOpPasswordEncoder.getInstance();
    }

    // 配置用戶及其對(duì)應(yīng)的角色
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin").password("123").roles("ADMIN","USER")
                .and()
                .withUser("suohe").password("123").roles("USER");
    }

    // 配置 URL 訪問(wèn)權(quán)限
    @Override
    protected  void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() // 開啟 HttpSecurity 配置
                .anyRequest().authenticated() // 用戶訪問(wèn)所有地址都必須登錄認(rèn)證后訪問(wèn)
                .and().formLogin().permitAll(); // 開啟表單登錄
    }
}

這里就是Spring Security的一個(gè)常規(guī)配置,相關(guān)配置含義可以參考我前面文章。

3.2.3 改造WebSocket配置

接下來(lái)對(duì)WebSocket配置進(jìn)行改造,代碼如下:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // 設(shè)置消息代理的前綴,如果消息的前綴為"/topic"、"/queue",就會(huì)將消息轉(zhuǎn)發(fā)給消息代理(broker)
        // 再由消息代理廣播給當(dāng)前連接的客戶端
        config.enableSimpleBroker("/topic","/queue");
        // 下面方法可以配置一個(gè)或多個(gè)前綴,通過(guò)這些前綴過(guò)濾出需要被注解方法處理的消息。
        // 例如這里表示前綴為"/app"的destination可以通過(guò)@MessageMapping注解的方法處理
        // 而其他 destination(例如"/topic""/queue")將被直接交給 broker 處理
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 定義一個(gè)前綴為"/chart"的endpoint,并開啟 sockjs 支持。
        // sockjs 可以解決瀏覽器對(duì)WebSocket的兼容性問(wèn)題,客戶端將通過(guò)這里配置的URL建立WebSocket連接
        registry.addEndpoint("/chat").withSockJS();
    }
}

這里的修改是在config.enableSimpleBroker(“/topic”);方法的基礎(chǔ) 上又增加了一個(gè)broker 前綴“/queue”,方便對(duì)群發(fā)消息和點(diǎn)對(duì)點(diǎn)消息進(jìn)行管理。

3.2.4 配置Controller

對(duì)WebSocket的Controller 進(jìn)行改造,代碼如下:

@Controller
public class GreetingController {

    @Autowired
    SimpMessagingTemplate messagingTemplate;

    // 處理來(lái)自"/app/hello"路徑的消息
    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Message greeting(Message message) throws Exception {
        return message;
    }

    // 處理來(lái)自"/app/chat"路徑的消息
    @MessageMapping("/chat")
    public void chat(Principal principal, Chat chat) {
        // 獲取當(dāng)前登錄用戶的用戶名
        String from = principal.getName();
        // 將用戶設(shè)置給chat對(duì)象的from屬性
        chat.setFrom(from);
        // 再將消息發(fā)送出去,發(fā)送的目標(biāo)用戶就是 chat 對(duì)象的to屬性值
        messagingTemplate.convertAndSendToUser(chat.getTo(),
                "/queue/chat", chat);
    }
}

代碼解釋:

  • 群發(fā)消息依然使用@SendTo注解來(lái)實(shí)現(xiàn),點(diǎn)對(duì)點(diǎn)的消息發(fā)送則使用SimpMessagingTemplate來(lái)實(shí)現(xiàn)。

  • 第10~16 行定義了一個(gè)新的消息處理接口,@MessageMapping("/chat)注 解表示來(lái)自“/app/chat”路徑的消息將被chat 方法處理。chat 方法的第一個(gè)參數(shù)Principal可以用來(lái)獲取當(dāng)前登錄用戶的信息,第二個(gè)參數(shù)則是客戶端發(fā)送來(lái)的消息。

  • 在chat 方法中,首先獲取當(dāng)前用戶的用戶名,設(shè)置給chat對(duì)象的from屬性,再將消息發(fā)送出去,發(fā)送的目標(biāo)用戶就是chat對(duì)象的to屬性值。

  • 消息發(fā)送使用的方法是convertAndSendToUser,該方法內(nèi)部調(diào)用了convertAndSend方法,并對(duì)消息路徑做了處理,部分源碼如下:

    public void convertAndSendToUser(String user, String destination, Object payload) throws MessagingException {
            this.convertAndSendToUser(user, destination, payload, (MessagePostProcessor)null);
        }
     public void convertAndSendToUser(String user, String destination, Object payload) throws MessagingException {
         this.convertAndSendToUser(user, destination, payload, (MessagePostProcessor)null);
     }//這里destinationPrefix 的默認(rèn)值是“/user”, 也就是說(shuō)消息的最終發(fā)送路徑是“/user/用戶名/queue/chat"。
    
    
  • chat是一個(gè)普通的JavaBean, to 屬性表示消息的目標(biāo)用戶,from 表示消息從哪里來(lái),content則是消息的主體內(nèi)容。

3.2.5 創(chuàng)建在線聊天頁(yè)面

在resources/static 目錄下創(chuàng)chat.html 頁(yè)面作為在線聊天頁(yè)面,代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>單聊</title>
    <script src="/webjars/jquery/jquery.min.js"></script>
    <script src="/webjars/sockjs-client/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/stomp.min.js"></script>
    <script>
        var stompClient = null;

        // 建立一個(gè)WebSocket連接
        function connect() {
            // 首先使用 SockJS 建立連接
            var socket = new SockJS('/chat');
            // 然后創(chuàng)建一個(gè)STOMP實(shí)例發(fā)起連接請(qǐng)求
            stompClient = Stomp.over(socket);
            // 連接成功回調(diào)
            stompClient.connect({}, function (frame) {
                // 訂閱服務(wù)端發(fā)送回來(lái)的消息
                stompClient.subscribe('/user/queue/chat', function (chat) {
                    // 將服務(wù)端發(fā)送回來(lái)的消息展示出來(lái)
                    showGreeting(JSON.parse(chat.body));
                });
            });
        }

        // 發(fā)送消息
        function sendMsg() {
            stompClient.send("/app/chat", {},
                JSON.stringify({'content':$("#content").val(),
                    'to':$("#to").val()}));
        }

        // 將服務(wù)端發(fā)送回來(lái)的消息展示出來(lái)
        function showGreeting(message) {
            $("#chatsContent")
                .append("<div>" + message.from+":"+message.content + "</div>");
        }

        // 頁(yè)面加載后進(jìn)行初始化動(dòng)作
        $(function () {
            // 頁(yè)面加載完畢后自動(dòng)連接
            connect();
            $( "#send" ).click(function() { sendMsg(); });
        });
    </script>
</head>
<body>
<div id="chat">
    <div id="chatsContent">
    </div>
    <div>
        請(qǐng)輸入聊天內(nèi)容:
        <input type="text" id="content" placeholder="聊天內(nèi)容">
        目標(biāo)用戶:
        <input type="text" id="to" placeholder="目標(biāo)用戶">
        <button id="send" type="button">發(fā)送</button>
    </div>
</div>
</body>
</html>

其中js文件基本與前文的前面js文件內(nèi)容一致, 差異主要體現(xiàn)在三個(gè)地方:

  • 連接成功后,訂閱的地址為“/user/queue/chat”, 該地址比服務(wù)端配置的地址多了“/user” 前綴,這是因?yàn)镾impMessagingTemplate類中自動(dòng)添加了路徑前綴。
  • 聊天消息發(fā)送路徑為“/app/chat”。
  • 發(fā)送的消息內(nèi)容中有一個(gè)to字段,該字段用來(lái)描述消息的目標(biāo)用戶。
3.2.6 測(cè)試

經(jīng)過(guò)如上幾個(gè)步驟之后,一個(gè)點(diǎn)對(duì)點(diǎn)的聊天服務(wù)就搭建成功了,接下來(lái)直接在瀏覽器地址欄中輸入http://calhost:8080/chat.html,首先會(huì)自動(dòng)跳轉(zhuǎn)到Spring Security的默認(rèn)登錄頁(yè)面,分別使用一開始配置的兩個(gè)用戶admin/123和suohe/123登錄,登錄成功后,就可以開始在線聊天了,如圖所示。

Spring Boot整合WebSocket文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-452668.html

到了這里,關(guān)于Spring Boot整合WebSocket的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 實(shí)時(shí)通信應(yīng)用的開發(fā):Vue.js、Spring Boot 和 WebSocket 整合實(shí)踐

    實(shí)時(shí)通信應(yīng)用的開發(fā):Vue.js、Spring Boot 和 WebSocket 整合實(shí)踐

    目錄 1.?什么是webSocket? 2.?webSocket可以用來(lái)做什么? 3.?webSocket協(xié)議 4. 服務(wù)器端 5. 客戶端 6. 測(cè)試通訊 WebSocket 是一種在單個(gè) TCP連接 上進(jìn)行全雙工通信的協(xié)議。WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單,允 許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù) 。在WebSocket API中,瀏覽

    2024年02月11日
    瀏覽(26)
  • MQTT協(xié)議-EMQX技術(shù)文檔-spring-boot整合使用--發(fā)送接收-消費(fèi)

    MQTT協(xié)議-EMQX技術(shù)文檔-spring-boot整合使用--發(fā)送接收-消費(fèi)

    MQTT(Message Queuing Telemetry Transport)是一種基于發(fā)布/訂閱模式的通信協(xié)議,它與MQ(Message Queue,消息隊(duì)列)有一定的關(guān)聯(lián),但二者并不完全相同。 MQTT是一種輕量級(jí)的通信協(xié)議,專門為在物聯(lián)網(wǎng)(IoT)設(shè)備之間的消息傳遞而設(shè)計(jì)。它運(yùn)行在TCP協(xié)議之上,以“發(fā)布-訂閱”模式進(jìn)行

    2024年02月12日
    瀏覽(21)
  • 整合 WebSocket 基于 STOMP 協(xié)議實(shí)現(xiàn)廣播

    整合 WebSocket 基于 STOMP 協(xié)議實(shí)現(xiàn)廣播

    SpringBoot 實(shí)戰(zhàn) (十六) | 整合 WebSocket 基于 STOMP 協(xié)議實(shí)現(xiàn)廣播 如題,今天介紹的是 SpringBoot 整合 WebSocket 實(shí)現(xiàn)廣播消息。 什么是 WebSocket ? WebSocket 為瀏覽器和服務(wù)器提供了雙工異步通信的功能,即瀏覽器可以向服務(wù)器發(fā)送信息,反之也成立。 WebSocket 是通過(guò)一個(gè) socket 來(lái)實(shí)現(xiàn)雙

    2024年01月21日
    瀏覽(20)
  • Springboot 整合 WebSocket ,使用STOMP協(xié)議 ,前后端整合實(shí)戰(zhàn) (一)(1)

    Springboot 整合 WebSocket ,使用STOMP協(xié)議 ,前后端整合實(shí)戰(zhàn) (一)(1)

    server: port: 9908 3.WebSocketConfig.java 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.springfra

    2024年04月25日
    瀏覽(26)
  • spring boot es | spring boot 整合elasticsearch | spring boot整合多數(shù)據(jù)源es

    spring boot es | spring boot 整合elasticsearch | spring boot整合多數(shù)據(jù)源es

    目錄 Spring Boot與ES版本對(duì)應(yīng) Maven依賴 配置類 使用方式 @Test中注入方式 @Component中注入方式 查詢文檔 實(shí)體類 通過(guò)ElasticsearchRestTemplate查詢 通過(guò)JPA查詢 保存文檔 參考鏈接 項(xiàng)目組件版本: Spring Boot:2.2.13.RELEASE Elasticsearch:6.8.0 JDK:1.8.0_66 Tips: 主要看第3列和第5列,根據(jù)ES版本選擇

    2023年04月18日
    瀏覽(28)
  • Springboot 整合 WebSocket ,使用STOMP協(xié)議+Redis 解決負(fù)載場(chǎng)景問(wèn)題

    Springboot 整合 WebSocket ,使用STOMP協(xié)議+Redis 解決負(fù)載場(chǎng)景問(wèn)題

    ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jacksonSeial.setObjectMapper(om); template.setValueSerializer(jacksonSeial); template.setKeySerializer(stringRedisSerializer); template.setHashKeySerializer(stringRedisSerializer); template

    2024年04月14日
    瀏覽(49)
  • SpringBoot項(xiàng)目整合WebSocket+netty實(shí)現(xiàn)前后端雙向通信(同時(shí)支持前端webSocket和socket協(xié)議哦)

    SpringBoot項(xiàng)目整合WebSocket+netty實(shí)現(xiàn)前后端雙向通信(同時(shí)支持前端webSocket和socket協(xié)議哦)

    目錄 ? 前言 技術(shù)棧 功能展示 一、springboot項(xiàng)目添加netty依賴 二、netty服務(wù)端 三、netty客戶端 四、測(cè)試 五、代碼倉(cāng)庫(kù)地址 ??專屬小彩蛋:前些天發(fā)現(xiàn)了一個(gè)巨牛的人工智能學(xué)習(xí)網(wǎng)站,通俗易懂,風(fēng)趣幽默,忍不住分享一下給大家。點(diǎn)擊跳轉(zhuǎn)到網(wǎng)站(前言 - 床長(zhǎng)人工智能教程

    2024年02月12日
    瀏覽(23)
  • Spring整合tomcat的WebSocket詳細(xì)邏輯(圖解)

    Spring整合tomcat的WebSocket詳細(xì)邏輯(圖解)

    主要解決存在的疑問(wèn) 為什么存在2種spring整合websocket的方式,一種是使用@ServerEndpoint注解的方式,一種是使用@EnableWebSocket注解的方式,這2種有什么區(qū)別和聯(lián)系?可以共存嗎?它們實(shí)現(xiàn)的原理是什么?它們的各種配置到底是什么意思?@EnableWebSocket是如何完成配置的? 在服務(wù)端

    2024年02月07日
    瀏覽(33)
  • 【Spring Boot】Spring Boot整合多數(shù)據(jù)源

    在實(shí)際的開發(fā)工作中,我們經(jīng)常會(huì)遇到需要整合多個(gè)數(shù)據(jù)源的情況,比如同時(shí)連接多個(gè)數(shù)據(jù)庫(kù)、讀寫分離、跨數(shù)據(jù)庫(kù)查詢等。本文將介紹如何使用Spring Boot來(lái)實(shí)現(xiàn)多數(shù)據(jù)源的整合,對(duì)于剛剛接觸開發(fā)的小伙伴可能有一些幫助。 在一個(gè)應(yīng)用程序中使用多個(gè)數(shù)據(jù)源意味著我們需要

    2024年02月10日
    瀏覽(28)
  • Spring Boot 實(shí)現(xiàn) WebSocket 示例

    Spring Boot 實(shí)現(xiàn) WebSocket 示例

    WebSocket協(xié)議提供了一種標(biāo)準(zhǔn)化的方法,通過(guò)單個(gè)TCP連接在客戶機(jī)和服務(wù)器之間建立全雙工、雙向的通信通道。它是一種不同于HTTP的TCP協(xié)議,但被設(shè)計(jì)為在HTTP上工作,使用端口80和443,并允許重用現(xiàn)有的防火墻規(guī)則。 WebSocket 協(xié)議是獨(dú)立的基于 TCP 協(xié)議。它與 HTTP 的唯一關(guān)系是

    2024年02月14日
    瀏覽(22)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包