欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用spring?boot+WebSocket實現(xiàn)后臺主動消息推送功能

 更新時間:2022年04月29日 09:29:21   作者:迷途小羔羊678  
目前對于服務(wù)端向客戶端推送數(shù)據(jù),常用技術(shù)方案有輪詢、websocket等,下面這篇文章主要給大家介紹了關(guān)于利用spring?boot+WebSocket實現(xiàn)后臺主動消息推送功能的相關(guān)資料,需要的朋友可以參考下

前言:

使用此webscoket務(wù)必確保生產(chǎn)環(huán)境能兼容/支持!使用此webscoket務(wù)必確保生產(chǎn)環(huán)境能兼容/支持!使用此webscoket務(wù)必確保生產(chǎn)環(huán)境能兼容/支持!主要是tomcat的兼容與支持。

有個需求:

APP用戶產(chǎn)生某個操作,需要讓后臺管理系統(tǒng)部分人員感知(表現(xiàn)為一個頁面消息)。

最早版本是后臺管理系統(tǒng)輪訓,每隔一段時間輪訓一次,由于消息重要,每隔幾秒就查一次。這樣做明顯很不雅!會消耗大量資源,并且大部分請求是沒有用的(查不到數(shù)據(jù)進來),很藍瘦。

后來,想著用消息推送的方式來處理這個邏輯。用戶在app產(chǎn)生了目標操作,即產(chǎn)生一個消息,推送給后臺管理系統(tǒng)的對應(yīng)用戶。

然后我就找各種資料,一開始同事推薦dwz,后來發(fā)現(xiàn)不太適用于目前的項目(也許能實現(xiàn)只是我不知道如何實現(xiàn))。

后來了解到WebSocket,網(wǎng)上看了很多文檔都是類似聊天室的場景,有些不同。在此,我主要側(cè)重介紹下 服務(wù)器主動推送,由服務(wù)端來觸發(fā)。

WebSocket 主要能實現(xiàn)的場景:

1、網(wǎng)頁聊天室

2、服務(wù)器消息實時通知

WebSocket 使用方法應(yīng)該有很多,在次介紹下使用  tomcat8+h5 環(huán)境下的實現(xiàn)。

ps:我自己的測試環(huán)境是tomcat7這樣寫是不行的。wang115032337《https://blog.csdn.net/wang115032337》這位朋友在他的環(huán)境下,tomcat7/8都可以用本文章的寫法,只不過需要去除WebSocketConfig類(有文章表示tomcat7和8對websocket的支持是不同的,本人未深入了解)

話不多說,直接上代碼,想深入了解WebSocket 的請查閱相關(guān)介紹。

1.pom

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

2. 使用@ServerEndpoint創(chuàng)立websocket endpoint( wang115032337這位朋友在他的環(huán)境下加入@ServerEndpoint類會報錯,直接刪除了仍可用)

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

3.具體實現(xiàn)類 可自己選擇url要不要帶參數(shù)

package com.star.manager.service;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
//@ServerEndpoint("/websocket/{user}")
@ServerEndpoint(value = "/websocket")
@Component
public class WebSocketServer {
    //靜態(tài)變量,用來記錄當前在線連接數(shù)。應(yīng)該把它設(shè)計成線程安全的。
    private static int onlineCount = 0;
    //concurrent包的線程安全Set,用來存放每個客戶端對應(yīng)的MyWebSocket對象。
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
    //與某個客戶端的連接會話,需要通過它來給客戶端發(fā)送數(shù)據(jù)
    private Session session;
    /**
     * 連接建立成功調(diào)用的方法*/
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在線數(shù)加1
        log.info("有新連接加入!當前在線人數(shù)為" + getOnlineCount());
        try {
             sendMessage("連接成功");
        } catch (IOException e) {
            log.error("websocket IO異常");
        }
    }
    //    //連接打開時執(zhí)行
    //    @OnOpen
    //    public void onOpen(@PathParam("user") String user, Session session) {
    //        currentUser = user;
    //        System.out.println("Connected ... " + session.getId());
    //    }
 
    /**
     * 連接關(guān)閉調(diào)用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //從set中刪除
        subOnlineCount();           //在線數(shù)減1
        log.info("有一連接關(guān)閉!當前在線人數(shù)為" + getOnlineCount());
    }
 
    /**
     * 收到客戶端消息后調(diào)用的方法
     *
     * @param message 客戶端發(fā)送過來的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("來自客戶端的消息:" + message);
 
        //群發(fā)消息
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
    /**
     * 
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("發(fā)生錯誤");
        error.printStackTrace();
    }
 
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }
 
    /**
     * 群發(fā)自定義消息
     * */
    public static void sendInfo(String message) throws IOException {
        log.info(message);
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                continue;
            }
        }
    }
 
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
 
    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }
 
    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
}

產(chǎn)生一個消息:產(chǎn)生消息場景有多種,http(s),定時任務(wù),mq等,這貼一個httpq請求的controller代碼

     @RequestMapping(value="/pushVideoListToWeb",method=RequestMethod.POST,consumes = "application/json")
     public @ResponseBody Map<String,Object> pushVideoListToWeb(@RequestBody Map<String,Object> param) {
         Map<String,Object> result =new HashMap<String,Object>();
         try {
             WebSocketServer.sendInfo("有新客戶呼入,sltAccountId:"+CommonUtils.getValue(param, "sltAccountId"));
             result.put("operationResult", true);
         }catch (IOException e) {
             result.put("operationResult", true);
         }
         return result;
     }

重要的地方我都加粗了,主要是這段,使用這個方法,可以實現(xiàn)服務(wù)器主動推送。

    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

4.js(html就不寫了,隨便找個能觸發(fā)這個js的就可以)

//socket = new WebSocket("ws://localhost:9094/starManager/websocket/張三");
        var socket;
        if(typeof(WebSocket) == "undefined") {
            console.log("您的瀏覽器不支持WebSocket");
        }else{
            console.log("您的瀏覽器支持WebSocket");
            
            //實現(xiàn)化WebSocket對象,指定要連接的服務(wù)器地址與端口  建立連接
            //socket = new WebSocket("ws://localhost:9094/starManager/websocket/張三")
            socket = new WebSocket("ws://localhost:9094/starManager/websocket");
            //打開事件
            socket.onopen = function() {
                console.log("Socket 已打開");
                //socket.send("這是來自客戶端的消息" + location.href + new Date());
            };
            //獲得消息事件
            socket.onmessage = function(msg) {
                console.log(msg.data);
                //發(fā)現(xiàn)消息進入    調(diào)后臺獲取
                getCallingList();
            };
            //關(guān)閉事件
            socket.onclose = function() {
                console.log("Socket已關(guān)閉");
            };
            //發(fā)生了錯誤事件
            socket.onerror = function() {
                alert("Socket發(fā)生了錯誤");
            }
             $(window).unload(function(){
                  socket.close();
                });
 
//                                    $("#btnSend").click(function() {
//                                        socket.send("這是來自客戶端的消息" + location.href + new Date());
//                                    });
//
//                                    $("#btnClose").click(function() {
//                                        socket.close();
//                                    });
        }

簡單說說:

通過前端代碼 

socket = new WebSocket("ws://localhost:9094/starManager/websocket");

其中,starManager是工程名,/webscoket是訪問路徑名

建立連接,前端調(diào)用scoket.open() 會使后臺在靜態(tài)成員變量webSocketSet里面增加一個元素,相當于一個緩存。后臺服務(wù)調(diào)用sendMessage

(指定某個用戶,定向)或sendInfo(遍歷webSocketSet逐個發(fā)送,類似群發(fā))方法,即可向已登錄的客戶端推送消息。

代碼就這么多。我的用這些代碼就跑的起來。做的時候出現(xiàn)過頁面報404等錯誤,如果也是spring boot+h5,仔細核對下和我代碼有無區(qū)別,加配置 路徑是有ok,問題應(yīng)該不大。

如果你恰好也有可以用WebSocket實現(xiàn)的類似場景,希望對你有幫助。

總結(jié)

到此這篇關(guān)于利用spring boot+WebSocket實現(xiàn)后臺主動消息推送功能的文章就介紹到這了,更多相關(guān)springboot+WebSocket消息推送內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論