SpringBoot實現(xiàn)websocket實現(xiàn)聊天

Maven依賴:

         <!--screw依賴-->
        <dependency>
            <groupId>cn.smallbun.screw</groupId>
            <artifactId>screw-core</artifactId>
            <version>1.0.2</version>
        </dependency>
        <!--hutools-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.12</version>
        </dependency>
        <!--javaee-api-->
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        <!--json-lib-->
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <classifier>jdk15</classifier>
        </dependency>
        <!--websocket-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

在線模擬websocket請求工具:
https://www.bejson.com/httputil/websocket/

websocketConfig:


/**
 * websocket配置
 */
@Configuration
public class websocketConfig {
    /**
     * 服務(wù)器端點導(dǎo)出器
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

WebSocketOneToOne:

/**
 * @ServerEndpoint 注解是一個類層次的注解,它的功能主要是將目前的類定義成一個websocket服務(wù)器端,
 *                 注解的值將被用于監(jiān)聽用戶連接的終端訪問URL地址,客戶端可以通過這個URL來連接到WebSocket服務(wù)器端
 */
@RestController
@ServerEndpoint(value = "/webSocketOneToOne/{param}")
public class WebSocketOneToOne {

    // 靜態(tài)變量,用來記錄當(dāng)前在線連接數(shù)。應(yīng)該把它設(shè)計成線程安全的。
    private static int onlineCount;
    //實現(xiàn)服務(wù)端與單一客戶端通信的話,可以使用Map來存放,其中Key為用戶標(biāo)識
    private static Map<String,WebSocketOneToOne> connections = new ConcurrentHashMap<>();
    // 與某個客戶端的連接會話,需要通過它來給客戶端發(fā)送數(shù)據(jù)
    private Session session;
    //角色
    private String role;
    //socketid
    private String socketId;

    /**
     * 連接建立成功調(diào)用的方法
     *
     * @param session
     *            可選的參數(shù)。session為與某個客戶端的連接會話,需要通過它來給客戶端發(fā)送數(shù)據(jù)
     */
    @OnOpen
    public void onOpen(@PathParam("param") String param, Session session) {
        this.session = session;
        String[] arr = param.split(",");
        this.role = arr[0];             //用戶標(biāo)識
        this.socketId = arr[1];         //會話標(biāo)識
        connections.put(role,this);     //添加到map中
        addOnlineCount();               // 在線數(shù)加
        System.out.println("有新連接加入!新用戶:"+role+",當(dāng)前在線人數(shù)為" + getOnlineCount());
    }

    /**
     * 連接關(guān)閉調(diào)用的方法
     */
    @OnClose
    public void onClose() {
        connections.remove(role);  // 從map中移除
        subOnlineCount();          // 在線數(shù)減
        System.out.println("有一連接關(guān)閉!當(dāng)前在線人數(shù)為" + getOnlineCount());
    }

    /**
     * 收到客戶端消息后調(diào)用的方法
     *
     * @param message
     *            客戶端發(fā)送過來的消息
     * @param session
     *            可選的參數(shù)
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("來自客戶端的消息:" + message);
        JSONObject json=JSONObject.fromObject(message);
        String string = null;  //需要發(fā)送的信息
        String to = null;      //發(fā)送對象的用戶標(biāo)識
        if(json.has("message")){
            string = (String) json.get("message");
        }
        if(json.has("role")){
            to = (String) json.get("role");
        }
        send(string,role,to,socketId);
    }

    /**
     * 發(fā)生錯誤時調(diào)用
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("發(fā)生錯誤");
        error.printStackTrace();
    }


    //發(fā)送給指定角色
    public void send(String msg,String from,String to,String socketId){
        try {
            //to指定用戶
            WebSocketOneToOne con = connections.get(to);
            if(con!=null){
                if(socketId==con.socketId||con.socketId.equals(socketId)){
                    con.session.getBasicRemote().sendText(from+"說11:"+msg);
                }

            }
            //from具體用戶
            WebSocketOneToOne confrom = connections.get(from);
            if(confrom!=null){
                if(socketId==confrom.socketId||confrom.socketId.equals(socketId)){
                    confrom.session.getBasicRemote().sendText(from+"說:"+msg);
                }

            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 獲取在線人數(shù)
     * @return
     */
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    /**
     * 在線數(shù)添加
     */
    public static synchronized void addOnlineCount() {
        WebSocketOneToOne.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketOneToOne.onlineCount--;
    }
}

用戶1

連接請求:

ws://127.0.0.1:8888/webSocketOneToOne/1,520

JSON消息內(nèi)容:

{ 'message': '2號用戶你好', 'role': '2', 'socketId': '520' }

用戶2

連接請求:

ws://127.0.0.1:8888/webSocketOneToOne/2,520

JSON消息內(nèi)容:

{ 'message': '1號用戶你好', 'role': '1', 'socketId': '520' }

理解性

message:需要發(fā)送的消息內(nèi)容
role:需要發(fā)送的對象
socketId:需要發(fā)送的房間

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容