1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Java 实现QQ界面聊天小项目 可聊天!

Java 实现QQ界面聊天小项目 可聊天!

时间:2021-06-30 16:15:50

相关推荐

Java 实现QQ界面聊天小项目 可聊天!

有情怀,有干货,微信搜索【程序员漫话编程】关注这个技术控程序员。

本文GitHub/ProceduralZC/JavaDevGuide已收录,有一线大厂面试完整考点、资料以及我的系列文章。

.功能实现

1.修改功能(密码、昵称、个性签名)

2.添加好友、删除好友

3.单聊功能

4.判断好友是否在线

2.模块划分

3.使用的知识

netty

swing

集合等同步阻塞队列synchronousQueue

数据库MySQL中的CRUD

C3p0连接池

JSON字符串

4.部分代码实现

tyController.java

接收到来自客户端的消息,与dao层进行交互

dao层与之数据库进行交互

修改密码

添加好友

从添加好友逻辑实现上我走了很多的弯路频繁的访问数据库,这是一件很不好的事情

packagechat.Project.controller;importchat.Project.bean.information;importchat.Project.constant.EnMsgType;importchat.Project.dao.*;importchat.utils.CacheUtil;importchat.utils.JsonUtils;importcom.fasterxml.jackson.databind.node.ObjectNode;ty.channel.Channel;importjava.util.ArrayList;importjava.util.Iterator;publicclassNettyController{privatestaticUserDaouserDao=newUserDaoImpl();privatestaticinformationDaoinformationDao=newinformationDaoImpl();privatestaticfriendDaofriendDao=newfriendDaoImpl();publicstaticStringprocessing(Stringmessage,Channelchannel){//解析客户端发送的消息ObjectNodejsonNodes=JsonUtils.getObjectNode(message);Stringmsgtype=jsonNodes.get("msgtype").asText();if(EnMsgType.EN_MSG_LOGIN.toString().equals(msgtype)){//登录操作returnloginOperation(jsonNodes,channel);}elseif(EnMsgType.EN_MSG_MODIFY_SIGNATURE.toString().equals(msgtype)){//修改签名returnmodifySignature(jsonNodes);}elseif(EnMsgType.EN_MSG_MODIFY_NICKNAME.toString().equals(msgtype)){//修改昵称returnmodifyNickname(jsonNodes);}elseif(EnMsgType.EN_MSG_GETINFORMATION.toString().equals(msgtype)){//获取登录信息returngetInformation(jsonNodes);}elseif(EnMsgType.EN_MSG_VERIFY_PASSWORD.toString().equals(msgtype)){//进行修改密码returnverifyPasswd(jsonNodes);}elseif(EnMsgType.EN_MSG_CHAT.toString().equals(msgtype)){//单聊模式returnSingleChat(jsonNodes);}elseif(EnMsgType.EN_MSG_GET_ID.toString().equals(msgtype)){//获取idreturngetId(jsonNodes);}elseif(EnMsgType.EN_MSG_GET_FRIEND.toString().equals(msgtype)){//获取好友列表returngetFriend(jsonNodes);}elseif(EnMsgType.EN_MSG_ADD_FRIEND.toString().equals(msgtype)){//添加好友returnaddFriends(jsonNodes);}elseif(EnMsgType.EN_MSG_DEL_FRIEND.toString().equals(msgtype)){//删除好友returndelFriend(jsonNodes);}elseif(EnMsgType.EN_MSG_ACTIVE_STATE.toString().equals(msgtype)){//判断好友的在线状态returnfriendIsActive(jsonNodes);}return"";}//判断好友在线状态privatestaticStringfriendIsActive(ObjectNodejsonNodes){intfriendId=jsonNodes.get("friendId").asInt();ObjectNodeobjectNode=JsonUtils.getObjectNode();objectNode.put("msgtype",EnMsgType.EN_MSG_ACK.toString());objectNode.put("srctype",EnMsgType.EN_MSG_ACTIVE_STATE.toString());//客户端保证用户独立存在且是好友Channelchannel=CacheUtil.get(friendId);//判断用户是否在线if(channel==null){//用户不在线objectNode.put("code",200);}else{//用户在线objectNode.put("code",300);}returnobjectNode.toString();}//添加好友privatestaticStringdelFriend(ObjectNodejsonNodes){IntegerfriendId=jsonNodes.get("friendId").asInt();intuserId=jsonNodes.get("id").asInt();StringlocalName=jsonNodes.get("localName").asText();//封装发回客户端的JSONObjectNodeobjectNode=JsonUtils.getObjectNode();objectNode.put("msgtype",EnMsgType.EN_MSG_ACK.toString());objectNode.put("srctype",EnMsgType.EN_MSG_DEL_FRIEND.toString());objectNode.put("code",200);//验证是否存在当前好友informationinformation=informationDao.getInformation(friendId);StringfriendName=information.getNickname();//查询自己是否有该好友booleanexist=friendDao.isExist(friendName,userId);if(exist){//存在当前好友进行删除操作friendDao.delFriend(userId,friendName);friendDao.delFriend(friendId,localName);objectNode.put("code",300);}returnobjectNode.toString();}//添加好友privatestaticStringaddFriends(ObjectNodejsonNodes){IntegerfriendId=jsonNodes.get("friendId").asInt();intuserId=jsonNodes.get("id").asInt();StringlocalName=jsonNodes.get("localName").asText();//验证是否有IDbooleanexists=userDao.verifyExistFriend(friendId);ObjectNodeobjectNode=JsonUtils.getObjectNode();objectNode.put("msgtype",EnMsgType.EN_MSG_ACK.toString());objectNode.put("srctype",EnMsgType.EN_MSG_ADD_FRIEND.toString());objectNode.put("code",200);if(exists){//表示存在此idobjectNode.put("code",300);//获取好友昵称informationinformation=informationDao.getInformation(friendId);StringfriendNickname=information.getNickname();//进行添加好友的操作两个对应的信息都应该添加friendDao.addFriends(userId,localName,friendNickname);friendDao.addFriends(friendId,friendNickname,localName);}returnobjectNode.toString();}//获取好友列表privatestaticStringgetFriend(ObjectNodejsonNodes){intuid=jsonNodes.get("uid").asInt();//返回ArrayLis集合ArrayList<String>friends=friendDao.getFriends(uid);//封装JSONObjectNodeobjectNode=JsonUtils.getObjectNode();objectNode.put("msgtype",EnMsgType.EN_MSG_ACK.toString());objectNode.put("srctype",EnMsgType.EN_MSG_GET_FRIEND.toString());//写回friend集合Iterator<String>iterator=friends.iterator();inti=0;while(iterator.hasNext()){objectNode.put("res"+i,iterator.next());i++;}//记录好友个数objectNode.put("count",i);returnobjectNode.toString();}//获取idprivatestaticStringgetId(ObjectNodejsonNodes){Stringnickname=jsonNodes.get("nickname").asText();informationinformation=informationDao.nicknameGetId(nickname);//联系人的idintuid=information.getUid();//封装JSONObjectNodeobjectNode=JsonUtils.getObjectNode();objectNode.put("msgtype",EnMsgType.EN_MSG_ACK.toString());objectNode.put("srctype",EnMsgType.EN_MSG_GET_ID.toString());objectNode.put("uid",uid);returnobjectNode.toString();}//单聊模式privatestaticStringSingleChat(ObjectNodejsonNodes){intid=jsonNodes.get("id").asInt();//根据id在friend表获取登录用户名//封装JSON数据服务端转发数据ObjectNodeobjectNode=JsonUtils.getObjectNode();objectNode.put("msgtype",EnMsgType.EN_MSG_ACK.toString());objectNode.put("srctype",EnMsgType.EN_MSG_CHAT.toString());//客户端保证用户独立存在且是好友Channelchannel=CacheUtil.get(id);//判断用户是否在线if(channel==null){//用户不在线objectNode.put("code",200);}else{//用户在线objectNode.put("code",300);//消息转发channel.writeAndFlush(jsonNodes.toString());}returnobjectNode.toString();}//修改密码privatestaticStringverifyPasswd(ObjectNodejsonNodes){intid=jsonNodes.get("id").asInt();StringoldPasswd=jsonNodes.get("oldPasswd").asText();StringnewPasswd=jsonNodes.get("newPasswd").asText();booleanexits=userDao.verifyPassword(oldPasswd,id);ObjectNodeobjectNode=JsonUtils.getObjectNode();objectNode.put("msgtype",EnMsgType.EN_MSG_VERIFY_PASSWORD.toString());objectNode.put("code",200);if(exits){//验证成功userDao.modifyPasswd(newPasswd,id);objectNode.put("code",300);}returnobjectNode.toString();}//获取信息privatestaticStringgetInformation(ObjectNodejsonNodes){intid=jsonNodes.get("id").asInt();informationinformation=informationDao.getInformation(id);//封装JSON发回客户端ObjectNodeobjectNode=JsonUtils.getObjectNode();objectNode.put("msgtype",EnMsgType.EN_MSG_ACK.toString());objectNode.put("srctype",EnMsgType.EN_MSG_GETINFORMATION.toString());objectNode.put("Nickname",information.getNickname());objectNode.put("Signature",information.getSignature());returnobjectNode.toString();}//修改昵称privatestaticStringmodifyNickname(ObjectNodejsonNodes){intid=jsonNodes.get("id").asInt();Stringnickname=jsonNodes.get("nickname").asText();//进行存储informationDao.storeNickname(nickname,id);return"";}//修改签名privatestaticStringmodifySignature(ObjectNodejsonNodes){intid=jsonNodes.get("id").asInt();Stringsignature=jsonNodes.get("signature").asText();//进行存储informationDao.storeSignature(signature,id);return"";}//登录操作privatestaticStringloginOperation(ObjectNodeobjectNode,Channelchannel){intid=objectNode.get("id").asInt();Stringpasswd=objectNode.get("passwd").asText();//进行数据库查询booleanexits=userDao.getInformation(id,passwd);ObjectNodejsonNodes=JsonUtils.getObjectNode();jsonNodes.put("msgtype",EnMsgType.EN_MSG_ACK.toString());jsonNodes.put("srctype",EnMsgType.EN_MSG_LOGIN.toString());jsonNodes.put("code",300);//返回状态码if(exits){jsonNodes.put("code",200);//添加用户的在线信息CacheUtil.put(id,channel);}returnjsonNodes.toString();}}

2.ClientHandler.java

客户端接受来自服务端返回的消息

根据返回的状态码来判断是否操作成功

ty;importchat.Frame.chat.ChatFrame;importchat.Frame.chat.linkmen;importchat.Frame.chat.login;importchat.Project.constant.EnMsgType;importchat.util.JsonUtils;importcom.fasterxml.jackson.databind.node.ObjectNode;ty.channel.ChannelHandlerContext;ty.channel.SimpleChannelInboundHandler;importjava.util.concurrent.SynchronousQueue;publicclassClientHandlerextendsSimpleChannelInboundHandler<String>{//定义一个同步阻塞队列状态码publicstaticSynchronousQueue<Object>queue=newSynchronousQueue<>();publicstaticStringNickname;publicStringSignature;@OverrideprotectedvoidchannelRead0(ChannelHandlerContextchannelHandlerContext,Strings)throwsException{}//客户端接收数据@OverridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg)throwsException{System.out.println(msg);//解析服务端发送的消息ObjectNodejsonNodes=JsonUtils.getObjectNode((String)msg);Stringmsgtype=jsonNodes.get("msgtype").asText();if(EnMsgType.EN_MSG_ACK.toString().equals(msgtype)){Stringsrctype=jsonNodes.get("srctype").asText();if(EnMsgType.EN_MSG_LOGIN.toString().equals(srctype)){//登录操作queue.offer(jsonNodes.get("code").asInt());}elseif(EnMsgType.EN_MSG_GETINFORMATION.toString().equals(srctype)){//存取信息Nickname=jsonNodes.get("Nickname").asText();Signature=jsonNodes.get("Signature").asText();linkmen.label_1.setText(Nickname);linkmen.field.setText(Signature);}elseif(EnMsgType.EN_MSG_CHAT.toString().equals(srctype)){//发送端返回消息queue.offer(jsonNodes.get("code").asInt());}elseif(EnMsgType.EN_MSG_GET_ID.toString().equals(srctype)){intuid=jsonNodes.get("uid").asInt();queue.offer(uid);}elseif(EnMsgType.EN_MSG_GET_FRIEND.toString().equals(srctype)){//获取登录用户的好友intcount=jsonNodes.get("count").asInt();login.friend=newString[count];for(inti=0;i<count;i++){login.friend[i]=jsonNodes.get("res"+i).asText();System.out.println(jsonNodes.get("res"+i));}}elseif(EnMsgType.EN_MSG_ADD_FRIEND.toString().equals(srctype)){//添加好友queue.offer(jsonNodes.get("code").asInt());}elseif(EnMsgType.EN_MSG_DEL_FRIEND.toString().equals(srctype)){//删除好友queue.offer(jsonNodes.get("code").asInt());}elseif(EnMsgType.EN_MSG_ACTIVE_STATE.toString().equals(srctype)){//好友在线状态queue.offer(jsonNodes.get("code").asInt());}}elseif(EnMsgType.EN_MSG_VERIFY_PASSWORD.toString().equals(msgtype)){//修改密码intcode=0;code=jsonNodes.get("code").asInt();queue.offer(code);}elseif(EnMsgType.EN_MSG_CHAT.toString().equals(msgtype)){//接收端接受消息封装朋友昵称Stringmessage=""+jsonNodes.get("message").asText();//聊天显示框读取消息ChatFrame.sb.append(message+"\n");ChatFrame.displayTextPanel.setText(ChatFrame.sb.toString());}}}

3.linkmen.java

这是登录成功的界面

packagechat.Frame.chat;importchat.Frame.operation.alterColumn.changeNickname;importchat.Frame.operation.alterColumn.changePassword;importchat.Frame.operation.alterColumn.changeSignature;importchat.Frame.operation.friendHandle.addFriend;importchat.Frame.operation.friendHandle.delFriend;importchat.Frame.tipFrame;importchat.Project.services.sendServers;ty.channel.Channel;importjavax.swing.*;importjavax.swing.event.ListSelectionEvent;importjavax.swing.event.ListSelectionListener;importjava.awt.*;importjava.awt.event.ItemEvent;importjava.awt.event.ItemListener;/***联系人界面*/publicclasslinkmenextendsJFrame{//容器privateJFrameframe;//标签privateJLabellabel_2,label_3,label_4,label;//昵称publicstaticJLabellabel_1;//状态框privateJComboBoxbox,box_1,box_2;//图片privateImageIconicon_1,icon;//文本privateJTextFieldfield_1;//个性签名publicstaticJTextFieldfield;//面板privateJPanelpanel_1,panel_3,panel;//滚动面板publicJScrollPanepanel_2;//列表publicstaticJListlist;//与服务端通信的通道privateChannelchannel;//用户的idprivateIntegerid;//暂存oldPasswdpublicstaticJLabellabel_5,label_6;//好友列表数组privateString[]fd;//列表publicstaticDefaultListModel<String>model;publiclinkmen(Integerid,Channelchannel,String[]fd){this.id=id;this.channel=channel;this.fd=fd;}publicvoidinit(){//初始化面板1并设置信息panel_1=newJPanel();panel_1.setLayout(null);panel_1.setLocation(0,0);panel_1.setBorder(BorderFactory.createTitledBorder("资料卡"));panel_1.setSize(newDimension(295,148));panel_1.setOpaque(false);//初始化面板3并设置信息panel_3=newJPanel();panel_3.setLayout(null);panel_3.setBorder(BorderFactory.createTitledBorder("系统设置"));panel_3.setLocation(0,617);panel_3.setSize(newDimension(295,55));panel_3.setOpaque(false);//设置头像标签label_2=newJLabel(newImageIcon("E:\\聊天软件\\untitled\\src\\imageSource\\4.png"));label_2.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));label_2.setBounds(15,15,100,100);panel_1.add(label_2);//初始暂存标签label_5=newJLabel();label_6=newJLabel();//设置昵称标签label_1=newJLabel("");label_1.setBounds(130,10,100,30);label_1.setFont(newFont("宋体",Font.PLAIN,18));panel_1.add(label_1);list=newJList<String>(model);//设置每个列表的高list.setFixedCellHeight(20);list.setSelectionBackground(newColor(0xD8FF2F));list.addListSelectionListener(newListSelectionListener(){@OverridepublicvoidvalueChanged(ListSelectionEvente){//打开一个聊天窗口if(e.getValueIsAdjusting()){for(inti=0;i<model.size();i++){if(model.get(i).equals(list.getSelectedValue())){//获取id有错误intids=newsendServers(channel).getId((String)list.getSelectedValue());if(ids!=0){newsendServers(channel).friendIsActive(ids);newChatFrame(ids,channel).setVisible(true);}else{System.out.println("好友不存在");}}}}}});//初始化面板二panel_2=newJScrollPane(list);panel_2.setBorder(BorderFactory.createTitledBorder("联系人"));panel_2.setLocation(0,147);panel_2.setSize(newDimension(295,470));panel_2.getViewport().setOpaque(false);list.setOpaque(false);panel_2.setOpaque(false);//设置在线状态bBox();box=newJComboBox();box.addItem("✅在线");box.addItem("\uD83D\uDCBF隐身");box.addItem("\uD83D\uDCBB忙碌");box.addItem("❎离线");box.setBounds(200,10,70,30);panel_1.add(box);//设置个性签名的标签label_4=newJLabel("个性签名:");label_4.setFont(newFont("宋体",Font.PLAIN,16));label_4.setForeground(Color.BLUE);label_4.setBounds(120,50,100,20);panel_1.add(label_4);//设置文本field=newJTextField("");field.setBounds(120,80,160,30);panel_1.add(field);label_3=newJLabel("\uD83D\uDD0D");label_3.setForeground(Color.RED);label_3.setBounds(10,122,20,20);panel_1.add(label_3);//设置搜索栏field_1=newJTextField();field_1.setBounds(30,120,250,25);panel_1.add(field_1);//对面板三进行初始化box_1=newJComboBox();box_1.addItem("\uD83D\uDD12\uD83D\uDD28\uD83D\uDD13");box_1.addItem("修改密码");box_1.addItem("修改昵称");box_1.addItem("修改签名");box_1.setBounds(8,20,100,25);panel_3.add(box_1);box_1.addItemListener(newItemListener(){@OverridepublicvoiditemStateChanged(ItemEvente){if("修改签名".equals(box_1.getSelectedItem())){//执行一次if(e.getStateChange()==ItemEvent.SELECTED){changeSignaturechangeSignature=newchangeSignature(linkmen.this);changeSignature.setVisible(true);field.setText(changeSignature.jTextField.getText());Stringsignature=field.getText();//存储签名的方法newsendServers(channel).modifySignature(signature,id);}}if("修改密码".equals(box_1.getSelectedItem())){if(e.getStateChange()==ItemEvent.SELECTED){changePasswordchangePassword=newchangePassword(linkmen.this);changePassword.setVisible(true);label_5.setText(changePassword.oldPassword.getText());StringoldPasswd=label_5.getText();label_6.setText(newString(changePassword.newPassword.getPassword()));StringnewPasswd=label_6.getText();//进行验证newsendServers(channel).verifyPasswd(oldPasswd,id,newPasswd);}}if("修改昵称".equals(box_1.getSelectedItem())){if(e.getStateChange()==ItemEvent.SELECTED){changeNicknamechangeNickname=newchangeNickname(linkmen.this);changeNickname.setVisible(true);label_1.setText(changeNickname.jTextField.getText());Stringnickname=label_1.getText();//存储昵称newsendServers(channel).modifyNickname(nickname,id);}}}});//添加好友、删除好友box_2=newJComboBox();box_2.addItem("\uD83D\uDC65");box_2.addItem("添加好友");box_2.addItem("删除好友");box_2.setBounds(170,20,100,25);box_2.addItemListener(newItemListener(){@OverridepublicvoiditemStateChanged(ItemEvente){if("添加好友".equals(box_2.getSelectedItem())){if(e.getStateChange()==ItemEvent.SELECTED){addFriendaddFriend=newaddFriend(linkmen.this);addFriend.setVisible(true);//读取要搜索的IDStringfriendIds=addFriend.jTextField.getText();//判断是否是字符串if(judgeDigit(friendIds)){intfriendId=Integer.parseInt(friendIds);//搜索数据库newsendServers(channel).addFriendOperate(friendId,id,label_1.getText());}else{newtipFrame().init("输入参数错误");}}}if("删除好友".equals(box_2.getSelectedItem())){if(e.getStateChange()==ItemEvent.SELECTED){delFrienddelFriend=newdelFriend(linkmen.this);delFriend.setVisible(true);//对其数据库进行删除操作StringfriendIds=delFriend.TextField.getText();//判断是否是字符串if(judgeDigit(friendIds)){intfriendId=Integer.parseInt(friendIds);//操作数据库newsendServers(channel).delFriendOperate(friendId,id,label_1.getText());}else{newtipFrame().init("输入参数错误");}}}}});panel_3.add(box_2);//设置frame信息frame=newJFrame();//设置窗体信息frame.setTitle("腾讯QQ");//给窗体设置图片icon_1=newImageIcon("E:\\聊天软件\\untitled\\src\\imageSource\\3.png");frame.setIconImage(icon_1.getImage());icon=newImageIcon("E:\\聊天软件\\untitled\\src\\imageSource\\5.png");label=newJLabel(icon);//获取窗口的第二层,将label放入frame.getLayeredPane().add(label,newInteger(Integer.MIN_VALUE));//获取frame的顶层容器,并设置为透明panel=(JPanel)frame.getContentPane();panel.setOpaque(false);frame.setLayout(null);frame.setLocation(750,150);frame.setSize(287,700);frame.setVisible(true);frame.setResizable(false);label.setBounds(0,0,287,700);frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);frame.add(panel_1);frame.add(panel_2);frame.add(panel_3);}publicvoidmian(){//初始化面板2并设置信息model=newDefaultListModel<>();for(inti=0;i<fd.length;i++){model.addElement(fd[i]);}init();//更新昵称和签名newsendServers(channel).update(id);//获取用户的昵称,和好友列表//设置签名和昵称字体初始样式和大小label_1.setFont(newFont("宋体",Font.PLAIN,18));field.setFont(newFont("宋体",Font.PLAIN,18));}//判断是否是数字privatestaticbooleanjudgeDigit(Stringstring){for(inti=0;i<string.length();i++){if(!Character.isDigit(string.charAt(i))){returnfalse;}}returntrue;}}

4.tipFrame

提示操作状态窗口

packagechat.Frame;importchat.Frame.chat.linkmen;importchat.Frame.operation.alterColumn.changeNickname;importjavax.swing.*;importjava.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;publicclasstipFrameextendsJDialog{privateContainercontainer;//显示错误信息publicJLabellabel;//确认按钮privateJButtonbutton;publictipFrame(){}publicvoidinit(Stringmsg){container=getContentPane();label=newJLabel(msg);label.setBounds(70,0,200,70);label.setFont(newFont("微软雅黑",Font.PLAIN,20));container.add(label);button=newJButton("确认");button.setBounds(35,50,140,40);container.add(button);setBounds(780,170,220,140);setLayout(null);setVisible(true);container.setBackground(newColor(0xD8FFD5));//提示窗口前置setAlwaysOnTop(true);button.addActionListener(newActionListener(){@OverridepublicvoidactionPerformed(ActionEvente){tipFrame.this.dispose();}});}}

5.运行例图

1.登录界面

注册账号和忘记密码没有添加事件现在就是个摆设

2.联系人界面

这里面的所有功能都可以使用

3.聊天界面

这个里面表情按钮没弄好

4.通信的过程

5.修改操作

6.好友的操作

文章持续更新,可以微信搜一搜「程序员漫话编程」第一时间阅读,回复【学习资料】或者【实战项目】有我准备的一线大厂面试资料和实战项目学习资源。

本文GitHub/ProceduralZC/JavaDevGuide已经收录,有大厂面试完整考点,欢迎Star。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。