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

前端訂閱后端推送WebSocket定時任務(wù)

這篇具有很好參考價值的文章主要介紹了前端訂閱后端推送WebSocket定時任務(wù)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

0.需求

? ? ? ? 后端定時向前端看板推送數(shù)據(jù),每10秒或者30秒推送一次。

1.前言知識

????????HTTP協(xié)議是一個應(yīng)用層協(xié)議,它的特點(diǎn)是無狀態(tài)、無連接和單向的。在HTTP協(xié)議中,客戶端發(fā)起請求,服務(wù)器則對請求進(jìn)行響應(yīng)。這種請求-響應(yīng)的模式意味著服務(wù)器無法主動向客戶端發(fā)送消息。

????????這種單向通信的缺點(diǎn)在于,如果服務(wù)器有持續(xù)的狀態(tài)變化,客戶端要獲取這些變化就很困難。為了解決這個問題,許多Web應(yīng)用采用了一種叫做長輪詢的技術(shù),即頻繁地通過AJAX和XML發(fā)起異步請求來檢查服務(wù)器的狀態(tài)。但這種方式效率較低,也很浪費(fèi)資源,因?yàn)樾枰粩嗟亟⑦B接或保持連接打開。

????????而WebSocket則是一種不同的通信協(xié)議,它允許客戶端和服務(wù)器之間進(jìn)行全雙工通信。這意味著無論是客戶端還是服務(wù)器,都可以隨時通過已經(jīng)建立的連接向?qū)Ψ桨l(fā)送數(shù)據(jù)。而且,WebSocket只需要建立一次連接就可以保持通信狀態(tài),無需頻繁地建立和斷開連接,因此效率大大提高。

????????總結(jié)一下,HTTP協(xié)議雖然廣泛應(yīng)用,但因其單向通信的局限性,在處理服務(wù)器狀態(tài)持續(xù)變化的情況時顯得力不從心。而WebSocket協(xié)議則通過全雙工通信的方式,有效地解決了這個問題,提高了通信效率。

websocket 發(fā)布-訂閱模式,websocket,定時任務(wù),websocket定時推送消息,看板推送消息

2.后端實(shí)現(xiàn)

2.1不帶參數(shù)

2.1.1添加依賴:

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

2.1.2websocket配置:

/**
 * 通過EnableWebSocketMessageBroker
 * 開啟使用STOMP協(xié)議來傳輸基于代理(message broker)的消息,
 * 此時瀏覽器支持使用@MessageMapping 就像支持@RequestMapping一樣。
 */

//WebSocket的配置類
@Configuration
//開啟對WebSocket的支持
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer{

    /**
     * 注冊stomp的端點(diǎn)
     * 注冊一個STOMP協(xié)議的節(jié)點(diǎn),并映射到指定的URL
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //endPoint 注冊協(xié)議節(jié)點(diǎn),并映射指定的URl點(diǎn)對點(diǎn)-用
        //注冊一個名字為"/endpointSocket" 的endpoint,并指定 SockJS協(xié)議。
        //允許使用socketJs方式訪問,訪問點(diǎn)為webSocketServer,允許跨域
        //連接前綴
          //配置客戶端嘗試連接地址
        //廣播
        registry.addEndpoint("/ws/public").setAllowedOriginPatterns("*").withSockJS();
        //點(diǎn)對點(diǎn)
        registry.addEndpoint("/ws/private").setAllowedOriginPatterns("*").withSockJS();
    }


   /**
     * 通過實(shí)現(xiàn) WebSocketMessageBrokerConfigurer 接口和加上 @EnableWebSocketMessageBroker 來進(jìn)行 stomp 的配置與注解掃描。
     * 其中覆蓋 registerStompEndpoints 方法來設(shè)置暴露的 stomp 的路徑,其它一些跨域、客戶端之類的設(shè)置。
     * 覆蓋 configureMessageBroker 方法來進(jìn)行節(jié)點(diǎn)的配置。
     * 其中 enableSimpleBroker配置的廣播節(jié)點(diǎn),也就是服務(wù)端發(fā)送消息,客戶端訂閱就能接收消息的節(jié)點(diǎn)。
     * 覆蓋setApplicationDestinationPrefixes方法,設(shè)置客戶端向服務(wù)端發(fā)送消息的節(jié)點(diǎn)。
     * 覆蓋 setUserDestinationPrefix 方法,設(shè)置一對一通信的節(jié)點(diǎn)。
     *
     * @param registry
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //配置消息代理,即設(shè)置廣播節(jié)點(diǎn)
        registry.enableSimpleBroker("/topic","/user");
        //后端接收的主題前綴,即客戶端向服務(wù)端發(fā)送消息需要有/client前綴
//        registry.setApplicationDestinationPrefixes("/client");
        //指定用戶發(fā)送(一對一)的前綴/user/
//        registry.setUserDestinationPrefix("/user/");
    }
}

2.1.3后端代碼?

????????一個是訂閱請求接口,一個是關(guān)閉定時任務(wù)接口。這段代碼實(shí)現(xiàn)了一個基于WebSocket的定時推送機(jī)制,允許通過發(fā)送WebSocket消息來啟動和關(guān)閉定時任務(wù),從而每30秒推送一次數(shù)據(jù)。

  /**
     * 看板接口-不帶參數(shù)
     * 定時任務(wù)(每30秒推送一次)
     */
    @MessageMapping("/backend/produce/summary")
    public void pushProduceSummary() {
        log.info("服務(wù)端接收到消息: {}");
        if (scheduledTask.get("pushProduceSummary") == null) {
            ScheduledFuture<?> future = executorService.scheduleAtFixedRate(() -> {
                ProgressVO progressVO = progressSummaryService.summary();
                String destination = "/topic/backend/produce/summary";
                template.convertAndSend(destination, progressVO);
                log.info("已推送信息,每30秒推送一次:{}");
            }, 1, 30, TimeUnit.SECONDS);
            scheduledTask.put("pushProduceSummary", future);
        } else {
            log.info("定時任務(wù)已開始!");
        }

    }
/**
     * 關(guān)閉/backend/produce/summary接口的定時任務(wù)
     *
     * @author weiq
     */
    @MessageMapping("/close/backend/produce/summary")
    public void cancelPushProduceSummary() {
        scheduledTask.forEach((StringKey, future) -> {
            if (future != null && !future.isCancelled() && StringKey.equals("pushProduceSummary")) {
                // 清除定時任務(wù)的引用
                scheduledTask.remove("pushProduceSummary");
                boolean cancel = future.cancel(true);
                if (cancel) {
                    log.info("已關(guān)閉定時任務(wù)Key={}",StringKey);
                }else{
                    log.info("失敗關(guān)閉定時任務(wù)Key={}",StringKey);
                }
            }
        });

    }

2.2帶參數(shù)

????????一個是訂閱請求接口,一個是關(guān)閉定時任務(wù)接口。

  • 當(dāng)客戶端向?/backend/produce/runEfficiency/{startTime}/{endTime}?這個 WebSocket 地址發(fā)送消息時,pushProduceRunEfficiency?方法會被調(diào)用。
  • 這個方法會檢查是否已有一個定時任務(wù)在運(yùn)行。如果沒有,它會創(chuàng)建一個新的定時任務(wù),該任務(wù)會每30秒從?runEfficiencyService?獲取運(yùn)行效率數(shù)據(jù),并通過 WebSocket 發(fā)送到指定的主題(destination)。
  • 前端(或任何監(jiān)聽該主題的 WebSocket 客戶端)需要事先訂閱這個主題,以便能夠接收后端發(fā)送的數(shù)據(jù)。
 /**
     * (看板)
     *定時任務(wù)(每30秒推送一次)
     * @param startTime
     * @param endTime
     */
    @MessageMapping("/backend/produce/runEfficiency/{startTime}/{endTime}")
    public void pushProduceRunEfficiency(@DestinationVariable Long startTime, @DestinationVariable Long endTime) {
        log.info("服務(wù)端接收到消息: startTime={},endTime={}", startTime, endTime);
        if (scheduledTask.get("pushProduceRunEfficiency") == null) {
            ScheduledFuture<?> future = executorService.scheduleAtFixedRate(() -> {
                List<RunVO> runVOList = runEfficiencyService.run(startTime, endTime);
                String destination = "/topic/backend/produce/runEfficiency" + "/" + startTime + "/" + endTime;
                template.convertAndSend(destination, runVOList);
                log.info("已推送信息,每30秒推送一次:{}");
            }, 1, 30, TimeUnit.SECONDS);
            scheduledTask.put("pushProduceRunEfficiency", future);
        }else{
            log.info("定時任務(wù)已開啟!");
        }

    }
    /**
     * 關(guān)閉/backend/produce/runEfficiency/{startTime}/{endTime}接口的定時任務(wù)
     *
     * @author weiq
     */
    @MessageMapping("/close/backend/produce/runEfficiency")
    public void cancelPushProduceRunEfficiency() {
        scheduledTask.forEach((StringKey, future) -> {
            if (future != null && !future.isCancelled() && StringKey.equals("pushProduceRunEfficiency")) {
                // 清除定時任務(wù)的引用
                scheduledTask.remove("pushProduceRunEfficiency");
                boolean cancel = future.cancel(true);
                if (cancel) {
                    log.info("已關(guān)閉定時任務(wù)Key={}",StringKey);
                } else {
                    log.info("失敗定時任務(wù)Key={}",StringKey);
                }
            }
        });
    }

3.前端驗(yàn)證

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
    <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.2.0.min.js"
            integrity="sha256-JAW99MJVpJBGcbzEuXk4Az05s/XyDdBomFqNlM3ic+I=" crossorigin="anonymous"></script>

    <script type="text/javascript">
        var stompClient = null;

        function setConnected(connected) {
            document.getElementById("connect").disabled = connected;
            document.getElementById("disconnect").disabled = !connected;
            $("#response").html();
        }

        function connect() {
            console.log("開始連接吧")
            var socket = new SockJS("http://localhost:8501/ws/public");
            stompClient = Stomp.over(socket);
            stompClient.connect({}, function (frame) {
                setConnected(true);
                console.log('Connected: ' + frame);
                //前端連接完成后,開始訂閱主題
                // stompClient.subscribe('/topic/all', function (response) {
                stompClient.subscribe('/topic/backend/produce/summary', function (response) {
                    var responseData = document.getElementById('responseData');
                    var p = document.createElement('p');
                    p.style.wordWrap = 'break-word';
                    p.appendChild(document.createTextNode(response.body));
                    responseData.appendChild(p);
                });
            }, {});
        }

        function disconnect() {
            if (stompClient != null) {
                stompClient.disconnect();
            }
            setConnected(false);
            console.log("Disconnected");
        }

        //請求地址,向WebSocket 地址發(fā)送消息
        function sendMsg() {
            var content = document.getElementById('content').value;
            // stompClient.send("/all", {}, JSON.stringify({'content': content}));
            stompClient.send("/backend/produce/summary", {}, JSON.stringify({'content': content }));
        }
        //關(guān)閉WebSocket 請求的定時任務(wù)
        function sendMsg1() {
            var content = document.getElementById('content').value;
            // stompClient.send("/all", {}, JSON.stringify({'content': content}));
            stompClient.send("/close/backend/produce/summary", {}, JSON.stringify({'content': content }));
        }
        // function sendMsg1() {
        //     var content = document.getElementById('content').value;
        //     // stompClient.send("/all", {}, JSON.stringify({'content': content}));
        //     stompClient.send("/close/scene/stepActualTime/128", {}, JSON.stringify({'content': content }));
        // }
        //
        // function sendMsg2() {
        //     var content = document.getElementById('content').value;
        //     // stompClient.send("/all", {}, JSON.stringify({'content': content}));
        //     stompClient.send("/close/scene/stepActualTime/219", {}, JSON.stringify({'content': content }));
        // }
    </script>
</head>

<body notallow="disconnect()">
<noscript>
    <h2 style="color: #ff0000">
        Seems your browser doesn't support Javascript! Websocket relies on Javascript being
        enabled. Please enable
        Javascript and reload this page!
    </h2>
</noscript>
<div>
    <div>
        <labal>連接廣播頻道</labal>
        <button id="connect" onclick="connect()">Connect</button>
        <labal>取消連接</labal>
        <button id="disconnect" disabled="disabled" onclick="disconnect()">Disconnect</button>
    </div>

    <div id="conversationDiv">
        <labal>廣播消息</labal>
        <input type="text" id="content"/>
        <button id="sendMsg" onclick="sendMsg();">Send</button>

    </div>
    <div id="conversationDiv1">
        <labal>廣播消息1</labal>
        <input type="text" id="content1"/>
        <button id="sendMsg1" onclick="sendMsg1();">Send</button>

    </div>

<!--    <div id="conversationDiv2">-->
<!--        <labal>廣播消息2</labal>-->
<!--        <input type="text" id="content2"/>-->
<!--        <button id="sendMsg2" onclick="sendMsg2();">Send</button>-->

<!--    </div>-->

    <div>
        <labal>接收到的消息:</labal>
        <p id="responseData"></p>
    </div>
</div>

</body>
</html>

后端啟動,打開HTML測試頁面,可看到運(yùn)行結(jié)果!文章來源地址http://www.zghlxwxcb.cn/news/detail-857290.html

到了這里,關(guān)于前端訂閱后端推送WebSocket定時任務(wù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • Vue使用WebSocket實(shí)現(xiàn)實(shí)時獲取后端推送的數(shù)據(jù)。

    Vue可以使用WebSocket實(shí)現(xiàn)實(shí)時獲取后端推送的數(shù)據(jù)。 1.在Vue項(xiàng)目中安裝WebSocket庫 可以使用npm或yarn安裝WebSocket庫: 2.創(chuàng)建WebSocket連接 在Vue組件中創(chuàng)建WebSocket連接,連接到后端WebSocket服務(wù)器,代碼如下: 上面的代碼中,使用WebSocket連接到后端WebSocket服務(wù)器,通過監(jiān)聽onmessage事件,

    2024年02月08日
    瀏覽(26)
  • Spring定時任務(wù)+webSocket實(shí)現(xiàn)定時給指定用戶發(fā)送消息

    生命無罪,健康萬歲,我是laity。 我曾七次鄙視自己的靈魂: 第一次,當(dāng)它本可進(jìn)取時,卻故作謙卑; 第二次,當(dāng)它在空虛時,用愛欲來填充; 第三次,在困難和容易之間,它選擇了容易; 第四次,它犯了錯,卻借由別人也會犯錯來寬慰自己; 第五次,它自由軟弱,卻把

    2024年02月07日
    瀏覽(30)
  • websockets-后端主動向前端推送消息

    websockets-后端主動向前端推送消息

    公司領(lǐng)導(dǎo)提出了一個新的需求,那就是部門主管在有審批消息的情況下,需要看到提示消息。其實(shí)這種需求最簡單的方法使接入短信、郵件、公眾號平臺。直接推送消息。但是,由于使自研項(xiàng)目,公司領(lǐng)導(dǎo)不想花錢,只能另辟蹊徑。 WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議。

    2024年02月09日
    瀏覽(22)
  • websocket實(shí)時推送統(tǒng)計數(shù)據(jù)給前端頁面

    websocket實(shí)時推送統(tǒng)計數(shù)據(jù)給前端頁面

    前提須知:websocket基本使用 業(yè)務(wù)場景,每秒推送統(tǒng)計數(shù)據(jù)給前端頁面,分別顯示前天,昨天,今天的前十名客戶數(shù)據(jù) @ServerEndpoint(\\\"/smsMCustomerStaTop10Ws\\\") 定義推送數(shù)據(jù)給到具體的連接標(biāo)識 以上 onOpen() 方法最終觸發(fā)的業(yè)務(wù)方法 smsMonitorService.pushSmsMCustomerStaTop10(); 以上 smsMonitorMapper.findSm

    2024年02月15日
    瀏覽(19)
  • SpringBoot集成WebSocket,實(shí)現(xiàn)后臺向前端推送信息

    SpringBoot集成WebSocket,實(shí)現(xiàn)后臺向前端推送信息

    在一次項(xiàng)目開發(fā)中,使用到了Netty網(wǎng)絡(luò)應(yīng)用框架,以及MQTT進(jìn)行消息數(shù)據(jù)的收發(fā),這其中需要后臺來將獲取到的消息主動推送給前端,于是就使用到了MQTT,特此記錄一下。 WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議。它實(shí)現(xiàn)了客戶端與服務(wù)器全雙工通信,學(xué)過計算機(jī)網(wǎng)絡(luò)都知道

    2024年01月16日
    瀏覽(18)
  • Springboot整合WebSocket實(shí)現(xiàn)主動向前端推送消息

    Springboot整合WebSocket實(shí)現(xiàn)主動向前端推送消息

    ? ? ? ? 在上篇文章tcp編程中,我們實(shí)現(xiàn)了C++客戶端與java服務(wù)器之間的通信,客戶端發(fā)送了一個消息給服務(wù)器,今天我們要實(shí)現(xiàn)基于WebSocket實(shí)現(xiàn)服務(wù)器主動向前端推送消息,并且以服務(wù)器接收到C++客戶端的消息主動向前端推送消息的觸發(fā)條件。 WebSocket 的誕生背景 ??????

    2024年03月16日
    瀏覽(22)
  • kafak消費(fèi)數(shù)據(jù),webSocket實(shí)時推送數(shù)據(jù)到前端
  • webSocket推送太快導(dǎo)致前端渲染卡頓問題優(yōu)化

    優(yōu)化思路: 把webSocket接收到的數(shù)據(jù)用一個數(shù)組存起來,達(dá)到一定長度再統(tǒng)一渲染,可根據(jù)推送數(shù)據(jù)的速度適當(dāng)調(diào)解數(shù)組長度限制,如果一段時間內(nèi)改數(shù)組長度打不要渲染條件,就用定時器之間渲染

    2024年02月03日
    瀏覽(18)
  • 蒼穹外賣項(xiàng)目解讀(四) 微信小程序支付、定時任務(wù)、WebSocket

    蒼穹外賣項(xiàng)目解讀(四) 微信小程序支付、定時任務(wù)、WebSocket

    HM新出springboot入門項(xiàng)目《蒼穹外賣》,筆者打算寫一個系列學(xué)習(xí)筆記,“蒼穹外賣項(xiàng)目解讀”,內(nèi)容主要從HM課程,自己實(shí)踐,以及踩坑填坑出發(fā),以技術(shù),經(jīng)驗(yàn)為主,記錄學(xué)習(xí),也希望能給在學(xué)想學(xué)的小伙伴一個參考。 注:本文章是直接拿到項(xiàng)目的最終代碼,然后從代碼出發(fā)

    2024年02月07日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包