pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

SpringBoot+WebSocket實現即時通訊的方法詳解

這篇文章主要為大家詳細介紹了如何利用SpringBoot+WebSocket實現即時通訊功能,文中示例代碼講解詳細,對我們學習或工作有一定參考價值,需要的可以參考一下

環境信息

名稱版本號
Spring Boot2.4.5
Idea2021.3.2

服務端實現

導入依賴

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

注意:Spring Boot在父工程中已經管理了websocket的版本信息,所以不用指定版本號也是可以的

創建配置類

package com.fenzhichuanmei.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * @author Yi Dai 484201132@qq.com
 * @since 2022/5/13 11:34
 */

@Configuration
public class WebsocketConfiguration {

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

}

創建此配置類的目的只是為了把ServerEndpointExporter 這個類的實例交給spring 容器進行管理,您可以用任意一種方式交給容器,如使用@Import(ServerEndpointExporter.class)這種方式等進行操作;此處只是我的編碼風格如此;并非必須這樣操作

創建一個注解式的端點并在其中通過配套注解聲明回調方法

package com.fenzhichuanmei.websocket;

import com.fenzhichuanmei.websocket.utils.SessionManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

/**
 * @author Yi Dai 484201132@qq.com
 * @since 2022/3/7 15:47
 */

@Slf4j
@Component
@ServerEndpoint("/arcticFoxServerEndpoint/{websocketClientType}")
public class ArcticFoxServerEndpoint {

    private static SessionManager sessionManager;

    @Resource
    public void setProcessor(SessionManager sessionManager) {
        ArcticFoxServerEndpoint.sessionManager = sessionManager;
    }

    /**
     * 建立連接成功的回調方法
     *
     * @param session             會話對象
     * @param websocketClientType 此參數就是路徑中{websocketClientType}位置傳入的參數
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("websocketClientType") int websocketClientType) {
        sessionManager.onOpen(session, websocketClientType);
    }

    /**
     * 當會話關閉時執行的回調方法
     *
     * @param session             會話對象
     * @param websocketClientType 此參數就是路徑中{websocketClientType}位置傳入的參數
     */
    @OnClose
    public void onClose(Session session, @PathParam("websocketClientType") int websocketClientType) {
        sessionManager.onClose(session, websocketClientType);
    }

    /**
     * 當收到客戶端信息時執行的回調方法
     *
     * @param session             會話對象
     * @param message             客戶端傳遞過來的信息
     * @param websocketClientType 此參數就是路徑中{websocketClientType}位置傳入的參數
     */
    @OnMessage
    public void onMessage(Session session, String message, @PathParam("websocketClientType") int websocketClientType) {
        sessionManager.onMessage(session, message, websocketClientType);
    }

    /**
     * 當發生錯誤時的回調方法
     *
     * @param session             會話對象
     * @param e                   異常對象
     * @param websocketClientType 此參數就是路徑中{websocketClientType}位置傳入的參數
     */
    @OnError
    public void onError(Session session, Throwable e, @PathParam("websocketClientType") int websocketClientType) {
        sessionManager.onError(session, e, websocketClientType);
    }

}

@ServerEndpoint注解標注此類為一個服務端的端點類,此注解有一個必須的參數,用于指定客戶端訪問的地址,本案例中為:/arcticFoxServerEndpoint,而路徑后面的/{websocketClientType}這個是路徑中參數的占位符,有點類似與Spring Mvc中Rest接口和@PathVariable注解的作用

注意事項: 一定要將此類交給spring 容器進行管理!!還有一個坑就是,此類的實例時非單例的,所以如果要在此類中注入其他的bean,不能使直接在屬性上使用@Resource注解或者@Autowired等注解進行注入,否則會報錯。正確操作應該是把要注入的字段設置為靜態的,然后通過非靜態的set方法進行注入,具體代碼請看上方實例

服務端主動發送消息給客戶端

通過上面的代碼我們可以知道每個回調方法中都會收到一個Session對象,正如您所想,要向客戶端發送消息正是要借助此對象;Session對象有一個getAsyncRemote方法,調用此方法可以得到一個RemoteEndpoint.Async對象,查看此對象,發現有很多send打頭的方法;

是的,這些方法就是發送消息的方法,博主這個項目中主要是通過JSON來進行交互的,所以我使用了sendText方法,示例代碼:

RemoteEndpoint.Async asyncRemote = session.getAsyncRemote();
asyncRemote.sendText(jsonString);

很顯然中轉變量asyncRemote 沒什么太大的用處,不如直接寫成:

session.getAsyncRemote().sendText(jsonString);

通過方法名看到,似乎還可以發送對象,二進制序列等,博主沒有深入研究,有興趣的小伙伴可以嘗試嘗試

客戶端實現

一般來講客戶端應該是用Java Script實現,但是博主這個項目比較特殊,需要用Java來實現客戶端,下面博主先以Java客戶端說明其實現細節,然后再說再前端如何實現

Java客戶端實現

導入依賴

<dependency>
    <groupId>org.java-websocket</groupId>
    <artifactId>Java-WebSocket</artifactId>
    <version>1.5.3</version>
</dependency>

其實Java中實現WebSocket的第三方包還有很多,博主這個地方使用的是Java-WebSocket,有興趣的小伙伴可以試試其他的包

建立連接和處理回調

package com.fenzhichuanmei.websocket;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fenzhichuanmei.components.PaymentComponent;
import com.fenzhichuanmei.pojo.Instructions;
import com.fenzhichuanmei.utils.WebsocketClientType;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.enums.ReadyState;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * @author Yi Dai 484201132@qq.com
 * @since 2022/5/13 10:16
 */

@Slf4j
@Component
public class ArcticFoxWebSocketClient {

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private PaymentComponent paymentComponent;

    @Resource
    private ArcticFoxWebSocketClientProperties properties;

    public void establishConnection() throws URISyntaxException {
        WebSocketClient webSocketClient = new WebSocketClient(new URI(String.format("%s/%d", properties.getWebSocketServerUrl(), WebsocketClientType.PAYMENT_DEVICE))) {
            @Override
            public void onOpen(ServerHandshake serverHandshake) {
                log.info("WebSocketClient: onOpen : {}", serverHandshake);
            }

            @Override
            public void onMessage(String jsonString) {
                try {
                    Instructions instructions = objectMapper.readValue(jsonString, Instructions.class);
                    if (instructions.getType() == Instructions.NOTICE_PAYMENT) {
                        paymentComponent.queryAnUnpaidOrdersAndPay();
                    } else {
                        throw new RuntimeException("錯誤的指令類型");
                    }
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onClose(int i, String s, boolean b) {
                log.info("WebSocketClient: onClose : i:{},s:{},b:{}", i, s, b);
                try {
                    Thread.sleep(1000 * 20);
                    establishConnection();
                } catch (InterruptedException | URISyntaxException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onError(Exception e) {
                log.error("WebSocketClient: onError {}", e.getMessage());
            }
        };
        webSocketClient.connect();
        while (!(webSocketClient.getReadyState() == ReadyState.OPEN)) {
            try {
                Thread.sleep(1000 * 2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        log.info("WebSocketClient: connection established successfully");
    }


    @Data
    @Component
    @ConfigurationProperties("arctic-fox-web-socket-client.properties")
    public static class ArcticFoxWebSocketClientProperties {

        private String webSocketServerUrl;

    }
}

代碼解釋: 其實我的establishConnection方法中上來就實例化了一個WebSocketClient 類的實例,請注意,此類是個抽象類,我在這里用匿名實現類的方式實現的,此類有幾個抽象方法需要實現,也就是onOpen,onMessage,onClose,onError四個方法,其作用其實已經是很見名知意了,和服務端的回調方法一樣,就不過多解釋;實例化此類需要傳入一個URI對象,這個URI對象其實就是封裝了對服務端連接的地址,由于博主不希望把服務端的地址給寫死了,所以我配置到了配置文件中,然后通過String.format靜態方法配合占位符拼接url地址和參數;路徑的規則是:協議名://IP地址(或域名):端口號/服務端聲明的地址/參數;舉個例子:

ws://192.168.88.88:8080/arcticFoxServerEndpoint/1

ws://localhost:8080/arcticFoxServerEndpoint/2

ws://為協議;實例化WebSocketClient 類的實例之后,調用其connect()方法即開始建立連接,調用getReadyState()方法可以獲得其狀態;由于我的服務端可能隨時都連不上,所以我在客戶端的onClose回調函數中進行了一個遞歸(20秒后),用于重新連接。

客戶端向服務端發送消息

通過WebSocketClient 類的實例,我們可以看到有以下方法,很明顯send方法就是用來發送消息使用的

示例代碼:

//判斷一下是否為空
if (Objects.nonNull(webSocketClient)) {
    try {
    	//通過jackson將對象轉換為json字符串(非必須)
        String jsonString = objectMapper.writeValueAsString(feedback);
        //發送信息
        webSocketClient.send(jsonString);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
} else {
    log.warn("no connection established");
}

在前端環境(vue)中使用websocket

安裝reconnecting-websocket包(非必須)

npm i --save reconnecting-websocket

安裝這個包是為了websocket能在斷線之后重新連接,其實不使用這個包也是可以用原生Java Script實現的;但是他和原生的api幾乎一樣;

示例代碼:

import ReconnectingWebSocket from "reconnecting-websocket";

export default function initializationWebsocket() {
    let reconnectingWebSocket = new ReconnectingWebSocket(`ws://localhost:8080/arcticFoxServerEndpoint/${2}`);
    reconnectingWebSocket.onopen = event => {
        console.log("on open :", event);
    };

    reconnectingWebSocket.onmessage = event => {
    	//event對象中data存儲的就是服務端發送過來的消息
        let parse = JSON.parse(event.data);
        console.log("webSocket on message :", parse);
    };

    reconnectingWebSocket.onclose = event => {
        console.log(event);
    };

    reconnectingWebSocket.onerror = event => {
        console.log(event);
    };
	
	//窗口關閉時斷開連接
    window.onbeforeunload = function () {
        reconnectingWebSocket.close();
    }
}

在前端中實現websocket就比較簡單了,就上面的幾行代碼即可,不用調用其他函數進行連接,實例化之后就開始連接了

想服務端發送信息

在前端中發送信息就更簡單了,直接調用reconnectingWebSocketsend方法,傳入要發送的數據即可

到此這篇關于SpringBoot+WebSocket實現即時通訊的方法詳解的文章就介紹到這了,更多相關SpringBoot WebSocket即時通訊內容請搜索html5模板網以前的文章希望大家以后多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

主站蜘蛛池模板: 锌合金压铸-铝合金压铸厂-压铸模具-冷挤压-誉格精密压铸 | 高效复合碳源-多核碳源生产厂家-污水处理反硝化菌种一长隆科技库巴鲁 | 天津力值检测-天津管道检测-天津天诚工程检测技术有限公司 | 电磁铁_小型推拉电磁铁_电磁阀厂家-深圳市宗泰电机有限公司 | 充气膜专家-气膜馆-PTFE膜结构-ETFE膜结构-商业街膜结构-奥克金鼎 | 北京律师事务所_房屋拆迁律师_24小时免费法律咨询_云合专业律师网 | 沈阳楼承板_彩钢板_压型钢板厂家-辽宁中盛绿建钢品股份有限公司 轴承振动测量仪电箱-轴承测振动仪器-测试仪厂家-杭州居易电气 | 体坛网_体坛+_体坛周报新闻客户端 | 土壤有机碳消解器-石油|表层油类分析采水器-青岛溯源环保设备有限公司 | 防水试验机_防水测试设备_防水试验装置_淋雨试验箱-广州岳信试验设备有限公司 | 昆山新莱洁净应用材料股份有限公司-卫生级蝶阀,无菌取样阀,不锈钢隔膜阀,换向阀,离心泵 | 齿辊分级破碎机,高低压压球机,立式双动力磨粉机-郑州长城冶金设备有限公司 | 热回收盐水机组-反应釜冷水机组-高低温冷水机组-北京蓝海神骏科技有限公司 | 超细粉碎机|超微气流磨|气流分级机|粉体改性设备|超微粉碎设备-山东埃尔派粉碎机厂家 | 水性漆|墙面漆|木器家具漆|水漆涂料_晨阳水漆官网 | 插针变压器-家用电器变压器-工业空调变压器-CD型电抗器-余姚市中驰电器有限公司 | 温室大棚建设|水肥一体化|物联网系统 | 万师讲师网-优质讲师培训师供应商,讲师认证,找讲师来万师 | 首页_中夏易经起名网 | 优宝-汽车润滑脂-轴承润滑脂-高温齿轮润滑油脂厂家 | 乐之康护 - 专业护工服务平台,提供医院陪护-居家照护-居家康复 | 布袋除尘器|除尘器设备|除尘布袋|除尘设备_诺和环保设备 | 茶楼装修设计_茶馆室内设计效果图_云臻轩茶楼装饰公司 | 精密五金冲压件_深圳五金冲压厂_钣金加工厂_五金模具加工-诚瑞丰科技股份有限公司 | 北京浩云律师事务所-企业法律顾问_破产清算等公司法律服务 | 植筋胶-粘钢胶-碳纤维布-碳纤维板-环氧砂浆-加固材料生产厂家-上海巧力建筑科技有限公司 | 能量回馈_制动单元_电梯节能_能耗制动_深圳市合兴加能科技有限公司 | 溶氧传感器-pH传感器|哈美顿(hamilton)| 船用烟火信号弹-CCS防汛救生圈-船用救生抛绳器(海威救生设备) | 三效蒸发器_多效蒸发器价格_四效三效蒸发器厂家-青岛康景辉 | 洗砂机械-球磨制砂机-洗沙制砂机械设备_青州冠诚重工机械有限公司 | 陶氏道康宁消泡剂_瓦克消泡剂_蓝星_海明斯德谦_广百进口消泡剂 | 钢衬玻璃厂家,钢衬玻璃管道 -山东东兴扬防腐设备有限公司 | 众品地板网-地板品牌招商_地板装修设计_地板门户的首选网络媒体。 | 阴离子聚丙烯酰胺价格_PAM_高分子聚丙烯酰胺厂家-河南泰航净水材料有限公司 | 海外整合营销-独立站营销-社交媒体运营_广州甲壳虫跨境网络服务 焊管生产线_焊管机组_轧辊模具_焊管设备_焊管设备厂家_石家庄翔昱机械 | 高效复合碳源-多核碳源生产厂家-污水处理反硝化菌种一长隆科技库巴鲁 | 楼梯定制_楼梯设计施工厂家_楼梯扶手安装制作-北京凌步楼梯 | 模具硅橡胶,人体硅胶,移印硅胶浆厂家-宏图硅胶科技 | 防水套管|柔性防水套管|伸缩器|伸缩接头|传力接头-河南伟创管道 防水套管_柔性防水套管_刚性防水套管-巩义市润达管道设备制造有限公司 | 三防漆–水性三防漆–水性浸渍漆–贝塔三防漆厂家 |