《OnlineChat996》基於微信羣聊的在線實時通信工具


項目源碼:你和我的暢聊時光


一、主要功能

  1. 註冊,成爲我們的註冊會員用戶,你將擁有全網唯一的ID。
  2. 登錄,進入擁有千萬好友的暢聊空間。
  3. 私聊,你可以選擇和任意在線用戶進行一次親密對話。
  4. 羣聊,只要你想,沒有不可以。你們的團體就是一個小羣組。

二、具體實現

1.服務器與客戶端的連接

服務器加載所有的配置信息,包括數據庫的密碼等。服務器根據Socket與客戶端連接,服務器根據收到的不同類型信息而進行不同的操作。如1代表用戶註冊操作。
1.註冊:將用戶信息存儲到服務器。登錄後將新上線的用戶信息發回給當前已在線的所有用戶。
2.私聊:服務器會檢測到所有的私聊信息以及發送方和接收方。
3.註冊羣:羣名和羣成員信息存儲在Map集合中。
4.羣聊:服務器會接收到所有的羣聊消息,併發送給羣聊內的每一個用戶。

public class MultiThreadServer {
    private static final String IP;
    private static final int PORT;
    // 緩存當前服務器所有在線的客戶端信息
    private static Map<String, Socket> clients = new ConcurrentHashMap<>();
    // 緩存當前服務器註冊的所有羣名稱以及羣好友
    private static Map<String,Set<String>> groups = new ConcurrentHashMap<>();
    static {
        Properties pros = CommUtils.loadProperties("socket.properties");
        IP = pros.getProperty("address");
        PORT = Integer.parseInt(pros.getProperty("port"));
    }

    private static class ExecuteClient implements Runnable {
        private Socket client;
        private Scanner in;
        private PrintStream out;

        public ExecuteClient(Socket client) {
            this.client = client;
            try {
                this.in = new Scanner(client.getInputStream());
                this.out = new PrintStream(client.getOutputStream(),
                        true,"UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void run() {
            while (true) {
                if (in.hasNextLine()) {
                    String jsonStrFromClient = in.nextLine();
                    MessageVO msgFromClient =
                            (MessageVO) CommUtils.json2Object(jsonStrFromClient,
                                    MessageVO.class);
                    // 新用戶註冊到服務端
                    if (msgFromClient.getType().equals("1")) {
                        String userName = msgFromClient.getContent();
                        // 將當前在線的所有用戶名發回客戶端
                        MessageVO msg2Client = new MessageVO();
                        msg2Client.setType("1");
                        msg2Client.setContent(CommUtils.object2Json(
                                clients.keySet()
                        ));
                        out.println(CommUtils.object2Json(msg2Client));
                        // 將新上線的用戶信息發回給當前已在線的所有用戶
                        sendUserLogin("newLogin:"+userName);
                        // 將當前新用戶註冊到服務端緩存
                        clients.put(userName,client);
                        System.out.println(userName+"上線了!");
                        System.out.println("當前聊天室共有"+
                                clients.size()+"人");
                    }
                    else if (msgFromClient.getType().equals("2")) {
                        // 用戶私聊
                        // type:2
                        //  Content:myName-msg
                        //  to:friendName
                        String friendName = msgFromClient.getTo();
                        Socket clientSocket = clients.get(friendName);
                        try {
                            PrintStream out = new PrintStream(clientSocket.getOutputStream(),
                                    true,"UTF-8");
                            MessageVO msg2Client = new MessageVO();
                            msg2Client.setType("2");
                            msg2Client.setContent(msgFromClient.getContent());
                            System.out.println("收到私聊信息,內容爲"+msgFromClient.getContent());
                            out.println(CommUtils.object2Json(msg2Client));
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }else if (msgFromClient.getType().equals("3")) {
                        // 註冊羣
                        String groupName = msgFromClient.getContent();
                        // 該羣的所有羣成員
                        Set<String> friends = (Set<String>) CommUtils.json2Object(
                                msgFromClient.getTo(),Set.class);
                        groups.put(groupName,friends);
                        System.out.println("有新的羣註冊成功,羣名稱爲"+
                                groupName+",一共有"+groups.size() + "個羣");
                    }else if (msgFromClient.getType().equals("4")) {
                        // 羣聊信息
                        System.out.println("服務器收到的羣聊信息爲:"+msgFromClient);
                        String groupName = msgFromClient.getTo();
                        Set<String> names = groups.get(groupName);
                        Iterator<String> iterator = names.iterator();
                        while (iterator.hasNext()) {
                            String socketName = iterator.next();
                            Socket client = clients.get(socketName);
                            try {
                                PrintStream out = new PrintStream(client.getOutputStream(),
                                        true,"UTF-8");
                                MessageVO messageVO = new MessageVO();
                                messageVO.setType("4");
                                messageVO.setContent(msgFromClient.getContent());
                                // 羣名-[]
                                messageVO.setTo(groupName+"-"+CommUtils.object2Json(names));
                                out.println(CommUtils.object2Json(messageVO));
                                System.out.println("服務端發送的羣聊信息爲:"+messageVO);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }

        /**
         * 向所有在線用戶發送新用戶上線信息
         * @param msg
         */
        private void sendUserLogin(String msg) {
            for (Map.Entry<String,Socket> entry: clients.entrySet()) {
                Socket socket = entry.getValue();
                try {
                    PrintStream out = new PrintStream(socket.getOutputStream(),
                            true,"UTF-8");
                    out.println(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(PORT);
        ExecutorService executors = Executors.
                newFixedThreadPool(50);
        for (int i = 0; i < 50; i++) {
            System.out.println("等待客戶端連接...");
            Socket client = serverSocket.accept();
            System.out.println("有新的連接,端口號爲"+client.getPort());
            executors.submit(new ExecuteClient(client));
        }
    }
}

2.註冊功能的實現

獲取到用戶在註冊頁面輸入的所有內容,封裝到User類中,存儲到數據庫中。如果提示註冊成功,則返回到登錄頁面;否則,停留在當前頁面。

public UserReg() {
        JFrame frame = new JFrame("用戶註冊");
        frame.setContentPane(userRegPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.pack();
        frame.setVisible(true);
        // 點擊註冊按鈕,將信息持久化到db中,成功彈出提示框
        regBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 獲取用戶輸入的註冊信息
                String userName = userNameText.getText();
                String password = String.valueOf
                        (passwordText.getPassword());
                String brief = brifeText.getText();
                // 將輸入信息包裝爲User類,保存到數據庫中
                User user = new User();
                user.setUserName(userName);
                user.setPassword(password);
                user.setBrief(brief);
                // 調用dao對象
                if (accountDao.userReg(user)) {//將user信息存到數據庫中
                    // 返回登錄頁面
                    JOptionPane.showMessageDialog(frame,"註冊成功!",
                            "提示信息",JOptionPane.INFORMATION_MESSAGE);
                    frame.setVisible(false);
                }else {
                    // 保留當前註冊頁面
                    JOptionPane.showMessageDialog(frame,"註冊失敗!",
                            "錯誤信息",JOptionPane.ERROR_MESSAGE);
                }
            }
        });

    }
3.登錄的實現

構建登錄界面,給每個按鈕設置點擊事件。
1.註冊按鈕,則彈出註冊頁面
2.登錄按鈕,則獲取用戶輸入的用戶名、密碼。
2.1校驗用戶信息,在數據中查找是否存在此用戶。不存在,提示登錄失敗,留在登錄界面。用戶可以選擇註冊,所有的註冊信息存儲在服務器的數據庫中。
2.2存在,提示登錄成功!然後與服務器建立連接,將當前用戶的用戶名發送到服務器。
2.3讀取服務端發回的所有在線用戶信息,通知每個在線用戶有某用戶上線了。

public UserLogin() {
        frame = new JFrame("用戶登錄");
        frame.setContentPane(UserLoginPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.pack();
        frame.setVisible(true);
        // 註冊按鈕
        regButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 彈出註冊頁面
                new UserReg();
            }
        });
        // 登錄按鈕
        loginButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 校驗用戶信息
                String userName = userNameText.getText();
                String password = String.valueOf(
                        passwordText.getPassword());
                User user = accountDao.userLogin(userName,password);//在數據庫中查看是否有對應的用戶名和密碼
                if (user != null) {
                    // 成功,加載用戶列表
                    JOptionPane.showMessageDialog(frame,
                             "登錄成功!","提示信息",JOptionPane.INFORMATION_MESSAGE);
                    frame.setVisible(false);
                    // 與服務器建立連接,將當前用戶的用戶名發送到服務端
                    Connect2Server connect2Server = new Connect2Server();
                    MessageVO msg2Server = new MessageVO();
                    msg2Server.setType("1");
                    msg2Server.setContent(userName);
                    String json2Server = CommUtils.object2Json(msg2Server);
                    try {
                        PrintStream out = new PrintStream(connect2Server.getOut(),
                                true,"UTF-8");
                        out.println(json2Server);
                        // 讀取服務端發回的所有在線用戶信息
                        Scanner in = new Scanner(connect2Server.getIn());
                        if (in.hasNextLine()) {
                            String msgFromServerStr = in.nextLine();
                            MessageVO msgFromServer =
                                    (MessageVO) CommUtils.json2Object(msgFromServerStr,
                                            MessageVO.class);
                            Set<String> users =
                                    (Set<String>) CommUtils.json2Object(msgFromServer.getContent(),
                                            Set.class);
                            System.out.println("所有在線用戶爲:"+users);
                            // 加載用戶列表界面
                            // 將當前用戶名、所有在線好友、與服務器建立連接傳遞到好友列表界面
                            new FriendsList(userName,users,connect2Server);
                        }
                    } catch (UnsupportedEncodingException ex) {
                        ex.printStackTrace();
                    }
                }else {
                    // 失敗,停留在當前登錄頁面,提示用戶信息錯誤
                    JOptionPane.showMessageDialog(frame,
                            "登錄失敗!","錯誤信息",
                            JOptionPane.ERROR_MESSAGE);
                }
            }
        });
    }
4.私聊

1.當用戶A在在線好友列表界面雙擊用戶B,即進入私聊界面。
2.用戶輸入信息,按回車,即將信息發送給服務器。發送到服務器之前,工具類會封裝發送方A的用戶名、消息內容、聊天類型、接收方B的用戶名,將其轉爲json字符串。
3.服務器對json字符串進行解析,決定進行私聊操作,服務器將信息發送給B。發送到B之前會將json字符串轉爲Object對象,用戶B最終才接收到A發送的消息。

public PrivateChatGUI(String friendName,
                          String myName,
                          Connect2Server connect2Server) {
        this.friendName = friendName;
        this.myName = myName;
        this.connect2Server = connect2Server;
        try {
            this.out = new PrintStream(connect2Server.getOut(),true,
                    "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        frame = new JFrame("與"+friendName+"私聊中...");
        frame.setContentPane(privateChatPanel);
        // 設置窗口關閉的操作,將其設置爲隱藏
        frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        frame.setSize(400,400);
        frame.setVisible(true);
        // 捕捉輸入框的鍵盤輸入
        send2Server.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                StringBuilder sb = new StringBuilder();
                sb.append(send2Server.getText());
                // 1.當捕捉到按下Enter
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    // 2.將當前信息發送到服務端
                    String msg = sb.toString();
                    MessageVO messageVO = new MessageVO();
                    messageVO.setType("2");
                    messageVO.setContent(myName+"-"+msg);
                    messageVO.setTo(friendName);
                    PrivateChatGUI.this.out.println(CommUtils.object2Json(messageVO));
                    // 3.將自己發送的信息展示到當前私聊界面
                    readFromServer(myName+"說:"+msg);
                    send2Server.setText("");
                }
            }
        });
    }

5.羣聊
(1)創建羣:

1.點擊創建羣,進入創建羣界面。所有的在線好友以列表形式展現。
2.選擇你想選擇的用戶,勾選進行多選,已選擇的用戶會存儲在集合中。
3.將自己加入到羣聊集合中,存儲羣名。
4.用工具類將羣名、羣成員信息、當前類的操作類型3,封裝成json字符串,發送給服務器。
5.隱藏創建羣界面,然後刷新羣列表界面。

public CreateGroupGUI(String myName,
                          Set<String> friends,
                          Connect2Server connect2Server,
                          FriendsList friendsList) {
        this.myName = myName;
        this.friends = friends;
        this.connect2Server = connect2Server;
        this.friendsList = friendsList;
        JFrame frame = new JFrame("創建羣組");
        frame.setContentPane(createGroupPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400,300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        // 將在線好友以checkBox展示到界面中
        friendLabelPanel.setLayout(new BoxLayout(friendLabelPanel,BoxLayout.Y_AXIS));
        Iterator<String> iterator = friends.iterator();
        while (iterator.hasNext()) {
            String labelName = iterator.next();
            JCheckBox checkBox = new JCheckBox(labelName);
            friendLabelPanel.add(checkBox);
        }
        // 點擊提交按鈕提交信息到服務端
        conformBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 1.判斷哪些好友選中加入羣聊
                Set<String> selectedFriends = new HashSet<>();
                Component[] comps = friendLabelPanel.getComponents();
                for (Component comp : comps) {
                    JCheckBox checkBox = (JCheckBox) comp;
                    if (checkBox.isSelected()) {
                        String labelName = checkBox.getText();
                        selectedFriends.add(labelName);
                    }
                }
                selectedFriends.add(myName);
                // 2.獲取羣名輸入框輸入的羣名稱
                String groupName = groupNameText.getText();
                // 3.將羣名+選中好友信息發送到服務端
                // type:3
                // content:groupName
                // to:[user1,user2,user3...]
                MessageVO messageVO = new MessageVO();
                messageVO.setType("3");
                messageVO.setContent(groupName);
                messageVO.setTo(CommUtils.object2Json(selectedFriends));
                try {
                    PrintStream out = new PrintStream(connect2Server.getOut(),
                            true,"UTF-8");
                    out.println(CommUtils.object2Json(messageVO));
                } catch (UnsupportedEncodingException ex) {
                    ex.printStackTrace();
                }
                // 4.將當前創建羣界面隱藏,刷新好友列表界面的羣列表
                frame.setVisible(false);
                // addGroupInfo
                // loadGroup
                friendsList.addGroup(groupName,selectedFriends);
                friendsList.loadGroupList();
            }
        });
    }
(2)羣聊操作:

1.雙擊一個羣,進入羣聊。
2.用戶A發送信息,將羣聊消息、操作類型、和其他羣成員信息封裝成json字符串發送到服務器。
3.服務器接收到後,將羣聊消息發送給所有的羣成員。
這裏需要注意的是:
a. 只有羣主才能發送第一條消息。
b. 創建羣時,只有羣主的羣列表纔會刷新,其他羣成員並不知道有這個羣的存在。
c. 只有當羣主發了第一條信息時,其他成員的羣列表纔會刷新出這個羣。
這一點仿照了微信羣聊的特點。

send2Server.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                StringBuilder sb = new StringBuilder();
                sb.append(send2Server.getText());
                // 捕捉回車按鍵
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    String str2Server = sb.toString();
                    // type:4
                    // content:myName-msg
                    // to:groupName
                    MessageVO messageVO = new MessageVO();
                    messageVO.setType("4");
                    messageVO.setContent(myName+"-"+str2Server);
                    messageVO.setTo(groupName);
                    try {
                        PrintStream out = new PrintStream(connect2Server.getOut(),
                                true,"UTF-8");
                        out.println(CommUtils.object2Json(messageVO));
                        System.out.println("客戶端發送的羣聊信息爲:"+messageVO);
                    } catch (UnsupportedEncodingException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        });
6.加載好友列表

1.用戶上線,刷新好友界面
2.創建羣,刷新羣列表界面
3.緩存所有私聊界面和羣聊界面

public class FriendsList {
    private String userName;
    // 存儲所有在線好友
    private Set<String> users;
    // 存儲所有羣名稱以及羣好友
    private Map<String,Set<String>> groupList = new ConcurrentHashMap<>();
    private Connect2Server connect2Server;
    // 緩存所有私聊界面
    private Map<String,PrivateChatGUI> privateChatGUIList = new ConcurrentHashMap<>();
    // 緩存所有羣聊界面
    private Map<String,GroupChatGUI> groupChatGUIList = new ConcurrentHashMap<>();
    // 好友列表後臺任務,不斷監聽服務器發來的信息
    // 好友上線信息、用戶私聊、羣聊
    private class DaemonTask implements Runnable {
        private Scanner in = new Scanner(connect2Server.getIn());
        @Override
        public void run() {
            while (true) {
                // 收到服務器發來的信息
                if (in.hasNextLine()) {
                    String strFromServer = in.nextLine();
                    // 此時服務器發來的是一個json字符串
                    if (strFromServer.startsWith("{")) {
                        MessageVO messageVO = (MessageVO) CommUtils.json2Object(strFromServer,
                                MessageVO.class);
                        if (messageVO.getType().equals("2")) {
                            // 服務器發來的私聊信息
                            String friendName = messageVO.getContent().split("-")[0];
                            String msg = messageVO.getContent().split("-")[1];
                            // 判斷此私聊是否是第一次創建
                            if (privateChatGUIList.containsKey(friendName)) {
                                PrivateChatGUI privateChatGUI = privateChatGUIList.get(friendName);
                                privateChatGUI.getFrame().setVisible(true);
                                privateChatGUI.readFromServer(friendName+"說:"+msg);
                            }else {
                                PrivateChatGUI privateChatGUI = new PrivateChatGUI(friendName,
                                        userName,connect2Server);
                                privateChatGUIList.put(friendName,privateChatGUI);
                                privateChatGUI.readFromServer(friendName+"說:"+msg);
                            }
                        }
                        else if (messageVO.getType().equals("4")) {
                            // 收到服務器發來的羣聊信息
                            // type:4
                            // content:sender-msg
                            // to:groupName-[1,2,3,...]
                            String groupName = messageVO.getTo().split("-")[0];
                            String senderName = messageVO.getContent().split("-")[0];
                            String groupMsg = messageVO.getContent().split("-")[1];
                            // 若此羣名稱在羣聊列表
                            if (groupList.containsKey(groupName)) {
                                if (groupChatGUIList.containsKey(groupName)) {
                                    // 羣聊界面彈出
                                    GroupChatGUI groupChatGUI = groupChatGUIList.get(groupName);
                                    groupChatGUI.getFrame().setVisible(true);
                                    groupChatGUI.readFromServer(senderName+"說:"+groupMsg);
                                }else {
                                    Set<String> names = groupList.get(groupName);
                                    GroupChatGUI groupChatGUI = new GroupChatGUI(groupName,
                                            names,userName,connect2Server);
                                    groupChatGUIList.put(groupName,groupChatGUI);
                                    groupChatGUI.readFromServer(senderName+"說:"+groupMsg);
                                }
                            }else {
                                // 若羣成員第一次收到羣聊信息
                                // 1.將羣名稱以及羣成員保存到當前客戶端羣聊列表
                                Set<String> friends = (Set<String>) CommUtils.json2Object(messageVO.getTo().split("-")[1],
                                        Set.class);
                                groupList.put(groupName, friends);
                                loadGroupList();
                                // 2.彈出羣聊界面
                                GroupChatGUI groupChatGUI = new GroupChatGUI(groupName,
                                        friends,userName,connect2Server);
                                groupChatGUIList.put(groupName,groupChatGUI);
                                groupChatGUI.readFromServer(senderName+"說:"+groupMsg);
                            }


                        }
                    }else {
                        // newLogin:userName
                        if (strFromServer.startsWith("newLogin:")) {
                            String newFriendName = strFromServer.split(":")[1];
                            users.add(newFriendName);
                            // 彈框提示用戶上線
                            JOptionPane.showMessageDialog(frame,
                                    newFriendName+"上線了!",
                                    "上線提醒",JOptionPane.INFORMATION_MESSAGE);
                            // 刷新好友列表
                            loadUsers();
                        }
                    }
                }
            }
        }
    }
    // 私聊點擊事件
    private class PrivateLabelAction implements MouseListener {
        private String labelName;

        public PrivateLabelAction(String labelName) {
            this.labelName = labelName;
        }

        // 鼠標點擊執行事件
        @Override
        public void mouseClicked(MouseEvent e) {
            // 判斷好友列表私聊界面緩存是否已經有指定標籤
            if (privateChatGUIList.containsKey(labelName)) {
                PrivateChatGUI privateChatGUI = privateChatGUIList.get(labelName);
                privateChatGUI.getFrame().setVisible(true);
            }else {
                // 第一次點擊,創建私聊界面
                PrivateChatGUI privateChatGUI = new PrivateChatGUI(
                        labelName,userName,connect2Server
                );
                privateChatGUIList.put(labelName,privateChatGUI);
            } 
    }

    // 羣聊點擊事件
    private class GroupLabelAction implements MouseListener {
        private String groupName;

        public GroupLabelAction(String groupName) {
            this.groupName = groupName;
        }

        @Override
        public void mouseClicked(MouseEvent e) {
            if (groupChatGUIList.containsKey(groupName)) {
                GroupChatGUI groupChatGUI = groupChatGUIList.get(groupName);
                groupChatGUI.getFrame().setVisible(true);
            }else {
                Set<String> names = groupList.get(groupName);
                GroupChatGUI groupChatGUI = new GroupChatGUI(
                        groupName,names,userName,connect2Server
                );
                groupChatGUIList.put(groupName,groupChatGUI);
            }
        }
    }

    public FriendsList(String userName, Set<String> users,
                       Connect2Server connect2Server) {
        this.userName = userName;
        this.users = users;
        this.connect2Server = connect2Server;
        frame = new JFrame(userName);
        frame.setContentPane(friendsPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400,300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        loadUsers();
        // 啓動後臺線程不斷監聽服務器發來的消息
        Thread daemonThread = new Thread(new DaemonTask());
        daemonThread.setDaemon(true);
        daemonThread.start();
        // 創建羣組
        createGroupBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new CreateGroupGUI(userName,users,connect2Server,
                        FriendsList.this);
            }
        });
    }
    // 加載所有在線的用戶信息
    public void loadUsers() {
        JLabel[] userLabels = new JLabel [users.size()];
        JPanel friends = new JPanel();
        friends.setLayout(new BoxLayout(friends,BoxLayout.Y_AXIS));
        // set遍歷
        Iterator<String> iterator = users.iterator();
        int i = 0;
        while (iterator.hasNext()) {
            String userName = iterator.next();
            userLabels[i] = new JLabel(userName);
            // 添加標籤點擊事件
            userLabels[i].addMouseListener(new PrivateLabelAction(userName));
            friends.add(userLabels[i]);
            i++;
        }
        frinedsList.setViewportView(friends);
        // 設置滾動條垂直滾動
        frinedsList.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        friends.revalidate();
        frinedsList.revalidate();
    }

    public void loadGroupList() {
        // 存儲所有羣名稱標籤Jpanel
        JPanel groupNamePanel = new JPanel();
        groupNamePanel.setLayout(new BoxLayout(groupNamePanel,
                BoxLayout.Y_AXIS));
        JLabel[] labels = new JLabel[groupList.size()];
        // Map遍歷
        Set<Map.Entry<String,Set<String>>> entries = groupList.entrySet();
        Iterator<Map.Entry<String,Set<String>>> iterator =
                entries.iterator();
        int i = 0;
        while (iterator.hasNext()) {
            Map.Entry<String,Set<String>> entry = iterator.next();
            labels[i] = new JLabel(entry.getKey());
            labels[i].addMouseListener(new GroupLabelAction(entry.getKey()));
            groupNamePanel.add(labels[i]);
            i++;
        }
        groupListPanel.setViewportView(groupNamePanel);
        groupListPanel.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        groupListPanel.revalidate();
    }

    public void addGroup(String groupName,Set<String> friends) {
        groupList.put(groupName,friends);
    }
}

三、整體流程

服務器:

負責緩存所有在線好友、羣組以及私聊羣聊的聊天記錄。根據客戶端進行不同的操作而緩存不同的數據到服務器上。

客戶端:

1.點擊註冊按鈕,觸發註冊事件。在註冊頁面,獲取用戶輸入的用戶名、密碼、簡介,將信息封裝到User類中,將user的信息保存到數據庫中,即進行數據插入操作。註冊成功,返回登錄界面。

2.輸入已註冊的用戶名、密碼,點擊登錄,觸發登錄事件。獲取用戶輸入的用戶名和密碼,在數據庫中查找是否有此用戶。

3.有,則成功登錄。然後與服務器建立連接,將當前用戶的用戶名發送到服務器,服務器緩存此用戶名。服務器給每一個在線好友發送新用戶上線了,並刷新好友列表。

刷新好友列表:加載所有在線的用戶信息,並給每一個用戶標籤添加標籤點擊事件。

4.客戶端讀取服務器返回的所有在線用戶信息,加載主界面。即加載用戶列表界面,將當前用戶名、所有在線好友、與服務器建立連接傳遞到好友列表界面。

5.好友列表界面:加載所有在線的用戶信息,並給每一個用戶標籤添加標籤點擊事件,觸發私聊功能。如果是第一次點擊,則創建私聊界面;如果之前已經有過聊天的記錄,則根據緩存中的指定標籤將私聊界面顯示出來。

6.創建私聊:根據傳遞的參數(發送方,接收方,Socket連接),一旦用戶按下回車,則將當前的發送方、接收方、消息封裝到協議類中,發給服務器,並將自己發送的信息展示到當前私聊界面。最後將當前私聊界面緩存起來。

7.創建羣。點擊創建羣,進入創建羣界面。所有的在線好友以列表形式展現。將已選擇的用戶存儲在集合中。將自己加入到羣聊集合中,存儲羣名。服務器緩存羣名和羣成員信息,將羣名稱標籤存儲在緩存中,給每個羣名稱標籤添加鼠標點擊事件,最後刷新羣列表界面。

8.羣聊:羣聊界面首次創建會存在緩存中,協議類將羣聊的發言人和羣名稱封裝起來,發給服務器。服務器經過解析,將消息發送給在羣組中的每一個人。

8.啓動後臺線程不斷監聽服務器發來的消息:
(1)服務器發來的是json字符串,我們需要進行解析。
a. 服務器發來的是私聊信息。判斷是不是第一次和此用戶進行的私聊。第一次私聊,則創建私聊界面,緩存此私聊界面。不是第一次私聊,將緩存中的私聊界面彈出來。
b. 服務器發來的是羣聊信息。若羣聊名稱在羣聊列表,彈出羣聊界面。如果自己剛剛創建了羣聊,則將羣聊信息緩存起來。若羣成員第一次收到羣聊信息,將羣名稱以及羣成員保存到當前客戶端羣聊列表,然後彈出羣聊界面,將羣聊界面緩存。
(2)服務器發來字符串:newLogin:userName。則提醒新用戶上線,刷新好友列表。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章