溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

SpringBoot怎么整合WebSocket實(shí)現(xiàn)后端向前端發(fā)送消息

發(fā)布時(shí)間:2023-03-06 11:39:27 來源:億速云 閱讀:164 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“SpringBoot怎么整合WebSocket實(shí)現(xiàn)后端向前端發(fā)送消息”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“SpringBoot怎么整合WebSocket實(shí)現(xiàn)后端向前端發(fā)送消息”吧!

一、什么是 websocket 接口

使用 websocket 建立長連接,服務(wù)端和客戶端可以互相通信,服務(wù)端只要有數(shù)據(jù)更新,就可以主動(dòng)推給客戶端。

WebSocket 使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)。在 WebSocket API 中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。
在 WebSocket API 中,瀏覽器和服務(wù)器只需要做一個(gè)握手的動(dòng)作,然后,瀏覽器和服務(wù)器之間就形成了一條快速通道。兩者之間就直接可以數(shù)據(jù)互相傳送。

二、適用場景

在業(yè)務(wù)開發(fā)過程中碰到一些異步處理(微信支付、支付寶支付的支付通知),跨應(yīng)用的消息傳遞。

當(dāng)業(yè)務(wù)執(zhí)行完畢后,需要將成功的信息投遞給前端。一般情況下都是前端調(diào)用后端的http/https接口獲取數(shù)據(jù),后端想要主動(dòng)推送消息給前端就需要使用到WebSocket進(jìn)行前后端的通信。

三、示例代碼

3.1、添加pom.xml依賴

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

3.2、創(chuàng)建WebSokcet配置類

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}
3.3、創(chuàng)建WebSokcet工具類
 
@ServerEndpoint(value = "/websocket")
@Component
public class WebSocketServer {
    private final static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
 
    //靜態(tài)變量,用來記錄當(dāng)前在線連接數(shù)。應(yīng)該把它設(shè)計(jì)成線程安全的。
    private static int onlineCount = 0;
    //concurrent包的線程安全Set,用來存放每個(gè)客戶端對應(yīng)的MyWebSocket對象。
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
 
    //與某個(gè)客戶端的連接會(huì)話,需要通過它來給客戶端發(fā)送數(shù)據(jù)
    private Session session;
 
    /**
     * 連接建立成功調(diào)用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        //加入set中
        webSocketSet.add(this);
        //在線數(shù)加1
        addOnlineCount();
        log.info("有新連接加入!當(dāng)前在線人數(shù)為" + getOnlineCount());
        try {
            MsgResponseVo userMsgResponseVo = new MsgResponseVo();
            userMsgResponseVo.setMsg("SUCCESS");
            WebSocketServer.sendInfo(JSON.toJSONString(userMsgResponseVo));
        } catch (IOException e) {
            log.error("websocket IO異常");
        }
    }
 
    /**
     * 連接關(guān)閉調(diào)用的方法
     */
    @OnClose
    public void onClose() {
        //從set中刪除
        webSocketSet.remove(this);
        //在線數(shù)減1
        subOnlineCount();
        log.info("有一連接關(guān)閉!當(dāng)前在線人數(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ā)生錯(cuò)誤");
        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--;
    }
}

3.3、創(chuàng)建測試發(fā)送消息接口

 @GetMapping("/testWebSocket")
    public ApiRestResponse testWebSocket() throws IOException {
        //消息體
        MsgResponseVo technicianMsgResponseVo = new MsgResponseVo();
        technicianMsgResponseVo.setRole("Technician");
        technicianMsgResponseVo.setRoleId(1);
        technicianMsgResponseVo.setMsg("您的訂單已取消");
        technicianMsgResponseVo.setMsgStatus("CANCEL_ORDER");
        technicianMsgResponseVo.setOrderNo("test");
        //發(fā)送消息
        WebSocketServer.sendInfo(JSON.toJSONString(technicianMsgResponseVo));
        return ApiRestResponse.success();
    }
}

3.4、測試webSocket

在網(wǎng)站中輸入ws://ip:端口/webSocket工具類的前綴(ws://127.0.0.1:8080/websocket)

SpringBoot怎么整合WebSocket實(shí)現(xiàn)后端向前端發(fā)送消息

3.5、前端使用WebSocket監(jiān)聽后端WebSocket地址 ,接收到消息后做下一步業(yè)務(wù)處理。

感謝各位的閱讀,以上就是“SpringBoot怎么整合WebSocket實(shí)現(xiàn)后端向前端發(fā)送消息”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對SpringBoot怎么整合WebSocket實(shí)現(xiàn)后端向前端發(fā)送消息這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI