WebSocket一對一聊天功能,springboot項目

一個springboot集成websocket一對一聊天的小demo

 

websocket所需的jar包

<dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <classifier>jdk15</classifier>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <version>1.3.5.RELEASE</version>
        </dependency>

 

WebSocketOneToOne

   

package com.cn.ljt.websocket;


import net.sf.json.JSONObject;
import org.springframework.web.bind.annotation.RestController;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ServerEndpoint 註解是一個類層次的註解,它的功能主要是將目前的類定義成一個websocket服務器端,
 *                 註解的值將被用於監聽用戶連接的終端訪問URL地址,客戶端可以通過這個URL來連接到WebSocket服務器端
 */
@RestController
@ServerEndpoint(value = "/webSocketOneToOne/{param}")
public class WebSocketOneToOne {
    // 靜態變量,用來記錄當前在線連接數。應該把它設計成線程安全的。
    private static int onlineCount;
    //實現服務端與單一客戶端通信的話,可以使用Map來存放,其中Key爲用戶標識
    private static Map<String,WebSocketOneToOne> connections = new ConcurrentHashMap<>();
    // 與某個客戶端的連接會話,需要通過它來給客戶端發送數據
    private Session session;
    private String role;
    private String socketId;

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

    /**
     * 連接關閉調用的方法
     */
    @OnClose
    public void onClose() {
        connections.remove(role);  // 從map中移除
        subOnlineCount();          // 在線數減
        System.out.println("有一連接關閉!當前在線人數爲" + getOnlineCount());
    }

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

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


    //發送給指定角色
    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+"說:"+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();
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketOneToOne.onlineCount++;
    }

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

配置websocketConfig

package com.cn.ljt.websocket;

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

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


}

HTML代碼,使用的thymeleaf模板

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script th:src="@{/js/jquery-1.12.4.js}"></script>
    <!--<script type="text/javascript" src="/js/jquery-1.12.4.js" ></script>-->
</head>
<script th:inline="javascript">
    //var usr=[[${usr}]];
    var websocket = null;
    //判斷當前瀏覽器是否支持WebSocket
    if ('WebSocket' in window) {
        //2,123 2登錄用戶標識,123會話id
        //[[${session.usr}]]獲取session的用戶標識
        var url = "ws://" + window.location.host +"/webSocketOneToOne/"+[[${session.usr}]]+",123"
        websocket = new WebSocket(url);
    } else {
        alert('當前瀏覽器 Not support websocket')
    }
    //連接發生錯誤的回調方法
    websocket.onerror = function() {
        setMessageInnerHTML("WebSocket連接發生錯誤");
    };
    //連接成功建立的回調方法
    websocket.onopen = function() {
        setMessageInnerHTML("WebSocket連接成功");
    }
    //接收到消息的回調方法
    websocket.onmessage = function(event) {
        console.log("回調信息",event.data)
        setMessageInnerHTML(event.data);
    }
    //連接關閉的回調方法
    websocket.onclose = function() {
        setMessageInnerHTML("WebSocket連接關閉");
    }
    //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。
    window.onbeforeunload = function() {
        closeWebSocket();
    }
    //將消息顯示在網頁上
    function setMessageInnerHTML(innerHTML) {
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }
    //關閉WebSocket連接
    function closeWebSocket() {
        websocket.close();
    }
    //發送消息
    function send() {
        var message = document.getElementById('text').value;
        //message作爲發送的信息,role作爲發送的對象標識,socketId是此次會話的標識
        websocket.send(JSON.stringify({'message':message,'role':document.getElementById('toname').value,'socketId':"123"}));
    }

</script>
<body>
用戶:<span id="usr" th:text="${session.usr}"></span>
<input id="text" type="text" />
<br/>發送給:<input id="toname" type="text" />
<br/>
<button onclick="send()">發送消息</button>
<button onclick="closeWebSocket()">關閉WebSocket連接</button>
<div id="message"></div>
</body>
</html>

controller 

package com.cn.ljt.controller;

import com.cn.ljt.websocket.WebSocketOneToOne;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;

@Controller
public class UserController {

    @Autowired
    private WebSocketOneToOne webSocketOneToOne;
    /**
     * 登錄界面直接聊天
     * **/
    @RequestMapping("user_1")
    public String user_1(String usr , HttpSession session){
        session.setAttribute("usr",usr);
        return "user_1";
    }
    /**
     * 發送消息 消息內容,發送人,接收人,會話標識
     * **/
    @RequestMapping("message")
    public void message(String msg,String from,String to,String socketId){
        webSocketOneToOne.send(msg, from, to, socketId);

    }
}

瀏覽器輸入http://localhost:8082/user_1?usr=2

 "2"爲用戶的標識

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章