韩顺平Java:qq项目离线发送接收消息/文件扩展

 思路:1、在服务端创建一个ConcurrentHashMap线程安全的集合用来存储离线用户的消息和文件,为了实现每个用户可以保存多条离线消息,我们在键值对value中采用ArrayList来保存多条message消息。

//存放离线留言/文件的集合
    private static ConcurrentHashMap<String, ArrayList<Message>> 
offLineDb = new ConcurrentHashMap<>();

2、 创建ArrayList集合,每个集合对应一个用户,有多少用户就创建多少个集合

public class ManageClientThreads {
    //创建存储不在线用户文件/消息内容的ArrayList<Message> 集合
    private static ArrayList<Message> arrayList1 = new ArrayList<>();
    private static ArrayList<Message> arrayList2 = new ArrayList<>();
    private static ArrayList<Message> arrayList3 = new ArrayList<>();
    private static ArrayList<Message> arrayList4 = new ArrayList<>();
    private static ArrayList<Message> arrayList5 = new ArrayList<>();
    private static ArrayList<Message> arrayList6 = new ArrayList<>();
}

3、 编写一个添加内容的方法,实现把用户对应的message数据存储到ConcurrentHashMap集合中

//添加方法
    public static void addClientOffLineDb(String userid,Message message){
        if (userid.equals("100")) {//如果检测到是100的用户的信息就存在arrayList1中
            arrayList1.add(message);//把message添加到对应的集合中
            offLineDb.put(userid,arrayList1);//添加内容到集合中
        }else if (userid.equals("200")){
            arrayList2.add(message);//把message添加到对应的集合中
            offLineDb.put(userid,arrayList2);//添加内容到集合中
        }else if (userid.equals("300")){
            arrayList3.add(message);//把message添加到对应的集合中
            offLineDb.put(userid,arrayList3);//添加内容到集合中
        }else if (userid.equals("至尊宝")){
            arrayList4.add(message);//把message添加到对应的集合中
            offLineDb.put(userid,arrayList4);//添加内容到集合中
        } else if (userid.equals("紫霞仙子")) {
            arrayList5.add(message);//把message添加到对应的集合中
            offLineDb.put(userid,arrayList5);//添加内容到集合中
        }else if (userid.equals("菩提老祖")){
            arrayList6.add(message);//把message添加到对应的集合中
            offLineDb.put(userid,arrayList6);//添加内容到集合中
        }
    }

4、如果用户不在线我们就调用添加方法,把信息存入集合中

else if (message.getMesType().equals(MessageType.MESSAGE_FILE_MES)){
                    //MessageType.MESSAGE_FILE_MES 文件消息(发送文件)类型
                    //根据message获取getter id,然后在得到对应线程
                    ServerConnectClientThread serverConnectClientThread =
                            ManageClientThreads.getServerConnectClientThread(message.getGetter());
                    if (serverConnectClientThread == null) {//如果用户不在线
                        System.out.println("用户不在线,文件消息存到了offLineDb集合中");
                        //调用方法把message内容存到数组中
                        ManageClientThreads.addClientOffLineDb(message.getGetter(),message);
                    } else {
                        System.out.println("用户在线文件直接转发");
                        //根据getter id 获取到对应的线程,将message对象转发
                        //代码解读:从管理线程的集合中通过message.getGetter()得到对应的线程
                        //在通过线程得到socket,在得到 getOutputStream() 输出流对象,
                        // 最后赋给对象输出流oos
                        ObjectOutputStream oos =
                                new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream());
                        //得到对应socket的对象输出流,将message对象转发给指定的客户端
                        oos.writeObject(message);
                    }

5、判断存储离线消息的集合中是否有刚刚登录用户的消息如果有就转发给他,并把离线消息从集合中删除。

//查找消息集合中是否有u.getUserId() 对应 Message 内容
                    ArrayList clientOffLineDb = ManageClientThreads.getClientOffLineDb(u.getUserId());
                    if (clientOffLineDb != null){
                        //取出ArrayList数组中的message
                        Iterator<Message> iterator = clientOffLineDb.iterator();//迭代器
                        while (iterator.hasNext()) {
                            Message message1 =  iterator.next();//获取对应内容
                            System.out.println(message1);

                            //得到线程对应的输出流 并赋给对象输出流
                            ObjectOutputStream oos1 =
                                    new ObjectOutputStream(ManageClientThreads.getServerConnectClientThread(u.getUserId()).getSocket().getOutputStream());
                            oos1.writeObject(message1);//把消息内容回发
                            ManageClientThreads.removeClientOffLineDb(message1.getGetter());//回发成功把消息内容从数组中移除
                            System.out.println("删除了集合中暂存的消息内容");
                        }
                    }

这里只写了扩展离线接收消息/文件的代码,实现了一个用户可以对多个离线用户发送任意数量的离线消息或文件,如果离线用户上线后接收的所有关于该用户的离线文件则会通过服务器转发给他,并从储存离线文件的集合中删除。

通过这种写法的好处是不用修改客户端的代码,只需要在服务器端进行修改,但是不好之处在于代码冗余度过高,如果有更好的思路希望能与大家交流一下。

效果演示:

登录100号用户给200号用户发送离线消息,200号用户登录成功自动读取离线消息并显示

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值