韩顺平Javaweb:qq项目离线发消息和传输文件的实现

public class QQServer {
    private ServerSocket ss=null;
    //创建一个集合,存放多个用户,如果是这些用户登录就认为是合法的
    //ConcurrentHashMap也可以,线程安全
    private static ConcurrentHashMap<String,User> validUsers=new ConcurrentHashMap<>();
    public static ConcurrentHashMap<String, ArrayList<Message>> leaveUsers=new ConcurrentHashMap<>();
    public static ConcurrentHashMap<String, Message> leaveFile=new ConcurrentHashMap<>();
    static{//在静态代码块初始化validUsers
        validUsers.put("100",new User("100","123456"));
        validUsers.put("200",new User("200","123456"));
        validUsers.put("300",new User("300","123456"));
        validUsers.put("400",new User("400","123456"));
        validUsers.put("500",new User("500","123456"));
    }

说明:我能够实现的离线功能:一个用户可以对不同的离线用户发送任意数量的离线消息,该用户上线后就会显示在控制台,同时这些离线消息会被清除。

本人想到的这种写法的优点:就是对于客户端的代码不需要做任何改动,只需要在服务器端进行修改。缺点:就是代码效率不高,欢迎大家给出更好的建议。

在QQServer部分分别设置离线消息和文件的集合,这里我们采用线程安全的ConcurrentHashMap

在离线消息的集合leaveUsers中,为了实现对每个用户可以保存多条离线消息,这里我们在

value部分采用ArrayList来保存多条message消息(还没学mysql)

for(String x:leaveUsers.keySet()){
                        if(u.getUserId().equals(x)){
                            for(Message xx:leaveUsers.get(x)){
                                ObjectOutputStream os=new ObjectOutputStream(socket.getOutputStream());
                                os.writeObject(xx);
                            }
                            leaveUsers.remove(x);//离线消息遍历后直接删除
                        }
                    }
                    for(String x:leaveFile.keySet()){
                        if(u.getUserId().equals(x)){
                            ObjectOutputStream ooos=new ObjectOutputStream(socket.getOutputStream());
                            ooos.writeObject(leaveFile.get(x));
                            leaveFile.remove(x);
                        }
                    }

在QQServer构造方法中我们在checkUser部分添加上述代码,这里我采用了增强for的叠加,目的是在用户首次登录时遍历检测是否有该用户的离线消息或文件,有的话就将其输出给客户端,这种写法的好处是客户端不需要在原基础上改动。

else if(message.getMesType().equals(MessageType.MESSAGE_FILE_MES)){
                    //根据getterId获取到对应的线程,再将message对象转发,文件
                    int count=0;
                    HashMap<String, ServerConnectClientThread> hm=ManageClientThread.getHm();
                    Iterator<String> iterator=hm.keySet().iterator();
                    while(iterator.hasNext()) {//遍历
                        String s=iterator.next();
                        if(s.equals(message.getGetter()))
                            count=1;
                    }
                    if(count==1) {
                        ServerConnectClientThread serverConnectClientThread = ManageClientThread.getSerConnectClientThread(message.getGetter());
                        ObjectOutputStream oos = new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream());
                        oos.writeObject(message);
                        System.out.println(message.getSender() + "给" + message.getGetter() + "发送文件" + message.getSrc() + "到其的电脑目录:" + message.getDest());
                    }else{
                        QQServer.leaveFile.put(message.getGetter(),message);
                    }
                }
                else if(message.getMesType().equals(MessageType.MESSAGE_COMM_MES)){
                    int count=0;
                    HashMap<String, ServerConnectClientThread> hm=ManageClientThread.getHm();
                    Iterator<String> iterator=hm.keySet().iterator();
                    while(iterator.hasNext()) {//遍历
                        String s=iterator.next();
                        if(s.equals(message.getGetter()))
                            count=1;
                    }
                    if(count==1) {
                        ServerConnectClientThread serverConnectClientThread = ManageClientThread.getSerConnectClientThread(message.getGetter());
                        //得到对应的socket的对象输出流,将message对象转发给指定的客户端
                        ObjectOutputStream oos = new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream());
                        oos.writeObject(message);
                        System.out.println(message.getSendTime() + ":\n" + message.getSender() + "对" + message.getGetter() + "说" + message.getContent());
                    } else {//优化了离线发消息功能
                        switch (message.getGetter()){
                            case"100":
                                arr1.add(new Message(message.getContent(),message.getSender(),message.getGetter(),message.getSendTime(),message.getMesType()));
                                QQServer.leaveUsers.put(message.getGetter(),arr1);
                                break;
                            case"200":
                                arr2.add(new Message(message.getContent(),message.getSender(),message.getGetter(),message.getSendTime(),message.getMesType()));
                                QQServer.leaveUsers.put(message.getGetter(),arr2);
                                break;
                            case"300":
                                arr3.add(new Message(message.getContent(),message.getSender(),message.getGetter(),message.getSendTime(),message.getMesType()));
                                QQServer.leaveUsers.put(message.getGetter(),arr3);
                                break;
                            case"400":
                                arr4.add(new Message(message.getContent(),message.getSender(),message.getGetter(),message.getSendTime(),message.getMesType()));
                                QQServer.leaveUsers.put(message.getGetter(),arr4);
                                break;
                            case"500":
                                arr5.add(new Message(message.getContent(),message.getSender(),message.getGetter(),message.getSendTime(),message.getMesType()));
                                QQServer.leaveUsers.put(message.getGetter(),arr5);
                                break;
                        }
                    }
                }

以上为服务器端的ServerConnectClientThread部分,将原来的文件和私聊部分替换成上述代码即可彻底实现,与原来的区别就是先对现有在线用户的线程集合进行遍历,通过if进行选择执行,存在就正常发送,如果不存在就在离线集合中将其添加。

ArrayList<Message> arr1=new ArrayList<>();
    ArrayList<Message> arr2=new ArrayList<>();
    ArrayList<Message> arr3=new ArrayList<>();
    ArrayList<Message> arr4=new ArrayList<>();
    ArrayList<Message> arr5=new ArrayList<>();

还有最后一点,就是将上述数组集合也写在ServerConnectClientThread,每个集合对应一个用户,即有多少账号就写多少个,本人虽然感觉这样写有点低效,但目前还没想到更好的办法解决这个问题,欢迎大家来分享自己的方法

 

 

 

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值