IM系统第二章 – 搜索好友和添加好友

问题:你是如何实现该功能的?

首先,我们得知道该功能的实现流程。

当客户端A 从窗体打开搜索栏时 — 》开始搜索 — 》搜索好友 — 》搜索完成 — 》处理结果 — 》用户点击添加好友 — 》添加操作 — 》执行添加 — 》双向添加好友 — 》处理结果 — 》显示

上面的流程用图概括就是(图片参照 小傅哥)

实现流程图中的主要功能涉及到的操作为:

  1. 自定义协议
  2. 客户端实现搜索好友的处理
  3. 服务端实现搜索好友的处理
  4. 客户端实现添加好友的处理
  5. 服务端实现添加好友的处理

自定义协议:(协议是用来交流的基本,双方都需要遵循这个协议才能进行数据传送)

需要实现四个协议:搜索好友的请求协议、添加好友的请求协议、搜索好友请求响应的协议、添加好友请求响应的协议

// 协议抽象类
public abstract class Packet{private final static Map<Byte,Class<? extends Packet>> packetType = new ConcurrentHashMap<>();static{packetType.put(Command.SearchFriendRequest, SearchFriendRequest.class);packetType.put(Command.SearchFriendResponse, SearchFriendResponse.class);packetType.put(Command.AddFriendRequest, AddFriendRequest.class);packetType.put(Command.AddFriendResponse, AddFriendResponse.class);}....
}

四个协议都作为单独的类来实现:

// 搜索好友请求 协议
public class SearchFriendRequest extends Packet{private String userId; // 用户Idprivate String searchKey; // 搜索字段 get()/set()...
}// 搜索好友请求应答 协议
public class SearchFriendResponse extends Packet {// 存储用户 数据传输对象 的集合private List<UserDto> list;
}// 添加好友请求协议
public class AddFriendRequest extends Packet {private String userId; // 自己的Idprivate String friendId; // 好友的Idget()/set()...
}// 添加好友请求应答的协议
public class AddFriendResponse extends Packet{private String friendId; // 好友的Idprivate String friendNickName; // 好友的昵称private String friendHead; // 好友的头像get()/set()...
}

再来看看 传输数据对象 (DTO):也就是说客户端和服务端之间 真正传送的数据对象是这些。

// 用户 数据传输对象
public class UserDto {private String userId; // 用户Idprivate String userNickName; // 用户昵称private String userHead; // 用户头像private Integer status; // 状态:0添加、1【保留】、2已添加构造函数...get()/set()...
}// 用户 模糊对象
public class LuckUserInfo{private String userId;       //用户IDprivate String userNickName; //用户昵称private String userHead;     //用户头像private Integer status;      // 状态;0添加、1[保留]、2已添加构造函数...get()/set()...
}// 用户好友
public class UserFriend {private Long id; // 自增IDprivate String userId; // 用户IDprivate String userFriendId; // 好友用户IDprivate Date createTime; // 创建时间private Date updateTime; // 更新时间构造函数...get()/set()...
}

自定义完协议后,开始实现 客户端和UI界面的搜索好友的 逻辑(这段简略说说就好)

搜索好友 客户端:

// 搜索好友 处理器
public class SearchFriendHandler extends SimpleChannelInboundHandler<SearchFriendResponse> {private UIService uiService;public SearchFriendHandler(UIService uiService) {this.uiService = uiService;}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, SearchFriendResponse msg) throws Exception {List<UserDto> list = msg.getList();if(null == list || list.isEmpty()) return;IChatMethod chat = uiService.getChat();Platform.runLater(() -> {for (UserDto user : list) {// 界面出现好友 “添加好友”的字样(类似于你搜索好友后,你要点击是否添加)chat.addLuckFriend(user.getUserId(), user.getUserNickName(), user.getUserHead(), user.getStatus());}});}
}

刚开始学的时候我有个疑问?就是为什么继承这个SimpleChannelInboundHandler 泛型的类型是请求应答 的协议 — 》 应该是客户端需要和UI界面进行对接,所以需要将请求应答返回的数据 传给UI进行处理。(而请求 协议本就没有带很多对象的集合信息,只是单个对象的信息)

搜索好友 服务端:

/*
注释:
这里的MyBizHandler也是一个抽象类,该类继承了SimpleChannelInboundHandler<T>类,该类还自己创建了channelRead()抽象方法由继承MyBizHandler的子类去实现
下面中的UserService是操作数据库的一个接口类
*/
public class SearchFriendHandler extends MyBizHandler<SearchFriendRequest> {@Overridepublic void channelRead(Channel channel, SearchFriendRequest msg) {logger.info("搜索好友请求的结果:{}",JSON.toJSONString(msg));// 创建 存储用户数据传输对象 的集合List<UserDto> userDtoList = new ArrayList<>();// 通过Id、Key获取到模糊用户信息的集合List<LuckUserInfo> luckUserInfoList  = userService.queryFuzzyUserInfoList(msg.getUserId(), msg.getSearchKey());UserDto userDto = new UserDto();userDto.setUserId(userInfo.getUserId());userDto.setUserNickName(userInfo.getUserNickName());userDto.setUserHead(userInfo.getUserHead());userDto.setStatus(userInfo.getStatus());userDtoList.add(userDto);}SearchFriendResponse response = new SearchFriendResponse();response.setList(userDtoList);channel.writeAndFlush(response);}
}

添加好友 客户端:

AddFriendResponse协议中获取到的 friendId、friendNickName、FriendHead 传送给 UI界面进行处理。

public class AddFriendHandler extends MyBizHandler<AddFriendResponse> {public AddFriendHandler(UIService uiService) {super(uiService);}@Overridepublic void channelRead(Channel channel, AddFriendResponse msg) {IChatMethod chat = uiService.getChat();Platform.runLater(() -> {chat.addFriendUser(true, msg.getFriendId(), msg.getFriendNickName(), msg.getFriendHead());});}
}

添加好友 服务端:

通过 添加好友请求协议的 userId(自己Id)和friendId(好友Id)来创建 “彼此的好友” 然后来添加到userFriendList;然后通过friendId 在数据库查询到好友用户信息,将查询到的用户属性包装在AddFriendResponse协议上在自己的channel管道传输;同理,通过 userId 在数据库中查询到自己的用户信息,将查询到的用户信息属性包装在 AddFriendResponse协议上在属于好友的channel管道传输。

public class AddFriendHandler extends MyBizHandler<AddFriendRequest> {@Overridepublic void channelRead(Channel channel, AddFriendRequest msg) {// 1.添加好友到数据库 A->B  B->AList<UserFriend> userFriendList = new ArrayList<>();userFriendList.add(new UserFriend(msg.getUserId(),msg.getFriendId()));userFriendList.add(new UserFriend(msg.getFriendId(),msg.getUserId()));// 从数据库中查询 好友信息UserInfo userInfo = userService.queryUserInfo(msg.getFriendId());channel.writeAndFlush(new AddFriendResponse(userInfo.getUserId(),userInfo.getUserNickName(), userInfo.getUserHead()));Channel friendChannel = socketChannelUtil.getChannel(msg.getFriendId());if(friendChannel == null) return;// 从数据库中查询 自己信息UserInfo friendInfo = userService.queryUserInfo(msg.getUserId());friendChannel.writeAndFlush(new AddFriendResponse(friendInfo.getUserId(), friendInfo.getUserNickName(), friendInfo.getUserHead()));}
}

总结:

这个 添加和搜索好友的功能步骤也是先通过自定义协议后,然后再去创建所需要的数据传输对象(DTO)和需要的model对象后才进行客户端和服务端的操作的;在客户端和服务端的操作中,主要是服务端需要写入具体的实现逻辑(比如,如何根据 搜索好友 协议下的信息去处理,如何根据 添加好友 协议下的信息去处理 等等。。)客户端的操作主要是收到 服务端将 请求应答的 协议包装好的信息后,与UI模块的信息进行处理(这部分就略微知道就好了)。

IM系统第二章 -- 搜索好友和添加好友相关推荐

  1. VLSI数字信号处理系统——第二章迭代边界

    VLSI数字信号处理系统--第二章迭代边界 作者:夏风喃喃 参考:VLSI数字信号处理系统:设计与实现 (美)Keshab K.Parhi/著 文章目录 VLSI数字信号处理系统--第二章迭代边界 一 ...

  2. AcWing算法提高课 Level-3 第二章 搜索

    池塘计数 题目 提交记录 讨论 题解 视频讲解 农夫约翰有一片 N∗M 的矩形土地. 最近,由于降雨的原因,部分土地被水淹没了. 现在用一个字符矩阵来表示他的土地. 每个单元格内,如果包含雨水,则用& ...

  3. 人工智能导论 第二章 搜索技术

    2.1 搜索的基本概念 搜索:一种求解问题的一般方法 问题求解的基本方法:搜索法.归约法.归结法.推理法及产生式 基本问题: 1.是否一定能找到一个解 2.找到的是否是最佳解 3.时间和空间复杂度 4 ...

  4. 第二章 搜索 【未完结】

    目录 Flood Fill 1097. 池塘计数[难度: 简单 / 知识点: 基本板子] 1098. 城堡问题 [难度: 一般 / 知识点: 二进制取位] 1106. 山峰和山谷[难度: 中 / 知识 ...

  5. 信号与系统 第二章 卷积总结 δ函数

  6. 【 linux系统入门管理篇-第二章文件和用户的管理】

    linux系统入门管理篇-第二章文件和用户的管理 本章介绍 一.文件管理 (一).Linux目录结构 (二).文件管理 1.文件管理命令 2.文件类型 二.用户管理 (一).用户/组基本概念 (二). ...

  7. 管理系统中计算机应用第二章思维导图,第二章 项目范例:剖析网络订票系统 课件(15张PPT)...

    第二章 项目范例:剖析网络订票系统 课件(15张PPT) 2.1 信息系统及其组成 2.2 信息系统的功能 2.3 信息系统中的计算机和移动终端 第二章 信息系统的组成与功能 教材p29-p33 信息 ...

  8. 【项目开发实战】第二章——在线商城系统

    系列文章目录 第一章--AI人机对战版五子棋游戏 第二章--在线商城系统 文章目录 系列文章目录 前言 1.项目介绍 2.项目规划分析 2.1 电子商务的简要介绍 2.2 在线博客+商城系统构成模块 ...

  9. 鸟哥的Linux私房菜(基础篇)-第二章、 Linux 如何学习(二.3. 有心朝Linux作业系统学习者的学习态度)

    第二章. Linux 如何学习 最近更新日期:2009/08/06 3. 有心朝Linux作业系统学习者的学习态度 3.1 从头学习Linux基础 3.2 选择一本易读的工具书 3.3 实作再实作 3 ...

最新文章

  1. javaScript常用知识点有哪些
  2. JVM—堆栈 堆 方法区 静态区 final static 内存分配
  3. c++中algorithm头文件、STL库简介及使用说明
  4. python执行adb命令_Python实现对adb命令封装
  5. matlab怎么求imf图,MATLAB中提取EMD分解后的每个IMF图像,并导出每个IMF数据
  6. mini_Xception架构
  7. Matplotlib库使用总结
  8. 高德地图设置中国经纬度范围
  9. 彻底删除vmware
  10. html报406错误,Ajax请求出现406的原因和解决方法
  11. Xshell6复制粘贴快捷设置
  12. 【读书笔记】《码农翻身》——一本差点被书名耽误的好书
  13. C#写入注册表打印异常提示无法写入到注册表项
  14. 2013年第四届C/C++ A组蓝桥杯省赛真题
  15. 计算机接口电路的种类,接口电路的分类_接口电路的功能_接口电路的作用是什么...
  16. 永中科技剥离台资百慕大是”执政败笔“
  17. php打印99乘法表加粗,PHP基础循环语句之打印99乘法表
  18. TLint for 虎扑体育应用源码项目
  19. 江苏省宿迁市谷歌高清卫星地图下载
  20. 制作集成SATA驱动的xp安装盘

热门文章

  1. 【3DsMAX】从零开始建房(4)
  2. Spark写入数据到Hbase(下)解决scala.Predef$.refArrayOps([Ljava/lang/Object;)Lscala/collection/mutable/ArrayOps
  3. python中matplotlib库的学习1
  4. android kill 命令杀死进程,【Android 应用开发】Android 杀进程总结 ( 杀后台进程 | 杀前台进程 | 杀其它进程 )...
  5. vscode中使用git,超级无敌简单
  6. 微信发红包场景写测试用例
  7. 【PR】PR在有原视频的情况下去除字幕视频水印学习记录
  8. 饥荒云服务器存档在哪个文件夹,饥荒存档位置的位置在哪里?如何添加别人的存档?...
  9. C语言---检查IPV4、MAC地址是否合法
  10. 在Windows下和MacBook中如何查找本地的字体文件