首页 JAVA-Socket通信 聊天室(服务端)
文章
取消

JAVA-Socket通信 聊天室(服务端)

关于聊天室中服务器部分

一个聊天室,我们可以将其分为服务端和客户端,而通信的简易过程如下图所示

对于服务器,我们需要做的是1、验证用户登陆信息。2、接收用户发送的信息并转发给目标用户

整体思路

Server端

image-20220617112109334

UserService

用于用户账号管理,预先创建几个账号,然后存到文件中,每次服务器执行时,都会将文件中的账号信息读入,同时新创建的用户账号也会存入到文件中去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
public class UserService {
    private static int idCount =3;//id
    //新增用户
    public void addUser(User user){
        user.setId(++idCount);
        List<User> users = loadAllUser();
        users.add(user);
        saveAllUser(users);
    }

    //用户登录
    public User login(long id,String password){
        User result = null;
        List<User> users =loadAllUser();
        for(User user : users){
            if(id == user.getId()&&password.equals(user.getPassword())){
                result=user;
                break;
            }
        }
        return result;
    }

    //根据ID加载用户
    public User loadUser(long id){
        User result = null;
        List<User> users=loadAllUser();
        for(User user:users){
            if(id==user.getId()){
                result=user;
                break;
            }
        }
        return result;
    }

    //加载所有用户
    public List<User> loadAllUser(){
        List<User> list = null;
        ObjectInputStream ois =null;
        try {
            ois = new ObjectInputStream(
                    new FileInputStream(
                            DataBuffer.configProp.getProperty("dbpath")));
            list =(List<User>) ois.readObject();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtil.close(ois);
        }
        return list;
    }


    //保存所有用户
    private void saveAllUser(List<User> users){
        ObjectOutputStream oos =null;
        try{
            oos = new ObjectOutputStream(
                    new FileOutputStream(
                            DataBuffer.configProp.getProperty("dbpath")));
            //写回用户信息
            oos.writeObject(users);
            oos.flush();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtil.close(oos);
        }
    }

    //初始化几个测试用户
    public void initUser(){
        User user = new User("admin", "Admin", 'm', 0);
        user.setId(1);

        User user2 = new User("123456", "Tom", 'm', 1);
        user2.setId(2);

        User user3 = new User("123456", "Lily", 'f', 2);
        user3.setId(3);

        List<User> users = new CopyOnWriteArrayList<User>();
        users.add(user);
        users.add(user2);
        users.add(user3);

        this.saveAllUser(users);
    }

    public static void main(String[] args){
        new UserService().initUser();
        List<User> users = new UserService().loadAllUser();
        for (User user : users) {
            System.out.println(user);
        }
    }
}

DataBuffer

用于服务器端从文件中读取数据,进行缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class DataBuffer {
    // 服务器端socket
    public static ServerSocket serverSocket;
    //在线用户的IO Map
    public static Map<Long,OnlineClientIOCache> onlineUserIOCacheMap;
    //在线用户Map
    public static Map<Long,User> onlineUsersMap;
    //服务器配置参数属性集
    public static Properties configProp;
    //已注册用户表的Model
    public static RegistedUserTableModel registedUserTableModel;
    // 当前在线用户表的Model
    public static OnlineUserTableModel onlineUserTableModel;
    // 当前服务器所在系统的屏幕尺寸
    public static Dimension screenSize;
    // 当前用户数据库
    public static UserService userService;
    static{
        // 初始化
        //ConcurrentSkipListMap: 线程安全的有序的哈希表 适用于高并发的场景
        onlineUserIOCacheMap = new ConcurrentSkipListMap<Long, OnlineClientIOCache>(); //在线用户的IO缓存map
        onlineUsersMap = new ConcurrentSkipListMap<Long, User>(); //在线用户map
        configProp = new Properties(); //创建配置文件
        registedUserTableModel = new RegistedUserTableModel(); //初始化几个已注册用户
        onlineUserTableModel = new OnlineUserTableModel(); //获取在线用户
        screenSize = Toolkit.getDefaultToolkit().getScreenSize(); //获取屏幕尺寸
        userService = new UserService(); //创建服务器

        // 加载服务器配置文件
        try {
            configProp.load(Thread.currentThread()
                    .getContextClassLoader()
                    .getResourceAsStream("serverconfig.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

RequestProcessor

这时服务器端最重要的一个类了,用于处理客户端发来的消息,并进行回复,对于每一项操作的实现原理无非就是服务器处理内部数据或是向指定客户端发送消息,详细看代码注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
//针对每个用户的服务线程
public class RequestProcessor implements Runnable {
    //当前正在请求服务器的客户端Socket
    private Socket currentClientSocket;
    public RequestProcessor(Socket currentClientSocket){
        this.currentClientSocket=currentClientSocket;
    }
    public void run(){
        boolean flag = true;//是否不断监听
        try{
            OnlineClientIOCache currentClientIOCache = new OnlineClientIOCache(
                    new ObjectInputStream(currentClientSocket.getInputStream()),
                    new ObjectOutputStream(currentClientSocket.getOutputStream()));
            while (flag){
                //不停地读取客户端发过来的请求对象
                //从请求输入流中读取到客户端提交的请求对象
                Request request = (Request)currentClientIOCache.getOis().readObject();
                System.out.println("Server读取了客户端的请求:" + request.getAction());
                //获取请求中的动作
                String actionName = request.getAction();
                if(actionName.equals("userRegist")){      //用户注册
                    regist(currentClientIOCache, request);
                }else if(actionName.equals("userLogin")){  //用户登录
                    login(currentClientIOCache, request);
                }else if("exit".equals(actionName)){       //请求断开连接
                    flag = logout(currentClientIOCache, request);
                }else if("chat".equals(actionName)){       //聊天
                    chat(request);
                }else if("toSendFile".equals(actionName)){ //准备发送文件
                    toSendFile(request);
                }else if("agreeReceiveFile".equals(actionName)){ //同意接收文件
                    agreeReceiveFile(request);
                }else if("refuseReceiveFile".equals(actionName)){ //拒绝接收文件
                    refuseReceiveFile(request);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //注册
    public void regist(OnlineClientIOCache oio,Request request) throws IOException{
        User user = (User)request.getAttribute("user");
        DataBuffer.userService.addUser(user);
        //创建一个响应对象
        Response response = new Response();
        response.setStatus(ResponseStatus.OK);
        response.setData("user",user);
        //向客户端写入响应对象
        oio.getOos().writeObject(response);
        oio.getOos().flush();
        //把新注册用户添加到RegistedUserTableModel中
        DataBuffer.registedUserTableModel.add(new String[]{
                String.valueOf(user.getId()),
                user.getPassword(),
                user.getNickname(),
                String.valueOf(user.getSex())});
    }

    //登录
    void login(OnlineClientIOCache currentClientIO, Request request) throws IOException {
        //获取输入的账号密码
        String idStr = (String)request.getAttribute("id");
        String password = (String) request.getAttribute("password");
        //建立服务对象
        UserService userService = new UserService();
        User user = userService.login(Long.parseLong(idStr), password);

        Response response = new Response();  //创建一个响应对象
        if(null != user){
            if(DataBuffer.onlineUsersMap.containsKey(user.getId())){ //用户已经登录了
                response.setStatus(ResponseStatus.OK);
                response.setData("msg", "该用户已经在别处上线了!");
                currentClientIO.getOos().writeObject(response);  //把响应对象往客户端写
                currentClientIO.getOos().flush();
            }else { //正确登录
                DataBuffer.onlineUsersMap.put(user.getId(), user); //添加到在线用户

                //设置在线用户
                response.setData("onlineUsers",
                        new CopyOnWriteArrayList<User>(DataBuffer.onlineUsersMap.values()));

                response.setStatus(ResponseStatus.OK);
                response.setData("user", user);
                currentClientIO.getOos().writeObject(response);  //把响应对象往客户端写
                currentClientIO.getOos().flush();

                //通知其它用户有人上线了
                Response response2 = new Response();
                response2.setType(ResponseType.LOGIN);
                response2.setData("loginUser", user);
                iteratorResponse(response2);

                //把当前上线的用户IO添加到缓存Map中
                DataBuffer.onlineUserIOCacheMap.put(user.getId(),currentClientIO);

                //把当前上线用户添加到OnlineUserTableModel中
                DataBuffer.onlineUserTableModel.add(
                        new String[]{String.valueOf(user.getId()),
                                user.getNickname(),
                                String.valueOf(user.getSex())});
            }
        }else{ //登录失败
            response.setStatus(ResponseStatus.OK);
            response.setData("msg", "账号或密码不正确!");
            currentClientIO.getOos().writeObject(response);
            currentClientIO.getOos().flush();
        }
    }
    //用户退出
    public boolean logout(OnlineClientIOCache oio, Request request) throws IOException{
        System.out.println(currentClientSocket.getInetAddress().getHostAddress()
                + ":" + currentClientSocket.getPort() + "走了");

        User user = (User)request.getAttribute("user");
        //把当前在线客户端的IO从Map中删除
        DataBuffer.onlineUserIOCacheMap.remove(user.getId());
        //从在线用户缓存Map中删除当前用户
        DataBuffer.onlineUsersMap.remove(user.getId());

        Response response = new Response();  //创建一个响应对象
        response.setType(ResponseType.LOGOUT);
        response.setData("logoutUser", user);
        oio.getOos().writeObject(response);  //把响应对象往客户端写
        oio.getOos().flush();
        currentClientSocket.close();  //关闭这个客户端Socket

        DataBuffer.onlineUserTableModel.remove(user.getId()); //把当前下线用户从在线用户表Model中删除
        iteratorResponse(response); //通知所有其它在线客户端

        return false;  //断开监听
    }
    //聊天
    public void chat(Request request) throws IOException {
        //获取消息内容
        Message msg = (Message)request.getAttribute("msg");
        //创建响应对象
        Response response = new Response();
        response.setStatus(ResponseStatus.OK);
        response.setType(ResponseType.CHAT);
        response.setData("txtMsg", msg);

        if(msg.getToUser() != null){ //私聊:只给私聊的对象返回响应
            OnlineClientIOCache io = DataBuffer.onlineUserIOCacheMap.get(msg.getToUser().getId());
            sendResponse(io, response);
        }else{  //群聊:给除了发消息的所有客户端都返回响应
            for(Long id : DataBuffer.onlineUserIOCacheMap.keySet()){
                if(msg.getFromUser().getId() == id ){  continue; }
                sendResponse(DataBuffer.onlineUserIOCacheMap.get(id), response);
            }
        }
    }
    //服务器广播
    public static void board(String str) throws IOException {
        //用户admin做为消息发送者
        User user = new User(1,"admin");
        Message msg = new Message();
        msg.setFromUser(user);
        msg.setSendTime(new Date());

        DateFormat df = new SimpleDateFormat("HH:mm:ss");
        StringBuffer sb = new StringBuffer();
        sb.append(" ").append(df.format(msg.getSendTime())).append(" ");
        sb.append("系统通知\n  "+str+"\n");
        msg.setMessage(sb.toString());
        //创建响应对象
        Response response = new Response();
        response.setStatus(ResponseStatus.OK);
        response.setType(ResponseType.BOARD);
        response.setData("txtMsg", msg);
        //向每个在线用户返回响应
        for (Long id : DataBuffer.onlineUserIOCacheMap.keySet()) {
            sendResponse_sys(DataBuffer.onlineUserIOCacheMap.get(id), response);
        }
    }

    //服务器踢除用户
    public static void remove(User user_) throws IOException{
        User user = new User(1,"admin");
        Message msg = new Message();
        msg.setFromUser(user);
        msg.setSendTime(new Date());
        msg.setToUser(user_);

        StringBuffer sb = new StringBuffer();
        DateFormat df = new SimpleDateFormat("HH:mm:ss");
        sb.append(" ").append(df.format(msg.getSendTime())).append(" ");
        sb.append("系统通知您\n  "+"您被强制下线"+"\n");
        msg.setMessage(sb.toString());

        Response response = new Response();
        response.setStatus(ResponseStatus.OK);
        response.setType(ResponseType.REMOVE);
        response.setData("txtMsg", msg);

        OnlineClientIOCache io = DataBuffer.onlineUserIOCacheMap.get(msg.getToUser().getId());
        sendResponse_sys(io, response);
    }

    //服务器发送私信
    public static void chat_sys(String str,User user_) throws IOException{
        User user = new User(1,"admin");
        Message msg = new Message();
        msg.setFromUser(user);
        msg.setSendTime(new Date());
        msg.setToUser(user_);

        DateFormat df = new SimpleDateFormat("HH:mm:ss");
        StringBuffer sb = new StringBuffer();
        sb.append(" ").append(df.format(msg.getSendTime())).append(" ");
        sb.append("系统通知您\n  "+str+"\n");
        msg.setMessage(sb.toString());

        Response response = new Response();
        response.setStatus(ResponseStatus.OK);
        response.setType(ResponseType.CHAT);
        response.setData("txtMsg", msg);

        OnlineClientIOCache io = DataBuffer.onlineUserIOCacheMap.get(msg.getToUser().getId());
        sendResponse_sys(io, response);
    }
    //拒绝接收文件
    private void refuseReceiveFile(Request request) throws IOException {
        FileInfo sendFile = (FileInfo)request.getAttribute("sendFile");
        Response response = new Response();  //创建一个响应对象
        response.setType(ResponseType.REFUSERECEIVEFILE);
        response.setData("sendFile", sendFile);
        response.setStatus(ResponseStatus.OK);
        //向请求方的输出流输出响应
        OnlineClientIOCache ocic = DataBuffer.onlineUserIOCacheMap.get(sendFile.getFromUser().getId());
        this.sendResponse(ocic, response);
    }

    //同意接收文件
    private void agreeReceiveFile(Request request) throws IOException {
        FileInfo sendFile = (FileInfo)request.getAttribute("sendFile");
        //向请求方(文件发送方)的输出流输出响应
        Response response = new Response();  //创建一个响应对象
        response.setType(ResponseType.AGREERECEIVEFILE);
        response.setData("sendFile", sendFile);
        response.setStatus(ResponseStatus.OK);
        OnlineClientIOCache sendIO = DataBuffer.onlineUserIOCacheMap.get(sendFile.getFromUser().getId());
        this.sendResponse(sendIO, response);

        //向文件接收方发出接收文件的响应
        Response response2 = new Response();  //创建一个响应对象
        response2.setType(ResponseType.RECEIVEFILE);
        response2.setData("sendFile", sendFile);
        response2.setStatus(ResponseStatus.OK);
        OnlineClientIOCache receiveIO = DataBuffer.onlineUserIOCacheMap.get(sendFile.getToUser().getId());
        this.sendResponse(receiveIO, response2);
    }

    // 准备发送文件
    public void toSendFile(Request request)throws IOException{
        Response response = new Response();
        response.setStatus(ResponseStatus.OK);
        response.setType(ResponseType.TOSENDFILE);
        FileInfo sendFile = (FileInfo)request.getAttribute("file");
        response.setData("sendFile", sendFile);
        //给文件接收方转发文件发送方的请求
        OnlineClientIOCache ioCache = DataBuffer.onlineUserIOCacheMap.get(sendFile.getToUser().getId());
        sendResponse(ioCache, response);
    }
    //向指定客户端IO的输出流中输出指定响应
    private void sendResponse(OnlineClientIOCache onlineUserIO, Response response)throws IOException {
        ObjectOutputStream oos = onlineUserIO.getOos();
        oos.writeObject(response);
        oos.flush();
    }

    // 向指定客户端IO的输出流中输出指定响应
    private static void sendResponse_sys(OnlineClientIOCache onlineUserIO, Response response)throws IOException {
        ObjectOutputStream oos = onlineUserIO.getOos();
        oos.writeObject(response);
        oos.flush();
    }
    //给所有在线客户都发送响应
    private void iteratorResponse(Response response) throws IOException {
        for(OnlineClientIOCache onlineUserIO : DataBuffer.onlineUserIOCacheMap.values()){
            ObjectOutputStream oos = onlineUserIO.getOos();
            oos.writeObject(response);
            oos.flush();
        }
    }

}

ServerInfoGUI

界面大致形状

1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
public class ServerInfoFrame extends JFrame{
    private static final long serialVersionUID = 6274443611957724780L;
    //发送信息输入窗口
    private JTextField jta_msg;
    //在线用户表
    private JTable onlineUserTable;
    //已注册用户表
    private JTable registedUserTable;

    public ServerInfoFrame(){
        init();
        loadData();
        setVisible(true);
    }

    //初始化窗体
    public void init(){
        this.setTitle("服务器启动");
        this.setBounds((DataBuffer.screenSize.width - 700)/2,
                (DataBuffer.screenSize.height - 475)/2, 700, 475);
        this.setLayout(new BorderLayout());

        JPanel panel = new JPanel();
        Border border=BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
        panel.setBorder(BorderFactory.createTitledBorder(border,"服务器监听中",TitledBorder.LEFT,TitledBorder.TOP));
        this.add(panel,BorderLayout.NORTH);

        int port = Integer.parseInt(DataBuffer.configProp.getProperty("port"));

        JLabel label =new JLabel("服务器端口:\n"+port);
        panel.add(label);
        JButton exitBtn = new JButton("关闭服务器");
        panel.add(exitBtn);

        JLabel la_msg =new JLabel("要发送的消息");
        panel.add(la_msg);
        //服务器要发送消息的输入框
        jta_msg = new JTextField(30);
        //定义一个监听器对象:发送广播消息
        ActionListener sendCaseMsgAction = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try{
                    sendAllMsg();
                }catch (IOException e1){
                    e1.printStackTrace();;
                }
            }
        };
        //给输入框加上事件监听器,按回车发送;
        jta_msg.addActionListener(sendCaseMsgAction);
        JButton bu_send = new JButton("send");
        //给按钮加上发送广播消息的监听器
        bu_send.addActionListener(sendCaseMsgAction);
        panel.add(jta_msg);
        panel.add(bu_send);

        //使用服务器缓存中的TableMo
        onlineUserTable = new JTable(DataBuffer.onlineUserTableModel);
        registedUserTable = new JTable(DataBuffer.registedUserTableModel);

        //取得表格上的弹出菜单对象,加到表格上;
        JPopupMenu pop = getTablePop();
        onlineUserTable.setComponentPopupMenu(pop);

        //选项卡
        JTabbedPane tabbedPane = new JTabbedPane();
        tabbedPane.addTab("在线用户列表",new JScrollPane(onlineUserTable));
        tabbedPane.addTab("已注册用户列表",new JScrollPane(registedUserTable));
        tabbedPane.setTabComponentAt(0,new JLabel("在线用户列表"));
        this.add(tabbedPane,BorderLayout.CENTER);

        final JLabel stateBar = new JLabel("",SwingConstants.RIGHT);
        stateBar.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
        //用定时任务来显示当前时间
        new java.util.Timer().scheduleAtFixedRate(
                new TimerTask() {
                    DateFormat df =new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
                    @Override
                    public void run() {
                        stateBar.setText("当前时间:" + df.format(new Date()) + "  ");
                    }
                },0,1000
        );
        //把状态栏添加到窗体的南边
        this.add(stateBar,BorderLayout.SOUTH);

        //关闭窗口
        this.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e) {
                logout();
            }
        });
        /* 添加关闭服务器按钮事件处理方法 */
        exitBtn.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent event) {
                logout();
            }
        });
    }

    //创建表格上的弹出菜单对象 实现发信 踢人功能
    private JPopupMenu getTablePop(){
        //弹出菜单对象
        JPopupMenu pop =new JPopupMenu();
        JMenuItem mi_send = new JMenuItem("发信");
        //菜单项对象
        //设定菜单命令关键字
        mi_send.setActionCommand("send");
        //菜单项对象
        JMenuItem mi_del = new JMenuItem("踢掉");
        //设定菜单命令关键字
        mi_del.setActionCommand("del");
        //弹出菜单上的监视器对象
        ActionListener al =new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 哪个菜单项点击了 这个s就是其设定的ActionCommand
                String s= e.getActionCommand();
                popMenuAction(s);
            }
        };
        mi_send.addActionListener(al);
        mi_del.addActionListener(al);
        pop.add(mi_send);
        pop.add(mi_del);
        return pop;
    }
    // 处理弹出菜单上的事件
    private void popMenuAction(String command){
        // 得到在表格上选中的行
        final int selectIndex = onlineUserTable.getSelectedRow();
        String usr_id = (String) onlineUserTable.getValueAt(selectIndex,0);
        System.out.println(usr_id);
        if(selectIndex==-1){
            JOptionPane.showMessageDialog(this,"请选择一个用户");
            return;
        }
        if (command.equals("del")) {
            // 从线程中移除处理线程对象
            try {
                RequestProcessor.remove(DataBuffer.onlineUsersMap.get(Long.valueOf(usr_id)));
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else if(command.equals("send")){
            final JDialog jd = new JDialog(this,true);
            jd.setLayout(new FlowLayout());
            jd.setSize(200,100);
            final JTextField jtd_m = new JTextField(20);
            JButton jb = new JButton("发送");
            jd.add(jtd_m);
            jd.add(jb);
            //发送按钮的事件实现
            jb.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println("服务器发送了一条消息");
                    String msg = jtd_m.getText();
                    try {
                        RequestProcessor.chat_sys(msg,DataBuffer.onlineUsersMap.get(Long.valueOf(usr_id)));
                    }catch (IOException e1){
                        e1.printStackTrace();
                    }
                    //清空输入框
                    jtd_m.setText("");
                    jd.dispose();
                }
            });
            jd.setVisible(true);
        }else{
            JOptionPane.showMessageDialog(this,"未知菜单"+command);
        }
        //刷新表格
        SwingUtilities.updateComponentTreeUI(onlineUserTable);
    }
    //按下发送服务器消息的按钮,给所有在线用户发送消息
    private void sendAllMsg() throws IOException{
        RequestProcessor.board(jta_msg.getText());
        //清空输入框
        jta_msg.setText("");
    }
    //把所有已注册的用户信息加载到RegistedUserTableModel中
    private void loadData(){
        List<User> users=new UserService().loadAllUser();
        for(User user:users){
            DataBuffer.registedUserTableModel.add(new String[]{
                String.valueOf(user.getId()),
                user.getPassword(),
                user.getNickname(),
                String.valueOf(user.getSex())
            });
        }
    }
    //关闭服务器
    private void logout(){
        //弹出提示窗口
        int select = JOptionPane.showConfirmDialog(ServerInfoFrame.this,
                "确定关闭吗?\n\n关闭服务器将中断与所有客户端的连接!",
                "关闭服务器",
                JOptionPane.YES_NO_OPTION);
        //如果用户点击的是关闭服务器按钮时会提示是否确认关闭。
        if (select == JOptionPane.YES_OPTION) {
            System.exit(0);//退出系统
        }else{
            //覆盖默认的窗口关闭事件动作
            setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        }
    }
}

entity 中的两个类仅用于界面,所以不会进行介绍。

运行结果

image-20220617152915327

image-20220617152931194

image-20220617152956174

image-20220617153019493

image-20220617153037535

基本完成,看起来还不错,就是有点丑。

本文由作者按照 CC BY 4.0 进行授权