Spring boot + LayIM + t-io 好友申请的处理以及上下线通知的实现


声明:本文转载自https://my.oschina.net/panzi1/blog/1590695,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

前言

    在上一篇中已经完成了好友申请的流程。本篇就是对申请处理流程的简单讲解。核心知识点在前几篇中已经介绍过很多次了,所以本篇也算是和推送部分有关的最终篇了。后续就继续踏踏实实学习其他的东西吧。

申请处理

    申请的处理流程如下:

    同意申请:更新消息状态,新增系统消息,加为好友,推送消息

    拒绝申请:更新消息状态,新增系统消息,推送消息

代码实现

    首先,在UI上,LayIM已经做的很棒了。点击同意事件已经写好,所以要做的就是对接后台的逻辑。

    

上图弹层代码:

             layim.setFriendGroup({                     type: 'friend'                     , username: user.username                     , avatar: user.avatar                     , group: parent.layui.layim.cache().friend //获取好友分组数据                     , submit: function (mygroup, index) {                         req.post('/layim/apply/agree/' + id, {                             group: mygroup                         }, function (res) {                             if (res.code != 0) {                                 return layer.msg(res.msg);                             }else{                                 //将好友追加到主面板                                 parent.layui.layim.addList({                                     type: 'friend'                                     , avatar: user.avatar //好友头像                                     , username: user.username //好友昵称                                     , groupid: mygroup //所在的分组id                                     , id: uid //好友ID                                     , status:res.data.status//好友状态                                     , sign: user.sign //好友签名                                 });                                 parent.layer.close(index);                                 othis.parent().html('已同意');                             }                         });                     }                 });

可以注意到,这里用到了 setFriendGroup方法和addList方法。前者就是加好友的界面,后者就是将用户添加到好友列表中。

    加好友逻辑不在赘述,主要是加好友成功之后要做两件事情,第一件,通知对方“xx同意加你为好友”。第二,将当前用户信息动态的加入到对方的好友列表中。这里要注意的是,同意添加之后要返回对方好友的在线状态,以便根据状态对好友头像做置灰处理。

    判断是否在线的方法如下:(应该会有其他方法)

 /**      * 判断一个用户是否在线      * */     public static boolean isOnline(long userId){         ChannelContext channelContext = getServerGroupContext()                 .users.find(getServerGroupContext(),userId+"");         return channelContext!=null && !channelContext.isClosed()&&!channelContext.isRemoved();     }

    通过看源码,可以知道根据用户ID获取channelContext,是通过一个map来实现的

private ObjWithLock<DualHashBidiMap<String, ChannelContext>> map =  new ObjWithLock<>(new DualHashBidiMap<String, ChannelContext>());

    其实本来我的写法是直接调用  map.getObj().containsKey(userId) 方法.后来查看源代码,发现还需要加锁。对锁的研究比较少,所以还是老老实实用了框架提供的find方法,然后对channelContext进行状态的判断。

/** 	 * Find. 	 * 	 * @param userid the userid 	 * @return the channel context 	 */ 	public ChannelContext find(GroupContext groupContext, String userid) { 		if (groupContext.isShortConnection()) { 			return null; 		}  		if (StringUtils.isBlank(userid)) { 			return null; 		} 		String key = userid; 		Lock lock = map.getLock().readLock(); 		DualHashBidiMap<String, ChannelContext> m = map.getObj();  		try { 			lock.lock(); 			return m.get(key); 		} catch (Exception e) { 			throw e; 		} finally { 			lock.unlock(); 		} 	}

    当调用同意添加好友接口之后,返回结果为:

    

    然后页面调用layim.addList方法,就可以将该用户动态加入到好友列表中

    

    同样我们在示范一遍,重新申请,然后申请人保留在线状态。

    

    大家看出区别了吗?不过目前这里有个小瑕疵,就是没有好友签名。不过无伤大雅,下次登录就可以了。

上下线通知

    其实从上文中的截图可以看到,头像有灰色有亮色同QQ一样来表示好友的在线状态。这个要归功于LayIM的好友属性中的 status 属性,它有onlineoffline两个值。我们可以通过一下方法实现头像的置灰功能。

layim.setFriendStatus(userId, 'offline');  layim.setFriendStatus(userId, 'online');

    下面回到我们的LayimMsgHandler当中,在处理handshake事件之后,之前已经介绍过绑定用户和绑定群组,最后呢要给所有在线的好友发送一个上线通知。具体通知方法如下:

  /**      * 通知该用户的好友上线消息      * */     private void notify(ChannelContext channelContext,boolean online) throws IOException{         long uid = Long.parseLong(channelContext.getUserid());         //获取用户所有的好友ID         List<String> allFriendIds = getUserService().getAllFriends(uid);         if(allFriendIds.size()==0){             return;         }         //构建消息体         LayimToClientOnlineStatusMsgBody msgBody = new LayimToClientOnlineStatusMsgBody(uid,online);         WsResponse statusPacket = BodyConvert.getInstance().convertToTextResponse(msgBody);          //调用sendToAll的方法         Aio.sendToAll(channelContext.getGroupContext(), statusPacket, filterChannelContext -> {             //筛选掉已经移除和关闭的连接             if(filterChannelContext.isRemoved()||filterChannelContext.isClosed()) {                 return false;             }             //筛选掉非当前用户好友的连接             String channelContextUserid = filterChannelContext.getUserid();             boolean exists = allFriendIds.stream().anyMatch(friendUserId ->                      friendUserId.equals(channelContextUserid));             return exists;         });     }

    所以,在handshake成功之后,调用一下 notify(channelContext,true) 方法实现上线消息推送,当触发onClose方法的时候,调用notify(channelContext,false)的方法实现下线消息推送。

   @Override     public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext)              throws Exception {         notify(channelContext,false);         Aio.remove(channelContext,"onClose");         return null;     }

    最后呢,初始化好友列表的时候还要做一个事情,就是已经在线的应该是亮色,不在线的是灰色,还要注意在线的排序在前边。排序方法,我们让UserViewModel实现ComparablecompareTo方法。

 public void setSort(Integer sort) {         this.status = sort==1?"online":"offline";         this.sort = sort;     }      private int sort;      @Override     public int compareTo(Object o) {         UserViewModel o1 = (UserViewModel) o;         return o1.getSort().compareTo(this.getSort());     }

    排序效果如下:

    

功能演示

    首先用“皇后”账号添加“皇上”为好友,皇上收到通知,准备处理。

    

    此时皇后的好友列表空空如也。

    

    皇上收到好友请求,打开并同意。

    

    此时,皇上的好友列表中增加了好友“皇后”

    

    而皇后的列表中也增加了皇上,并且收到了一条消息。

    

    

    至此整个好友申请处理流程结束。皇后看到皇上批准了好友请求,安心的睡去了。下线走人。

    

总结

    写了这么几篇,其实中心点就是一个,实现推送即可。毕竟业务是活的,可以随时变动,但是推送的中心思想不变。本篇没有介绍什么新东西。无非是业务上的完善。不过多看看源代码还是挺有好处的。多看多学多用,继续加油,希望我的博客能给看到的人一些小小的帮助。

    支持的小伙伴们给个star吧。虽然代码有点乱,后续肯定是要慢慢重构的啦。

    代码地址:https://github.com/fanpan26/SpringBootLayIM

    

本文发表于2017年12月16日 00:33
(c)注:本文转载自https://my.oschina.net/panzi1/blog/1590695,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2829 讨论 0 喜欢 2

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1