java基于socket多线程的swing聊天室(完整版,附源码,带数据库存储)⽬    录
注意:
⽤的本地redis数据库,所以你需要现在本地安装redis数据库
设计需求
实现功能:
客户端和客户端之间的消息传递(私聊)
客户端和客户端之间的⽂件发送(私聊)
客户端和服务器之间的消息传递(聊)
总体设计
1.1 实验环境准备:
集成开发环境:IDEA
JDK:JDK>=9
实现流程
项⽬框架
Javabean⽬录:存储java实体类。
Info:通信的消息报⽂类,包括消息报⽂的类型、内容、发送者、接收者、附件。
User:客户端(⽤户)实体,字段为username,password,image,分别是⽤户名,密码,头像。
Service⽬录:主要的业务流程、界⾯,包括登录、注册等业务、⼴播聊天和私聊业务。
Starter:对外提供的启动类
Client:启动⼀个客户端
Server:启动服务器
Util:封装好基本操作的⼯具类
RedisUtils:完成和redis远程服务器的操作,主要存储⽤户名、密码、通信缓存等
SwingUtils:注册组件时候需要的⼯具类,封装了⽐如图标⽐例⾃适应、等⽐例设置⾯板⼤⼩等常⽤功能
ToolUtils:包括⼀些通⽤功能,⽐如获取系统时间、获得全局唯⼀⽇志对象,获得⽂件后缀名、读写⽂件、获得⽤户头像等。
详细设计
1.1实体类部分
1.1.1 Info类
1. public class Info implements Serializable {
2.
3. /**
4.      * 消息类型
5.      */
6. private int type;
7. /**
8.      * 消息内容
12.      * 消息发送者⽤户名
13.      */
14. private String source;
15. /**
16.      * 消息接收者⽤户名
17.      */
18. private String dest;
19.
20. /**
21.      * ⽂件名
22.      */
23. private String fileName;
24.
25. /**
26.      * 附件
27.      */
28. private List attach;
29. ...
30. Get
31. Set
32. toString
33. }
这个类代表整个通信过程传输的报⽂,其中,type字段最为关键,它决定了发送报⽂的类型,不同的值代表不同的类型,接受⽅收到报⽂后,解析出其中的type字段,根据不同的值执⾏不同的操作。
Type字段对应类型如下:
1. /**
2.  * 服务器和客户端之间的消息协议
3.  * 0-CS第⼀次握⼿信息
4.  * 1-client请求⼴播信息
5.  * 2-保留
6.  * 3-client请求上传⽂件
7.  * 4-client查询在线⼈数
8.  * 5-server返回系统在线⼈数
9.  * 6-server返回反馈消息
10.  * 7-client查询在线⽤户列表
11.  * 8-server返回在线⽤户列表
12.  * 9-client私聊发送信息
13.  * 10-client私聊发送⽂件
14.  * 11-server转发私聊⽂件
15.  * @author zhupengcheng
16.  */
1.1.2 User类
1. public class User implements Serializable {
2.
3. /**
4.      * ⽤户名
5.      */
6. private String username;
7. /**
8.      * 密码
9.      */
10. private String password;
11. /**
12.      * 头像
16. get
17. set
18. toString
19. }
这个类代表⽤户实体,主要⽤在登录、注册流程中,及其登录、注册业务跳转到通信业务中,我需要传递⼀个user对象,记录这个⽤户(客户端)的⼀些信息。
1.2客户端部分
1.1.1 登录部分
1. /**
2.          * 登录点击事件
3.          */
4.        login_btn.addActionListener(new ActionListener() {
5. @Override
6. public void actionPerformed(ActionEvent e) {
7.                String username = Text().trim();
8.                String password = new String(Password());
9. if (username == null || password == null) {
10.                    JOptionPane.showMessageDialog(null,"⽤户名、密码不许为空!", "⽤户登录", JOptionPane.INFORMATION_MESSAGE);
11.                }
12. final int recv = RedisUtils.validUser(username, password);
13. if (recv == 0) {
14.                    JOptionPane.showMessageDialog(null,"⽤户不存在,请先注册!", "⽤户登录", JOptionPane.INFORMATION_MESSAGE);
15. return;
16.                }
17. if (recv == 1) {
18.                    JOptionPane.showMessageDialog(null,"密码错误!", "⽤户登录", JOptionPane.INFORMATION_MESSAGE);
19. return;
20.                }
21. if (RedisUtils.isAlive(username)) {
22.                    JOptionPane.showMessageDialog(null,"你已经登录了,不能重复登录!", "⽤户登录", JOptionPane.INFORMATION_MESSAGE);
23. return;
24.                }
25.                JOptionPane.showMessageDialog(null,"登录成功!", "⽤户登录", JOptionPane.INFORMATION_MESSAGE);
26. final User user = new User();
27.                user.setUsername(username);
28.                user.setUsername(password);
29.                user.Profile());
30.                ProfileFrame.launch(user);
31.                dispose();
32.            }
33.        });
⾸先,判断输⼊的⽤户名、密码是否为空,如果为空,给出提⽰;如果不为空,再判断⽤户名是否存在于数据库中,没有不存在于数据库中说明没有注册,给出提⽰;如果存在,再判断密码与数据库中存储的密码是否⼀致,如果不⼀致,给出提⽰,如果⼀致,再判断⽤户是否已经登录了,如果⽤户在线那么数据库缓存列表有记录,如果已经登录成功了,给出提⽰,防⽌重复登录,如果没有,那么登录,跳转到聊天室页⾯。
1.1.2 修改密码部分
1. /**
2.          * 修改密码点击事件
3.          */
4.        modify_btn.addActionListener(new ActionListener() {
5. @Override
6. public void actionPerformed(ActionEvent e) {
7.                String username = Text().trim();
8.                String password = new String(Password());
9. if (username == null || password == null) {
10.                    JOptionPane.showMessageDialog(null,"⽤户名、密码不许为空!", "修改密码", JOptionPane.INFORMATION_MESSAGE);
11.                }
12. final int recv = RedisUtils.validUser(username, password);
13. if (recv == 0) {
14.                    JOptionPane.showMessageDialog(null,"⽤户不存在,请先注册!", "修改密码", JOptionPane.INFORMATION_MESSAGE);
15. return;
16.                }
17. if (recv == 1) {
18.                    JOptionPane.showMessageDialog(null,"密码错误!", "修改密码", JOptionPane.INFORMATION_MESSAGE);
19. return;
20.                }
21. final String newPassword = (String) JOptionPane.showInputDialog(null, "请输⼊新密码", "修改密
码", JOptionPane.INFORMATION_MESSAGE, null, null, null);
22.                System.out.println(newPassword);
23. if (StringUtils.isBlank(newPassword)) {
24.                    JOptionPane.showMessageDialog(null,"新密码不许为空!", "修改密码", JOptionPane.INFORMATION_MESSAGE);
25. return;
26.                }
27.  difyUser(username, newPassword);
28.            }
29.        });
⾸先,判断输⼊的⽤户名、密码是否为空,如果为空,给出提⽰;如果不为空,判断⽤户名是否存在于数据库中,如果不存在,给出注册的都提⽰;如果存在,继续判断密码,如果与数据库中存储的密码不⼀致,给出提⽰;如果⼀致,给出输⼊对话框,读取⽤户输⼊的新密码,这⾥继续判断新密码的合理性,如果为空,给出提⽰;如果和旧密码⼀样,给出提⽰;如果全是空格,给出提⽰;符合要求后存储到数据库中。
1.1.3 注册部分
1. /**
2.        * 注册点击事件
3.        */
4.        register_btn.addActionListener(new ActionListener() {
5. @Override
6. public void actionPerformed(ActionEvent e) {
7.                String username = Text().trim();
8.                String password = new String(Password());
9. if (username == null || password == null) {
10.                    JOptionPane.showMessageDialog(null,"⽤户名、密码不许为空!", "注册", JOptionPane.INFORMATION_MESSAGE);
11.                }
12. final int recv = RedisUtils.insertUser(username, password);
13. if (recv == 0) {
14.                    JOptionPane.showMessageDialog(null,"⽤户已存在,请直接登录!", "注册", JOptionPane.INFORMATION_MESSAGE);
15.                }
16. if (recv == 1) {
17.                    JOptionPane.showMessageDialog(null,"注册失败!", "注册", JOptionPane.INFORMATION_MESSAGE);
18.                }
19. if (recv == 2 ) {
20.                    JOptionPane.showMessageDialog(null,"注册成功!", "注册", JOptionPane.INFORMA
TION_MESSAGE);
21.                }
22.            }
23.        });
这⾥⾸先判断⽤户输⼊的⽤户名、密码是否为空,如果为空,给出提⽰;然后判断⽤户名是否已经存在于数据库中,如果已经存在,给出可以直接登录的提⽰;这⾥⾯新⽤户的注册细节全部由⾃⼰封装的redis数据库⼯具类完成,只需要保存调⽤函数返回的结果进⾏判断即可。
1.3⼯具类部分
1.1.1 RedisUtils⼯具类
1. public class RedisUtils {
2. /**
3.      * redis操作实体
4.      */
5. private static Jedis jedis;
6. /**
7.      * 远程服务器ip地址
8.      */
9. private static final String HOST = "101.37.32.165";
10. /**
11.      * 操作正确的返回值
12.      */
13. private static final String OK = "OK";
14. /**
15.      * 存储在线⽤户的集合
16.      */
17. private static String ALIVEUSERS = "aliveUsers";
18.
19. /**
20.      * 建⽴连接
21.      */
22. public static Jedis init() {
23.        jedis = new Jedis(HOST);
24.        jedis.select(1);
25.        Logger().RealTime() + "\t" + jedis.ping());
26. return jedis;
27.    }
28.
29. /**
30.      * 验证⽤户
31.      * @param username ⽤户名
32.      * @return 0-⽤户不存在,1-⽤户存在,密码错误,2-⽤户存在,密码正确
33.      */
34. public static int validUser(String username, String password) {
35. if (jedis == null) {
socket编程聊天室基本流程
36.            RedisUtils.init();
37.        }
38. if (! isExists(username)) {
39. return0;
40.        }
41.        String recv = (username);
42. if (! Objects.equals(recv,password)) {
43. return1;
44.        }
45. return2;
46.    }
47.
48. /**
49.      * 验证⽤户名是否存在
50.      * @param username ⽤户名
51.      * @return
52.      */
53. private static boolean isExists(String username) {
54. if (jedis == null) {
55.            RedisUtils.init();

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。