HTML5 websocket vue + java 简单使用

5 篇文章 0 订阅
4 篇文章 0 订阅
前端(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):
package com.firefly.wx.controller;

import com.firefly.chatRoomRecode.domain.ChatRoomRecode;
import com.firefly.chatRoomRecode.service.IChatRoomRecodeService;
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;

/**
* @author Hong Jianwei <jianwei.hong @ pactera.com >
* @date 2017/12/11 13:23
*/
@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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值