WebSocket的使用

一、WebSocket概述

        一般我们前后端交互都是使用http,http是前端发起一个请求,后端回复。它的特点就是前端发起请求后端返回数据,一次交互就没了。而我们在聊天的时候,A给B发送了一个消息,我们后台接收到了消息然后主动推送给B去显示。
websocket是一个双向通信的协议,前后端都可以主动的去发送消息。websocket本质上也是一个请求连接,所以我们也可以像http请求一样传递连接参数。当我们连接成功后,后端会产生一个session,我们可以通过这个session去发消息(它里面提供了一个发送消息的方法)

配置类:

@Configuration
public class WebSocketConfig {

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

二、前端代码

initWebSocket: function (userId,sessionId) {                
	// WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https                
	this.websock = new WebSocket("ws://127.0.0.1:1997/websocket/"+userId+"/"+sessionId);                
	this.websock.onopen = this.websocketonopen;                
	this.websock.onerror = this.websocketonerror;                
	this.websock.onmessage = this.websocketonmessage;                
	this.websock.onclose = this.websocketclose;
},              
websocketonopen: function () {                
	console.log("WebSocket连接成功");    
},              
websocketonerror: function (e) { 
	console.log("WebSocket连接发生错误",e);              
},              
websocketonmessage: function (e) {  
	console.log("获取到后端传递来的数据",e.data);     
},              
websocketclose: function (e) {
	console.log("WebSocket连接关闭",e);                
},
    //开始会话
		startSession(sessionId){
			console.log(sessionId);
			if(this.websock != undefined){
				this.websock.close()
			}
			this.curSessionId = sessionId
			this.initWebSocket(this.curUserId, sessionId)
			this.msgList(sessionId)
		},
	created() { // 页面创建生命周期函数              
		
	},     
	updated(){
		// 解决每次发消息到最后面
		var elmnt = document.getElementById("msg_end");
		elmnt.scrollTop = elmnt.scrollHeight;
	},   
	destroyed: function () { // 离开页面生命周期函数              
		this.websocketclose();        
	},

1、initWebSocket

        我们调用initWebSocket方法就可以和后端建立连接,userIdsessionId就是我们传递的参数。

2、websocketonopen

        websocket连接成功后,就会调用websocketonopen方法。

3、websocketonerror

        websocket连接失败后,就会调用websocketonerror方法

4、websocketonmessage

        当接收到后端发送消息的时候,就会调用 websocketonmessage方法,e.data就是传递的消息内容。

5、websocketclose

        当websocket连接关闭的时候,就会调用这个websocketclose方法。

关闭连接的原因有很多,后端异常、网络异常等一些原因,所以我们可以在这里考虑如何做中断后重连

三、后端代码

     @OnOpen
    public void onOpen(Session session,@PathParam(value="userId")Integer userId, @PathParam(value="sessionId")String sessionId) {
        this.session = session;
        CurPool.webSockets.put(userId,this);
        List<Object> list = new ArrayList<>();
        list.add(sessionId);
        list.add(session);
        CurPool.sessionPool.put(userId , list);
        System.out.println("【websocket消息】有新的连接,总数为:"+CurPool.webSockets.size());
    }

    @OnClose
    public void onClose() {
        // 断开连接删除用户删除session
        Integer userId = Integer.parseInt(this.session.getRequestParameterMap().get("userId").get(0));
        CurPool.sessionPool.remove(userId);
        CurPool.webSockets.remove(userId);
        if (userMapper == null){
            this.userMapper = (UserMapper)SpringContextUtil.getBean("userMapper");
        }
        User user = userMapper.selectByPrimaryKey(userId);
        CurPool.curUserPool.remove(user.getName());
        System.out.println("【websocket消息】连接断开,总数为:"+CurPool.webSockets.size());
    }

    @OnMessage
    public void onMessage(String message) {
        String sessionId = this.session.getRequestParameterMap().get("sessionId").get(0);
        if (sessionId == null){
            System.out.println("sessionId 错误");
        }
        // 在这里无法注入Mapper所以使用这种方式注入Mapper
        if (seesionListMapper == null){
            this.seesionListMapper = (SeesionListMapper)SpringContextUtil.getBean("seesionListMapper");
        }
        if (userMapper == null){
            this.userMapper = (UserMapper)SpringContextUtil.getBean("userMapper");
        }
        if (msgInfoMapper == null){
            this.msgInfoMapper = (MsgInfoMapper)SpringContextUtil.getBean("msgInfoMapper");
        }
        SessionList sessionList = seesionListMapper.selectByPrimaryKey(Integer.parseInt(sessionId));
        User user = userMapper.selectByPrimaryKey(sessionList.getUserId());
        MsgInfo msgInfo = new MsgInfo();
        msgInfo.setContent(message);
        msgInfo.setCreateTime(new Date());
        msgInfo.setFromUserId(sessionList.getUserId());
        msgInfo.setFromUserName(user.getName());
        msgInfo.setToUserId(sessionList.getToUserId());
        msgInfo.setToUserName(sessionList.getListName());
        msgInfo.setUnReadFlag(0);
        // 消息持久化
        msgInfoMapper.insert(msgInfo);

        // 判断用户是否存在,不存在就结束
        List<Object> list = CurPool.sessionPool.get(sessionList.getToUserId());
        if (list == null || list.isEmpty()){
            // 用户不存在,更新未读数
            seesionListMapper.addUnReadCount(sessionList.getToUserId(),sessionList.getUserId());
        }else{
            // 用户存在,判断会话是否存在
            String id = seesionListMapper.selectIdByUser(sessionList.getToUserId(), sessionList.getUserId())+"";
            String o = list.get(0) + "";
            if (id.equals(o)){
                // 会话存在直接发送消息
                sendTextMessage(sessionList.getToUserId(),JsonUtils.objectToJson(msgInfo));
            }else {
                // 判断会话列表是否存在
                if (id == null || "".equals(id) || "null".equals(id)){
                    // 新增会话列表
                    SessionList tmpSessionList = new SessionList();
                    tmpSessionList.setUserId(sessionList.getToUserId());
                    tmpSessionList.setToUserId(sessionList.getUserId());
                    tmpSessionList.setListName(user.getName());
                    tmpSessionList.setUnReadCount(1);
                    seesionListMapper.insert(tmpSessionList);
                }else {
                    // 更新未读消息数量
                    seesionListMapper.addUnReadCount(sessionList.getToUserId(),sessionList.getUserId());
                }
                // 会话不存在发送列表消息
                List<SessionList> sessionLists = seesionListMapper.selectByUserId(sessionList.getToUserId());
                sendTextMessage(sessionList.getToUserId() ,JsonUtils.objectToJson(sessionLists));
            }
        }
        System.out.println("【websocket消息】收到客户端消息:"+message);
    }

1、onOpen

        前端调用连接的时候,就会调用这个方法。我们可以拿到当前连接的session和传递的参数。

我们在这里去保存这个session,后面发消息需要用到

   2、onClose

        当连接中断的时候,会调用这个方法。

我们可以在这里去清除这个session

3、onMessage

        当前端向我们发消息(this.websock.send(content))的时候,就进入了这个方法

我们可以通过this.session拿到当前发消息的session(具体的代码可以看下源码)

4、sendTextMessage

        发送文本消息,我们通过 session.getBasicRemote().sendText(message) 这个方法主动的向前端推送消息。前端的websocketonmessage方法就可以接收到我们的消息了。

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值