失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > java聊天室群聊及私聊实现!

java聊天室群聊及私聊实现!

时间:2024-06-10 06:26:08

相关推荐

java聊天室群聊及私聊实现!

java聊天室群聊及私聊实现!

一:业务逻辑

连接数据库,实现注册登录账号的功能使用serverSocket接收并发送消息实现服务器功能客户端使用socket与服务器交互

二:类设计及代码结构

MyMessage类:该类主要用于封装发送的消息内容ServerSocketTest类:服务器段实现类signup类:通过数据库实现登录注册SocketFrame:聊天主界面类

三:代码

Mymessage类代码:

package objtalk;import java.io.Serializable;import java.util.ArrayList;import javax.swing.text.StyledDocument;/** 该消息类分为两种* 一种是实际消息内容* 还有一种是当前群聊的成员信息* */public class MyMessage implements Serializable {// 序列化&&反序列化(用于被传输的对象)public static final long serialVersionUID = 1l;public static final int MES_TYPE_PLAIN = 1;//文本消息public static final int MES_TYPE_UPDATE_CLIENTLIST = 2;//更新用户列表消息private StyledDocument content ;//非文本消息(例如图片)private ArrayList<String> clientList;//当前群聊成员信息private int mesType = -1;private boolean ifmass=true;//判断是群聊消息还是私聊信息private String ip="null";//私发message对象ipprivate String usename = "null";public String getIp() {return ip;}public void setIp(String ip) {this.ip = ip;}public MyMessage(Boolean ifmass,int mesType) {this.ifmass=ifmass;this.mesType = mesType;}public int getMesType() {return mesType;}public void setMesType(int mesType) {this.mesType = mesType;}public StyledDocument getContent() {return content;}public void setContent(StyledDocument content) {this.content = content;}public ArrayList<String> getClientList() {return clientList;}public void setClientList(ArrayList<String> clientList) {this.clientList = clientList;}public boolean getisIfmass() {return ifmass;}public void setIfmass(boolean ifmass) {this.ifmass = ifmass;}}

signup类代码:

package objtalk;/*创建一张talk数据表* 表结构为usename和password* */import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import javax.swing.JButton;import javax.swing.JEditorPane;import javax.swing.JFrame;import javax.swing.JOptionPane;import javax.swing.JTextField;import com.mysql.jdbc.Connection;import com.mysql.jdbc.Statement;public class signup extends JFrame{private JTextField usename = new JTextField();//文本输入框private JTextField password = new JTextField();private JButton signup = new JButton("注册");//按钮private JButton signin = new JButton("登陆");//数据库信息private String user = "";private String pwd = "";private String url = "";//jdbc:myaql://ip或端口号/需要打开的databaseprivate boolean tag = false;//判断账号密码是否正确public signup() {// TODO Auto-generated constructor stubthis.setSize(300,400);this.setLocationRelativeTo(null);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setLayout(null);this.add(usename);this.add(password);this.add(signin);this.add(signup);usename.setSize(100,30);password.setSize(100,30);signin.setSize(100,50);signup.setSize(100,50);usename.setLocation(100,100);password.setLocation(100,200);signin.setLocation(50,300);signup.setLocation(150,300);try {Class.forName("com.mysql.jdbc.Driver");//开启数据库} catch (ClassNotFoundException e2) {// TODO Auto-generated catch blocke2.printStackTrace();}signin.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String useName = usename.getText().toString();String passWord = password.getText().toString();if(useName.isEmpty()||passWord.isEmpty()){JOptionPane.showMessageDialog(null, "请输入用户名或密码", "error",JOptionPane.ERROR_MESSAGE);}else{try {Connection con = (Connection) DriverManager.getConnection(url, user, pwd);//数据库连Statement stmt = (Statement) con.createStatement();//创建语句对象String sql = "select * from talk";//数据库语句ResultSet rs = (ResultSet) stmt.executeQuery(sql);//执行语句得到结果,以行的角度表现查询结果java.sql.ResultSetMetaData rsmd = rs.getMetaData();//结果以列的形式展现while(rs.next()){//按行逐个读取查询的内容,next()表示行的移动if(rs.getString(1).equals(useName)&&rs.getString(2).equals(passWord)){tag = true;new SocketFrame().setVisible(true);//跳转到主界面exits();//关闭当前界面return;}}if(tag==false){JOptionPane.showMessageDialog(null, "账号密码错误!", "error",JOptionPane.ERROR_MESSAGE);}} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}}});signup.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubString useName = usename.getText().toString();String passWord = password.getText().toString();if(useName.isEmpty()||passWord.isEmpty()){JOptionPane.showMessageDialog(null, "请输入用户名或密码", "error",JOptionPane.ERROR_MESSAGE);}else{Connection con;try {con = (Connection) DriverManager.getConnection(url, user, pwd);Statement stmt = (Statement) con.createStatement();String sql = "insert talk value('"+useName+"','"+passWord+"');";stmt.executeUpdate(sql);JOptionPane.showMessageDialog(null,"注册成功", "done",JOptionPane.ERROR_MESSAGE);//stmt.executeQuery(sql);//执行语句得到结果,以行的角度表现查询结果} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}//数据库连接,Connection是接口不能用new}}});}public void exits() {this.setVisible(false);}public static void main(String[] args) {new signup().setVisible(true);}}

SocktFrame类代码

package objtalk;import java.awt.BorderLayout;import java.awt.Font;import java.awt.Image;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.BufferedWriter;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import .Socket;import .SocketAddress;import java.nio.channels.NonWritableChannelException;import java.nio.channels.SelectableChannel;import java.util.ArrayList;import java.util.List;import javax.imageio.ImageIO;import javax.lang.model.element.Element;import javax.swing.AbstractListModel;import javax.swing.DefaultListModel;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.JDialog;import javax.swing.JFileChooser;import javax.swing.JFrame;import javax.swing.JList;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;import javax.swing.JTextPane;import javax.swing.event.AncestorListener;import javax.swing.event.ListSelectionListener;import javax.swing.filechooser.FileNameExtensionFilter;import javax.swing.text.BadLocationException;import javax.swing.text.SimpleAttributeSet;import javax.swing.text.StyleConstants;import javax.swing.text.StyledDocument;public class SocketFrame extends JFrame {private JTextPane jtpMes = new JTextPane();//消息框private StyledDocument contentDoc = jtpMes.getStyledDocument();//取出文本(),属性定义(sas的容器)private JScrollPane jspMes = new JScrollPane(jtpMes);//为消息框添加滑动框private JButton btnSend = new JButton("Send");private JButton btnConnect = new JButton("Connect");private JButton btnSelectimg = new JButton("img");private JTextPane jtpNewMes = new JTextPane();//消息框(可以显示图片和文字)private JScrollPane jspNewMes = new JScrollPane(jtpNewMes);//为群聊框添加滑动框private StyledDocument sendDoc = jtpNewMes.getStyledDocument();private JPanel panSend = new JPanel();JPanel btnPan = new JPanel();private Font font = new Font("宋体", Font.PLAIN, 20);private JList<String> listClient = new JList<>();private JScrollPane jspClientList = new JScrollPane(listClient);private Socket socket;private ObjectOutputStream out;private ReadThread reader;//读取消息线程public SocketFrame() {this.setSize(800, 600);this.setLocationRelativeTo(null);this.setDefaultCloseOperation(EXIT_ON_CLOSE);init();getContentPane().add(jspMes);getContentPane().add(panSend, BorderLayout.SOUTH);getContentPane().add(jspClientList, BorderLayout.EAST);}public void updateListClient(ArrayList list) {//跟新群聊用户信息listClient.setModel(new ClientListModel(list));}class ClientListModel extends AbstractListModel {//更新list信息ArrayList list;public ClientListModel(ArrayList list) {super();this.list = list;}@Overridepublic Object getElementAt(int arg0) {return list.get(arg0);}@Overridepublic int getSize() {return list.size();}}private void init() {panSend.setLayout(new BorderLayout());panSend.add(jspNewMes,BorderLayout.CENTER);panSend.add(btnPan,BorderLayout.EAST);btnPan.add(btnSend);btnPan.add(btnConnect);btnPan.add(btnSelectimg);jtpMes.setEditable(false);jtpMes.setFont(font);jtpNewMes.setFont(font);btnSend.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent arg0) {String str = jtpNewMes.getText().trim();//得到文本System.out.println(str);if (str != null && str.length() > 0 && socket != null) {SocketAddress address = socket.getRemoteSocketAddress();//得到本地地址String ip = address.toString().substring(1,address.toString().indexOf(":") + 1);//获得ipSimpleAttributeSet sas = new SimpleAttributeSet();//容器存储消息体StyleConstants.setFontSize(sas,24);//设置字体try {/*senDoc消息内容会自动从输入消息框获取(绑定更新,50行57行代码实现),这里只是在消息前面添加ip(类似用户名)*/sendDoc.insertString(0, ip, sas);} catch (BadLocationException e) {// TODO Auto-generated catch blocke.printStackTrace();}MyMessage mes = new MyMessage(true,MyMessage.MES_TYPE_PLAIN);mes.setContent(sendDoc);sendMes(mes);//发送消息try {sendDoc.remove(0, sendDoc.getLength());//去除容器中的内容} catch (BadLocationException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}});btnConnect.addActionListener(new ActionListener() {//连接服务器@Overridepublic void actionPerformed(ActionEvent arg0) {if(socket==null){try {socket = new Socket("10.117.45.114", 12345);//具体ip自己设置reader = new ReadThread(socket);reader.start();out = new ObjectOutputStream(socket.getOutputStream());//创建消息输入流} catch (Exception e) {e.printStackTrace();}}}});btnSelectimg.addActionListener(new ActionListener() {//选区本地图片存入容器@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubJFileChooser fc = new JFileChooser("d:");//文件选择器FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & GIF Image", "jpg","gif");//文件筛选器fc.setFileFilter(filter);int i = fc.showOpenDialog(SocketFrame.this);if(i == JFileChooser.APPROVE_OPTION){try {Image img = ImageIO.read(fc.getSelectedFile());ImageIcon icon = new ImageIcon(img);SimpleAttributeSet sas = new SimpleAttributeSet();//容器StyleConstants.setIcon(sas, icon);//把图标放入sas容器sendDoc.insertString(sendDoc.getLength(), "icon", sas);//把sas插入文本格式,属性定义} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();} catch (BadLocationException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}}});this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent arg0) {//关闭主界面后程序退出流关闭if (out != null) {MyMessage mes = new MyMessage(true,MyMessage.MES_TYPE_PLAIN);//mes.setContent("quit");sendMes(mes);reader.stopRun();}}});listClient.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {// TODO Auto-generated method stubsuper.mouseClicked(e);if(e.getClickCount()==2){//双击触发私聊new PrivateDialog(listClient.getSelectedValue().toString()).setVisible(true);}}});}public void append(StyledDocument sd){int caretPosition = jtpMes.getStyledDocument().getLength();caretPosition+=sd.getLength();try {for(int i=0;i<sd.getLength();i++){javax.swing.text.Element e = sd.getCharacterElement(i);if(e.getName().equals("icon")){contentDoc.insertString(contentDoc.getLength(), "icon", e.getAttributes());i+=2;}else{String s = sd.getText(i, 1);contentDoc.insertString(contentDoc.getLength(), s, e.getAttributes());}}contentDoc.insertString(contentDoc.getLength(), "\n", null);} catch (BadLocationException e) {// TODO Auto-generated catch blocke.printStackTrace();}jtpMes.setCaretPosition(caretPosition);}public void sendMes(MyMessage m) {if (out != null) {try {out.reset();//反复发送同一个内容不断改变的对象需要使用reset(此时为sendDoc)out.writeObject(m);out.flush();} catch (IOException e) {e.printStackTrace();}}}class ReadThread extends Thread {Socket c;boolean flag = true;public ReadThread(Socket c) {this.c = c;}@Overridepublic void run() {try {ObjectInputStream in = new ObjectInputStream((c.getInputStream()));MyMessage newMes = (MyMessage) in.readObject();while (flag) {switch (newMes.getMesType()) {case MyMessage.MES_TYPE_PLAIN:append(newMes.getContent());//将得到的消息添加进聊天框break;case MyMessage.MES_TYPE_UPDATE_CLIENTLIST:updateListClient(newMes.getClientList());//更新聊天人信息break;}//将输入流和message对象初始化供下次使用in = new ObjectInputStream((c.getInputStream()));newMes = (MyMessage) in.readObject();}} catch (Exception e) {e.printStackTrace();}}public void stopRun() {flag = false;}}class PrivateDialog extends JDialog{//单独对话框private JTextPane jtpPriMes = new JTextPane();private JScrollPane jspPriMes = new JScrollPane(jtpPriMes);private JButton btnPriSend = new JButton("Send");private JButton btnselect = new JButton("select");private JPanel panFun = new JPanel();private String ip;public PrivateDialog(String ip) {// TODO Auto-generated constructor stubthis.ip = ip;this.setTitle(ip);this.setSize(400, 300);this.setLocationRelativeTo(null);init();this.add(panFun);}private void init() {panFun.add(jtpPriMes);panFun.add(btnPriSend);panFun.add(btnselect);btnPriSend.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubString str = jtpPriMes.getText().trim();if(str!=null&&str.length()>0&&socket!=null){MyMessage mes = new MyMessage(false,MyMessage.MES_TYPE_PLAIN);mes.setIp(ip);mes.setContent(jtpPriMes.getStyledDocument());sendMes(mes);}}});btnselect.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubJFileChooser fc = new JFileChooser("d:");FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & GIF Image", "jpg","gif");//文件筛选器fc.setFileFilter(filter);int i = fc.showOpenDialog(SocketFrame.this);if(i == JFileChooser.APPROVE_OPTION){try {Image img = ImageIO.read(fc.getSelectedFile());ImageIcon icon = new ImageIcon(img);SimpleAttributeSet sas = new SimpleAttributeSet();//容器StyleConstants.setIcon(sas, icon);//把图标放入sas容器jtpPriMes.getStyledDocument().insertString(jtpPriMes.getStyledDocument().getLength(), "icon", sas);//把sas插入文本格式,属性定义} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();} catch (BadLocationException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}}});}}}

ServerSocketTest代码

package objtalk;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import .ServerSocket;import .Socket;import .SocketAddress;import java.util.ArrayList;import java.util.Arrays;import java.util.HashSet;import java.util.Iterator;import javax.swing.text.SimpleAttributeSet;import javax.swing.text.StyleConstants;import javax.swing.text.StyledDocument;import org.omg.CORBA.SystemException;public class ServerSocketTest {ServerSocket server;HashSet<Socket> clientSet = new HashSet<>();public ServerSocketTest() {try {server = new ServerSocket(12345);} catch (IOException e) {e.printStackTrace();}}public void work() {int no = 0;//连接服务器的个数try {while (true) {Socket client = server.accept();clientSet.add(client);SendUpdateClientList();no++;new ClientThread(client, no).start();}} catch (IOException e) {e.printStackTrace();}}public void SendUpdateClientList() {//发送用户变更的消息,用户退出和加入的监听MyMessage mes = new MyMessage(true,MyMessage.MES_TYPE_UPDATE_CLIENTLIST);mes.setClientList(getClientList());massMes(mes);}public void massMes(MyMessage mes) {//群发消息Iterator<Socket> it = clientSet.iterator();while (it.hasNext()) {sendMes(it.next(), mes);}}public void singleMes(MyMessage mes){//单发消息for(Socket s : clientSet){if(s.getRemoteSocketAddress().toString().equals(mes.getIp())){//String判等必须用equalssendMes(s, mes);break;}}}public void sendMes(Socket s, MyMessage mes) {ObjectOutputStream out;try {out = new ObjectOutputStream(s.getOutputStream());out.writeObject(mes);out.flush();} catch (IOException e1) {e1.printStackTrace();}}public ArrayList<String> getClientList() {ArrayList<String> list = null;if (clientSet.size() > 0) {list = new ArrayList<String>();Iterator<Socket> it = clientSet.iterator();int index = 0;while (it.hasNext()) {list.add(it.next().getRemoteSocketAddress().toString());}}return list;}class ClientThread extends Thread {Socket c;int no;public ClientThread(Socket c, int no) {super();this.c = c;this.no = no;}@Overridepublic void run() {try (ObjectInputStream in = new ObjectInputStream((c.getInputStream()));) {MyMessage newMes = (MyMessage) in.readObject();while (newMes.getContent()!=null) {//不断接收发来的消息if(newMes.getisIfmass()==true){massMes(newMes);System.out.println(newMes.getContent().getText(0,newMes.getContent().getLength() ));}else{singleMes(newMes);}newMes = (MyMessage) in.readObject();}} catch (Exception e) {e.printStackTrace();} finally {try {c.close();} catch (IOException e) {e.printStackTrace();}clientSet.remove(c);//用户退出后SendUpdateClientList();}}}public static void main(String[] args) {new ServerSocketTest().work();}}

四:使用方法:

开启ServerSocketTest类(打开服务器)开启signUp类,注册,登录,连接,开始聊天(可以多开几个实现群聊)

五:项目github地址

/Chaos1874/javaTalk

如果觉得《java聊天室群聊及私聊实现!》对你有帮助,请点赞、收藏,并留下你的观点哦!

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