HTML5 websocket 前后端代码(Vue+Java)简单使用

备忘
前端(Vue):

<template>
  <div></div>
</template>

<script>
  export default {
    name: "chatRoomSurvey",
    data() {
      return {
        chatRoomWebsocket: null
      }
    },
    computed: {
      // ...
    },
    created() {
      // 初始化 websocket
      this.initWebSocket()
    },
    methods: {
      // 初始化 websocket 连接
      initWebSocket() {
        if (typeof WebSocket != 'undefined') {
          this.supported = "支持 websocket"
        } else {
          this.supported = "不支持 websocket"
        }
        //ws地址
        const wsuri = "ws://" + this.currentUrlPath + "/websocket/" + this.$route.params.chatRoomId + "/" + this.$store.state.user.token + "/" + this.chatRoomData.hostUser;
        this.chatRoomWebsocket = new WebSocket(wsuri);
        this.chatRoomWebsocket.onerror = this.websocketOnError
        this.chatRoomWebsocket.onmessage = this.websocketOnMessage
        this.chatRoomWebsocket.onclose = this.websocketOnClose
      },
      //连接发生错误的回调方法
      websocketOnError() {
        console.log("WebSocket 连接发生错误")
      },
      //接收到消息的回调方法
      websocketOnMessage(event) {
        // 接收消息
        let data = JSON.parse(event.data)
        // ...
      },
      //连接关闭的回调方法
      websocketOnClose(e) {
        console.log("WebSocket 连接关闭", e)
        console.log(this.chatRoomWebsocket)
      },
      //关闭 WebSocket 连接
      websocketClose() {
        this.chatRoomWebsocket.close()
      },
      // 判断是否是 url
      isURL(str_url) {
        var strRegex = /^((https|http|ftp|rtsp|mms)?:\/\/)?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]$)|([0-9a-z_!~*'()-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/;
        var re = new RegExp(strRegex);
        return re.test(str_url)
      },
      // 发送消息
      sendContent() {
        let messageData = {
          chatRoomId: this.$route.params.chatRoomId,
          chatUser: this.$store.state.user.token,
          chatAvatar: this.userInfo.userAvatar,
          chatNickName: this.userInfo.userNickNameTem + this.backgroundInfo,
          chatContent: this.text,
          chatType: "1"
        }
        if (this.chatRoomWebsocket.readyState != '1') {
          // 如果按下按钮时socket 不是连接状态,重连并等到连接成功再发送消息
          this.initWebSocket()
          this.chatRoomWebsocket.onopen = () => {
            this.chatRoomWebsocket.send(JSON.stringify(messageData));
            this.content.push({
              askImg: this.userInfo.userAvatar,
              askContent: this.text,
              askNickName: this.userInfo.userNickNameTem + this.backgroundInfo,
              userId: this.chatRoomData.hostUser
            })
            this.$refs.sTest.value = '' // 清空输入框的内容
            // viewbox 移动到最底部
            this.viewboxScrollToBottom()
          }
        } else {
          this.chatRoomWebsocket.send(JSON.stringify(messageData));
          this.content.push({
            askImg: this.userInfo.userAvatar,
            askContent: this.text,
            askNickName: this.userInfo.userNickNameTem + this.backgroundInfo,
            userId: this.chatRoomData.hostUser
          })
          this.$refs.sTest.value = '' // 清空输入框的内容
          // viewbox 移动到最底部
          this.viewboxScrollToBottom()
        }
      },
      // viewbox 移动到最底部
      viewboxScrollToBottom() {
        if (this.$refs.viewBox) {
          this.$nextTick(() => {
            // DOM 更新后再执行
            this.$refs.viewBox.scrollTo(this.$refs.viewBox.getScrollBody().scrollHeight + "55")
          })
        }
      },
    },
    components: {}
  }
</script>

<style scoped>
</style>

后端(Java):

// ...
import net.sf.json.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.SpringConfigurator;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/websocket/{chatRoomId}/{userId}/{hostUserId}")
@Component
public class MyWebSocket {
    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    private static ConcurrentHashMap<String, MyWebSocket> webSocketSet = new ConcurrentHashMap<String, MyWebSocket>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    //当前发消息的聊天室编号
    private String chatRoomId = "";

    //当前发消息的用户编号
    private String userId = "";

    //该次连接所属的聊天室的主持人 id
    private String hostUserId = "";

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(@PathParam(value = "chatRoomId") String param1, @PathParam(value = "userId") String param2, @PathParam(value = "hostUserId") String param3, Session session) throws Exception {
        chatRoomId = param1;
        userId = param2;
        hostUserId = param3;
        this.session = session;
        webSocketSet.put("room" + param1 + "-" + "user" + param2, this); //加入 map 中
        addOnlineCount();           //在线数加1
        System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());

        // 若该用户不是主持人
        if (!userId.equals(hostUserId)) {
            // 普通用户上线时给主持人发送当前房间在线情况
            System.out.println("普通用户上线时给主持人发送当前房间在线情况");
            sendOnlinePersonnel(chatRoomId, hostUserId);
            // 遍历 hashmap 查询主持人是否上线
            for (String key : webSocketSet.keySet()) {
                if (key.equals("room" + param1 + "-" + "user" + hostUserId)) {
                    // 给自己发主持人已上线
                    JSONObject jso = new JSONObject();
                    jso.put("messageType", "2");
                    jso.put("data", true);
                    System.out.println("自己不是主持人,主持人已上线");
                    sendMessage(jso.toString());
                    return;
                }
            }
            // 给自己发主持人未上线
            JSONObject jso = new JSONObject();
            jso.put("messageType", "2");
            jso.put("data", false);
            System.out.println("自己不是主持人,主持人未上线");
            sendMessage(jso.toString());
        } else {
            // 群发主持人已上线
            JSONObject jso = new JSONObject();
            jso.put("messageType", "2");
            jso.put("data", true);
            System.out.println("自己是主持人,主持人已上线");
            sendInfoForAll(chatRoomId, userId, jso.toString());
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() throws Exception {
        System.out.println("当前想要删除的webSocketSet:" + "room" + chatRoomId + "-" + "user" + userId);
        if (!userId.equals("")) {
            webSocketSet.remove("room" + chatRoomId + "-" + "user" + userId);  //从set中删除
            subOnlineCount();           //在线数减1
            System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
            // 若该用户是主持人
            if (userId.equals(hostUserId)) {
                // 给所有人群发发主持人已下线
                JSONObject jso = new JSONObject();
                jso.put("messageType", "2");
                jso.put("data", false);
                sendInfoForAll(chatRoomId, userId, jso.toString());
            } else {
                // 普通用户离线时给主持人发送当前房间在线情况
                System.out.println("普通用户下线时给主持人发送当前房间在线情况");
                sendOnlinePersonnel(chatRoomId, hostUserId);
            }
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) throws Exception {
        JSONObject jsStr = JSONObject.fromObject(message);
        System.out.println("-------------------------------------------");
        // 发来的不是查询在线情况的,也不是公告相关
        if (!jsStr.get("chatType").toString().equals("3") && !jsStr.get("chatType").toString().equals("2")) {
            // 普通文字消息需要保存到数据库中,视频或者图片另有别的后台 api 保存
            if (jsStr.get("chatType").toString().equals("1")) {
                System.out.println("来自客户端的消息:" + jsStr.get("chatContent").toString());
                // 发来的是聊天消息
                ChatRoomRecode chatRoomRecode = new ChatRoomRecode();
                chatRoomRecode.setChatContent(jsStr.get("chatContent").toString());
                chatRoomRecode.setChatRoomId(Long.valueOf(jsStr.get("chatRoomId").toString()));
                chatRoomRecode.setChatUser(Long.valueOf(jsStr.get("chatUser").toString()));
                chatRoomRecode.setChatTime(new java.sql.Date(new Date().getTime()));
                chatRoomRecode.setChatType(jsStr.get("chatType").toString());
                chatRoomRecode.setChatNickName(jsStr.get("chatNickName").toString());
                chatRoomRecode.setChatAvatar(jsStr.get("chatAvatar").toString());

                // 往数据库中存入聊天的信息
                IChatRoomRecodeService chatRoomRecodeService = SpringCtx.getBeanByClass(IChatRoomRecodeService.class);
                Boolean isOK = chatRoomRecodeService.insert(chatRoomRecode);
            }
            // 发送消息
            JSONObject jso = new JSONObject();
            jso.put("chatContent", jsStr.get("chatContent").toString());
            jso.put("chatAvatar", jsStr.get("chatAvatar").toString());
            jso.put("chatNickName", jsStr.get("chatNickName").toString());
            jso.put("chatUser", jsStr.get("chatUser").toString());
            // 普通的消息是 1,主持人上下线的消息是 2
            jso.put("messageType", "1");
            sendInfoForAll(chatRoomId, userId, jso.toString());
        } else if (jsStr.get("chatType").toString().equals("3")) {
            // 发来的是需要查询当前聊天室人员在线情况的消息
            sendOnlinePersonnel(chatRoomId, hostUserId);
        }
    }

    /**
     * 发生错误时调用
     *
     * @OnError
     */
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }


    /**
     * 发送消息
     *
     * @OnError
     */
    public void sendMessage(String message) throws IOException {
//        this.session.getBasicRemote().sendText(message);
        this.session.getAsyncRemote().sendText(message);
    }


    /**
     * 给该聊天室的主持人发送当前聊天室内的人员在线情况
     *
     * @OnError
     */
    public static void sendOnlinePersonnel(String chatRoomId, String hostUserId) throws IOException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("messageType", "3");
        JSONObject jsonObjectPersonnel = new JSONObject();
        // 遍历 hashmap
        for (String key : webSocketSet.keySet()) {
            String[] keyArr = key.split("-");
            // 房间号相同
            if (keyArr[0].equals("room" + chatRoomId)) {
                jsonObjectPersonnel.put(keyArr[1].substring(4), true);
            }
        }
        jsonObject.put("onlinePersonnel", jsonObjectPersonnel);
        if (!(webSocketSet.get("room" + chatRoomId + "-" + "user" + hostUserId) + "").equals("null")) {
            webSocketSet.get("room" + chatRoomId + "-" + "user" + hostUserId).sendMessage(jsonObject.toString());
        }
    }

    /**
     * 群发给该聊天室不是自己的所有人
     *
     * @OnError
     */
    public static void sendInfoForAll(String chatRoomId, String userId, String info) throws IOException {
        // 群发消息
        // 遍历 hashmap
        for (String key : webSocketSet.keySet()) {
            try {
                String[] keyArr = key.split("-");
//                System.out.println("-------------------------------------------");
//                System.out.println("keyArr[0].equals(\"room\" + chatRoomId)");
//                System.out.println(keyArr[0].equals("room" + chatRoomId));
//                System.out.println("!keyArr[1].equals(\"user\" + userId)");
//                System.out.println(!keyArr[1].equals("user" + userId));     && !keyArr[1].equals("user" + userId)
                if (keyArr[0].equals("room" + chatRoomId) && !keyArr[1].equals("user" + userId)) {
                    webSocketSet.get(key).sendMessage(info);
                }
            } catch (IOException e) {
                System.out.println("e:" + e);
                e.printStackTrace();
            }
        }
    }

    /**
     * 群发自定义消息
     */
//    public static void sendInfo(String message) throws IOException {
//        for (MyWebSocket item : webSocketSet) {
//            try {
//                item.sendMessage(message);
//            } catch (IOException e) {
//                continue;
//            }
//        }
//    }
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

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

    public static synchronized void subOnlineCount() {
        MyWebSocket.onlineCount--;
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值