java实现服务器、客户端的多线程聊天室

上课学习的利用swing界面的简单聊天室;包括登录、注册、聊天群发以及下线等功能
运行效果如图:
服务器开启:
在这里插入图片描述在这里插入图片描述
登录:
登录界面
注册:
在这里插入图片描述
聊天:
在这里插入图片描述
项目所需资料:sounds文件下是上下线的提示音。images内是背景图片,lib内是连接mysql的工具
在这里插入图片描述

配置文件jdbc.properties:

url=jdbc:mysql://localhost/shopping?useUnicode=true&characterEncoding=utf-8
username=root
password=123456
(shopping是我的数据库名称)

一、工具包(util)

1.ImageUtil用于设置屏幕背景
package goktech.util;

import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class ImageUtil extends JPanel{
	private String imgPath;
	public ImageUtil(String imgPath) {
		this.imgPath = imgPath;
	}
	
	@Override
	protected void paintComponent(Graphics g) {
		ImageIcon icon=new ImageIcon(imgPath);
		g.drawImage(icon.getImage(), 0, 0, getWidth(), getHeight(), null);
	}
}
2、JDBCUtil:用于连接数据库
package goktech.util;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtil {
	//工具类的特点:方法都是静态的
	static String url=null;
	static String username=null;
	static String password=null;
	
	//读取配置文件
	static {
		try {
			Properties pro=new Properties();
			FileInputStream in=new FileInputStream("file/jdbc.properties");
			//InputStream in=JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
			pro.load(in);
			url=pro.getProperty("url");
			username=pro.getProperty("username");
			password=pro.getProperty("password");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			}
		}
		
	//获取连接的方法
	public static Connection getConn() {
		Connection conn=null;
		try {
			//1.注册驱动java.sql.DriverManager.registerDriver(new Driver())
			//DriverManager.registerDriver(new Driver());
			//Class.forName("com.mysql.jdbc.Driver");
			//2.创建链接
			conn=DriverManager.getConnection(url,username,password);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				}
		return conn;
		}
		
	//释放资源的方法
	public static void close(Connection conn,Statement sta,ResultSet rs) {
		closeConn(conn);
		closeSta(sta);
		closeRs(rs);
		}
		
		
	//释放资源
	public static void close(Connection conn,Statement sta) {
		closeConn(conn);
		closeSta(sta);
		}
		
	//关闭连接的方法
	private static void closeConn(Connection conn) {
		try {
			if (conn!=null) {
				conn.close();
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	//关闭通道的方法
	private static void closeSta(Statement sta) {
		try {
			if (sta!=null) {
				sta.close();
				}	
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	//关闭结果集的方法
	private static void closeRs(ResultSet rs) {
		try {
			if (rs!=null) {
				rs.close();
				}	
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
}
3、WhisperUtil
package goktech.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

public class WhisperUtil {
	// Properties加载配置文件信息
	public static void loadPro(Properties pro, File file) {
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		try {
			pro.load(new FileInputStream(file));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@SuppressWarnings("unused")
	public static String getTimer() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return sdf.format(new Date());
	}
}

二、实体类(bean)

1.User:用户实体类
//封装用户类
public class User {
	private int id;
	private String userName;
	private String passWord;
	
	public User() {
		super();
	}
	public User(String userName, String passWord) {
		super();
		this.userName = userName;
		this.passWord = passWord;
	}
	public User(int id, String userName, String passWord) {
		super();
		this.id = id;
		this.userName = userName;
		this.passWord = passWord;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassWord() {
		return passWord;
	}
	public void setPassWord(String passWord) {
		this.passWord = passWord;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", userName=" + userName + ", passWord=" + passWord + "]";
	}
}

2、ChatBean:封装聊天信息
package goktech.bean;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;

//聊天信息的封装类
public class ChatBean implements Serializable{
	private static final long serialVersionUID=1L;
	private int type;   //聊天类型  1.上线更新   -1下线更新
	private HashSet<String> clients;         //存放先选中的用户
	private HashMap<String,Client> onlines;  //存放在线用户
	private String name;  //姓名
	private String info;  //信息
	private String timer; //时间
	public ChatBean() {
		super();
	}
	public ChatBean(int type, HashSet<String> clients, HashMap<String, Client> onlines, String name, String info,
			String timer) {
		super();
		this.type = type;
		this.clients = clients;
		this.onlines = onlines;
		this.name = name;
		this.info = info;
		this.timer = timer;
	}
	public int getType() {
		return type;
	}
	public void setType(int type) {
		this.type = type;
	}
	public HashSet<String> getClients() {
		return clients;
	}
	public void setClients(HashSet<String> clients) {
		this.clients = clients;
	}
	public HashMap<String, Client> getOnlines() {
		return onlines;
	}
	public void setOnlines(HashMap<String, Client> onlines) {
		this.onlines = onlines;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getInfo() {
		return info;
	}
	public void setInfo(String info) {
		this.info = info;
	}
	public String getTimer() {
		return timer;
	}
	public void setTimer(String timer) {
		this.timer = timer;
	}
	public static long getSerialversionuid() {
		return serialVersionUID;
	}
}
3、Client:客户端实体类
package goktech.bean;
import java.net.Socket;
//封装的客户端实体类
public class Client {
	private String name;       //客户端名称
	private Socket socket;     //客户端的socket
	
	public Client() {
		super();
	}

	public Client(String name, Socket socket) {
		super();
		this.name = name;
		this.socket = socket;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Socket getSocket() {
		return socket;
	}

	public void setSocket(Socket socket) {
		this.socket = socket;
	}
}

三、dao包

package goktech.dao;
import goktech.bean.User;
public interface UserDao {
	//根据用户名查询用户的方法
	boolean selectByName(String username);
	
	//插入数据的方法(注册)
	int insertUser(User user);
	
	//登录的方法
	User login(String userName,String passWord);
}

四、dao.impl:dao包类的具体实现

package goktech.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import goktech.bean.User;
import goktech.dao.UserDao;
import goktech.util.JDBCUtil;

public class UserDaoImpl implements UserDao{
	@Override
	public boolean selectByName(String username) {
		Connection conn=null;
		PreparedStatement pre=null;
		ResultSet rs=null;
		try {
			//1.创建连接
			conn=JDBCUtil.getConn();
			String sql="select * from user where username=?";
			//2.创建通道
			pre=conn.prepareStatement(sql);
			//3.给参数赋值
			pre.setString(1, username);
			//4.执行查询
			rs=pre.executeQuery();
			//5.遍历结果集
			if(rs.next()) {
				return true;
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			//6.释放资源
			JDBCUtil.close(conn, pre, rs);
		}
		return false;
	}

	@Override
	public int insertUser(User user) {
		Connection conn=null;
		PreparedStatement pre=null;
		int i=0;
		try {
			//1.创建连接
			conn=JDBCUtil.getConn();
			String sql="insert into user(username,password) values (?,?)";
			//2.创建通道
			pre=conn.prepareStatement(sql);
			//3.给参数赋值
			pre.setString(1, user.getUserName());
			pre.setString(2, user.getPassWord());
			//4.执行更新
			i=pre.executeUpdate();
			//5.遍历结果集
			return i;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			//6.释放资源
			JDBCUtil.close(conn, pre);
		}
		return i;
	}

	@Override
	public User login(String userName, String passWord) {
		Connection conn=null;
		PreparedStatement pre=null;
		ResultSet rs=null;
		User user=null;
		
		try {
			//1.创建链接
			conn=JDBCUtil.getConn();
			String sql="select * from user where username=? and password=?";
			//2.创建通道
			pre=conn.prepareStatement(sql);
			//3.给参数赋值
			pre.setString(1, userName);
			pre.setString(2, passWord);
			//4.执行查询
			rs=pre.executeQuery();
			//5.遍历结果集
			while (rs.next()) {
				String name=rs.getString("username");
				String pass=rs.getString("password");
				user=new User(name, pass);
			}
			return user;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//6.释放资源
			JDBCUtil.close(conn, pre, rs);
		}
		return user;
	}
}

五、server:服务器界面

package goktech.server;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import goktech.bean.ChatBean;
import goktech.bean.Client;
import goktech.util.WhisperUtil;

public class Server extends JFrame implements ActionListener{
	//服务器页面相关属性
	private JPanel panel;
	private JLabel label1,label2;
	private JTextField textfield;
	private JButton start,end;
	
	//相关变量
	private ServerSocket serverSocket;
	private HashMap<String,Client> onlines=new HashMap<>();
	
	//服务器属性初始化
	public Server() {
		init();
	}
	//初始化属性
	private void init() {
		this.setTitle("聊天室服务器");   //设置标题
		this.setSize(400, 600);		//设置宽高
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   //设置关闭方式
		this.setResizable(false);    //设置大小不可变
		this.setLocationRelativeTo(null);   //设置居中
		
		panel=new JPanel();
		panel.setLayout(null);//绝对布局
		
		label1=new JLabel("端口");
		label1.setFont(new Font("微软 雅黑",Font.BOLD,16));
		label1.setBounds(110, 150, 50, 30);
		
		textfield=new JTextField();
		textfield.setText("8099");
		//设置文本框字体
		textfield.setHorizontalAlignment(JTextField.CENTER);  //设置字体居中
		textfield.setBounds(180, 150,80,30);
		//按钮初始化
		start=new JButton("启动服务器");
		start.setBounds(120, 250, 140, 35);
		//按钮绑定事件
		start.addActionListener(this);
		
		//添加组件到画板
		panel.add(label1);
		panel.add(textfield);
		panel.add(start);
		
		this.add(panel);
		this.setVisible(true);
	}
	
	//start.addActionListener(this);start点击执行下面的代码
	@Override
	public void actionPerformed(ActionEvent e) {
		//e.getActionCommand()获取按钮的值
		if("启动服务器".equals(e.getActionCommand())) {
			String text=textfield.getText();
			//将端口号保存到配置文件去
			Properties pro=new Properties();
			pro.setProperty("port", text);
			pro.setProperty("ip", "127.0.0.1");
			try {
				FileOutputStream fos=new FileOutputStream("file/config.properties");
				pro.store(fos,"服务器的端口号配置文件");
			} catch (FileNotFoundException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
			int port=Integer.parseInt(text);
			try {
				//创建服务器端的socket
				serverSocket=new ServerSocket(port);
				onlines=new HashMap<String,Client>();
				
				//更新页面
				panel.removeAll();
				panel.setBackground(Color.cyan);
				label2=new JLabel("端口:"+port+",服务器正在运行,请勿关闭");
				label2.setFont(new Font("微软雅黑",Font.BOLD, 16));
				label2.setBounds(50, 100, 300, 50);
				
				end=new JButton("关闭服务器");
				end.setBounds(120, 250, 140, 35);
				end.addActionListener(this);

				panel.add(label2);
				panel.add(end);
				//调用方法更新
				panel.updateUI();
				
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			//因为服务器要不断监听客户端,所以需要创建一个线程,不断监听客户端连接
			new ServerThread().start();
		}else if("关闭服务器".equals(e.getActionCommand())) {
			System.exit(-1);	
		}
	}
	
	/**
	 * 服务器线程
	 * @author Administrator
	 *
	 */
	class ServerThread extends Thread{
		public void run() {
			try {
				while(true) {
					//监听客户端连接,获取到连接服务器的客户端的socket
					Socket socket = serverSocket.accept();
					System.out.println(socket+":连上了服务器");
					//因为监听到了客户端连接要对该客户端不断进行读写,所以创建了一个对服务器进行读写的线程
					new ClientThread(socket).start();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
		    	e.printStackTrace();
			}
		}
	}
	/**
	 * 客户端线程
	 * 服务器专门对客户端进行读写的过程
	 * @author Administrator
	 *
	 */
	class ClientThread extends Thread{
		private Socket socket;  //客户端的socket
		private ChatBean bean;
		private ObjectOutputStream oos;
		private ObjectInputStream ois;
		
		public ClientThread(Socket socket) {
			this.socket=socket;
		}
			
		public void run() {
			try {
				while(true) {
					ois=new ObjectInputStream(socket.getInputStream());
					bean=(ChatBean)ois.readObject();
					switch(bean.getType()) {
						
					case 0:{
						//0:表示上下线更新列表
						//创建客户端相关信息
						Client client=new Client();
						client.setName(bean.getName());
						client.setSocket(socket);
						onlines.put(bean.getName(), client);
							
						//告诉其他客户端XXX上线的消息
						ChatBean chatbean=new ChatBean();
						//存放在线用户名
						HashSet<String>set=new HashSet<>();
						set.addAll(onlines.keySet());
						chatbean.setClients(set);
						chatbean.setInfo(WhisperUtil.getTimer()+" "+bean.getName()+"上线了\n");
						bean.setType(0);
							
						sendAll(chatbean);
						break;
					}   
					case -1: {
						 //下线
						ChatBean chatbean=new ChatBean();
						chatbean.setType(-1);
						//返回结果运行客户端下线
						oos=new ObjectOutputStream(socket.getOutputStream());
						oos.writeObject(chatbean);
						oos.flush();
							
						//在线用户列表移除该下线用户
						onlines.remove(bean.getName());
						//通知剩下的用户有人下线了并刷新其列表
						ChatBean chatbean2=new ChatBean();
						chatbean2.setType(0);
						chatbean2.setInfo(bean.getTimer()+" "+bean.getName()+" 下线了\n");
							
						HashSet<String> set=new HashSet<>();
						set.addAll(onlines.keySet());
						chatbean2.setClients(set);
						
						sendAll(chatbean2);
						return;
					} 
					case 1:{
						//聊天
						ChatBean chatbean=new ChatBean();
						chatbean.setType(1);
						chatbean.setTimer(bean.getTimer());
						chatbean.setInfo(bean.getInfo());
						chatbean.setClients(bean.getClients());
						chatbean.setName(bean.getName());
							
						sendMessage(chatbean);
						break;
					}
					default:
						break;
					}
				}
			} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
			} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
			}finally {
				close();
			}
		}

		/**
		 * 发送信息
		 * @param chatbean
		 */
		private void sendMessage(ChatBean chatbean) {
			Collection<Client> allOnlines=onlines.values();
			Iterator<Client>it=allOnlines.iterator();
			HashSet<String>clients=chatbean.getClients();
			while(it.hasNext()) {
				Socket socket=null;
				Client client=it.next();
				if(clients.contains(client.getName())) {
					socket=client.getSocket();
					
					try {
						oos=new ObjectOutputStream(socket.getOutputStream());
						oos.writeObject(chatbean);
						oos.flush();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
			
		/**
		 * 负责向每个在线用户刷新信息
	     * @param cb
		 */
		private void sendAll(ChatBean cb) {
			//1.获取所有的在线客户端Socket
			Collection<Client>clients=onlines.values();
			//2.遍历集合,取到每一个客户端
			Iterator<Client>it=clients.iterator();
			ObjectOutputStream oos=null;
			//3.把消息类用输出流发送给每一个客户端
			while(it.hasNext()) {
			    Socket socket=it.next().getSocket();
				try{
					oos=new ObjectOutputStream(socket.getOutputStream());
					oos.writeObject(cb);
					oos.flush();
				}catch (IOException e) {
					e.printStackTrace();
				} 
			}
		}
		/**
		 * 关闭流
	     */
		public void close() {
			if(oos!=null) {
				try {
						oos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(ois!=null) {
				try {
						ois.close();
				} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
				}
			}
			if(socket!=null) {
				try {
					socket.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
				    e.printStackTrace();
				}
			}
		}
	}
	public static void main(String[] args) {
		Server server=new Server();
	}
}
	

六、login:包括登录界面和注册界面

1、login:登录
package goktech.login;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import java.awt.BorderLayout;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;
import javax.swing.JTextField;
import goktech.bean.ChatBean;
import goktech.bean.User;
import goktech.client.ChatRoom;
import goktech.dao.UserDao;
import goktech.dao.impl.UserDaoImpl;
import goktech.util.ImageUtil;
import javax.swing.JButton;
import java.awt.Color;

public class Login extends JPanel implements ActionListener{
	private JLabel user;
	private JLabel pass;
	private JTextField userName;
	private JPasswordField password;
	private JLabel welcome;
	private JButton login;
	private JButton register;
	private ImageUtil imageUtil;   //用来设置背景样式
	private JFrame JFrame;
	
	private Socket socket;
	private UserDao userdao=new UserDaoImpl();
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		new Login();
	}

	/**
	 * Create the application.初始化属性
	 */
	public Login() {
		init();
	}

	/**
	 * 进行属性初始化
	 */
	private void init() {
		
		JFrame=new JFrame("登陆界面");
		JFrame.setTitle("轻语聊天室");
		JFrame.setSize(500,300);
		JFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JFrame.setResizable(false);
		JFrame.setLocationRelativeTo(null);   
		this.setLayout(null);    //设置绝对布局
		
		//背景设置
		imageUtil=new ImageUtil("images/whisper.png");
		imageUtil.setBounds(120, 5, 300, 300);
		
		welcome=new JLabel("欢迎登录");
		welcome.setFont(new Font("楷体", Font.BOLD, 36));
		welcome.setBounds(120, 5, 200, 100);
		
		user=new JLabel("用户名");
		user.setBounds(60,100, 50,30);
		
		pass=new JLabel("密码");
		pass.setBounds(60,140,50,30);
		
		userName=new JTextField(10);
		userName.setBounds(120,100,140,30);
		
		password=new JPasswordField(10);
		password.setBounds(120,140,140,30);
		
		//按钮的初始化
		login=new JButton("登录");
		login.setBackground(Color.GREEN);
		login.setBounds(280,210,80,30);
		//登录按钮的点击事件
		login.addActionListener(this);
		
		register=new JButton("注册");
		register.setBackground(Color.orange);
		register.setBounds(380, 210,80,30);
		//注册按钮的点击事件
		register.addActionListener(this);
		
		this.add(welcome);
		this.add(user);
		this.add(pass);
		this.add(userName);
		this.add(password);
		this.add(login);
		this.add(register);
		this.add(imageUtil);
		
		JFrame.add(this);
		JFrame.setVisible(true);
	}

	//给按钮绑定点击事件
	@Override
	public void actionPerformed(ActionEvent e) {
		String name=userName.getText();
		String pass=password.getText();
		if("登录".equals(e.getActionCommand())) {
			if(name.equals("")||pass.equals("")) {
				JOptionPane.showMessageDialog(null, "用户名或密码为空");
			}else {
				//传入用户密码,判断是否存在
				User user=userdao.login(name,pass);
				if(user==null) {
					JOptionPane.showMessageDialog(null, "用户名或者密码错误,请重新输入!");
				}else {
					//表示登录成功
					JOptionPane.showMessageDialog(null, "登录成功!");
					String ip=getIpOrPort("ip");
					int port=Integer.parseInt(getIpOrPort("port"));
					try {
						//创建客户端的socket
						socket=new Socket(ip,port);
						//创建聊天界面
						ChatRoom cr=new ChatRoom(name,socket);
						//关闭当前页面
						JFrame.setVisible(false);
					} catch (Exception e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
			}
			
		}else if("注册".equals(e.getActionCommand())) {
			JFrame.setVisible(false);//关闭当前登录页面
			Register register=new Register();//打开注册页面
		}
	}
	
	private String getIpOrPort(String key) {
		String result=null;
		Properties pro=new Properties();
		try {
			FileInputStream in=new FileInputStream("file/config.properties");
			//需要加载的配置文件
			pro.load(in);
			result=pro.getProperty(key);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
}
2、Register:注册
package goktech.login;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import goktech.bean.User;
import goktech.dao.UserDao;
import goktech.dao.impl.UserDaoImpl;
import goktech.util.ImageUtil;

public class Register extends JPanel implements ActionListener{
	//页面布局属性
	private JLabel user;
	private JLabel pass,rePass;
	private JTextField userName;
	private JPasswordField password,rePassword;
	private JLabel welcome;
	private JButton cancel;
	private JButton register;
	private ImageUtil imageUtil;   //用来设置背景样式
	private JFrame JFrame;
	private Socket socket;
	private UserDao userdao=new UserDaoImpl();
	private User user2;
	
	//初始化属性
		public Register() {
			init();
		}

	private void init() {
		JFrame=new JFrame("注册界面");
		JFrame.setTitle("轻语聊天室");
		JFrame.setSize(500,300);
		JFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JFrame.setResizable(false);
		JFrame.setLocationRelativeTo(null);
		this.setLayout(null);    //设置绝对布局
		
		//背景设置
		imageUtil=new ImageUtil("images/whisper.png");
		imageUtil.setBounds(120,5,300,300);
		
		welcome=new JLabel("欢迎注册");
		welcome.setFont(new Font("楷体",Font.BOLD,36));
		welcome.setBounds(120, 5, 200, 100);
		
		user=new JLabel("用户名");
		user.setBounds(60,100,50,30);
		
		pass=new JLabel("密码");
		pass.setBounds(60,140,50,30);
		
		userName=new JTextField(10);
		userName.setBounds(120,100,140,30);
		
		password=new JPasswordField(10);
		password.setBounds(120,140,140,30);
		
		rePass=new JLabel("确认密码");
		rePass.setBounds(60,180,80,30);	
		
		rePassword=new JPasswordField(10);
		rePassword.setBounds(120,180,140,30);
		
		//按钮的初始化
		register=new JButton("注册");
		register.setBackground(Color.green);
		register.setBounds(280,210,80,30);
		//登录按钮的点击事件
		register.addActionListener(this);
		
		cancel=new JButton("返回");
		cancel.setBackground(Color.orange);
		cancel.setBounds(380,210,80,30);
		//取消按钮的点击事件
		cancel.addActionListener(this);
		
		this.add(welcome);
		this.add(user);
		this.add(pass);
		this.add(rePass);
		this.add(userName);
		this.add(password);
		this.add(rePassword);
		this.add(cancel);
		this.add(register);
		this.add(imageUtil);
		
		JFrame.add(this);
		JFrame.setVisible(true);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		String name=userName.getText();
		String passWord=password.getText();
		String repassWord=rePassword.getText();
		if("注册".equals(e.getActionCommand())) {
			if(name.equals("")||passWord.equals("")||repassWord.equals("")) {
				JOptionPane.showMessageDialog(null, "用户名或密码不能为空");
			}else {
				if(!passWord.equals(repassWord)) {
					JOptionPane.showMessageDialog(null, "两次密码不一致");
				}else {
					//去数据库查询用户名是否重复
					boolean b=userdao.selectByName(name);
					if(b) {
						//提示用户该用户名已存在
						JOptionPane.showMessageDialog(null, "该用户名已存在,请重新输入!");
					}else {
						//输入数据成功,注册成功;向数据库插入数据
						user2=new User(name, repassWord);
						//判断向数据库插入信息是否成功
						if(userdao.insertUser(user2)>0) {
							JOptionPane.showMessageDialog(null, "注册成功!");
							//JFrame.setVisible(false);
							new Login();
						}else {
							JOptionPane.showMessageDialog(null, "注册失败,请稍后再试!");
						}
					}
				}
			}
		}else if("返回".equals(e.getActionCommand())) {
			//JFrame.setVisible(false);
			new Login();
		}
	}
	public static void main(String[] args) {
		new Register();
	}
}

七、客户端(client)

package goktech.client;

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import javax.swing.AbstractListModel;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;

import goktech.bean.ChatBean;
import goktech.util.ImageUtil;
import goktech.util.WhisperUtil;

//聊天室界面
public class ChatRoom extends JPanel implements ActionListener{
	//聊天室界面属性
	private static final long serialVersionUID=1L;
	private JFrame JFrame;
	private ImageUtil imageUtil;
	//发送框、接收框、好友列表的滚动条
	private JScrollPane sendMsg,receiveMsg,friendList;
	//信息接收框、消息发送框
	private JTextArea receiveInfo,sendInfo;
	// 显示指定数组中的元素(列表容器)
	private JList<String> list;
	// 用于显示当前用户
	private JLabel currentUser;
	// 发送和关闭按钮
	private JButton send, close;
	
	//聊天室其他属性
	private String name;
	private Socket socket;
	private ObjectOutputStream oos;
	private ObjectInputStream ois;
	private Vector onlines;
	private static AbstractListModel listmodel;//列表模型

	private File file1, file2;
	// 消息提示音
	private URL sound1;
	// 上线提示音
	private URL sound2;
	private AudioClip audioClip1, audioClip2;
	
	//聊天室构造方法
	public ChatRoom(String name,Socket socket) {
		this.name=name;
		this.socket=socket;
		onlines=new Vector<>();
		init();
		
		try {
			oos=new ObjectOutputStream(socket.getOutputStream());
			//记录上线用户的信息在chatbean中,并发送给服务器
			ChatBean chatbean=new ChatBean();
			chatbean.setType(0);
			chatbean.setName(name);
			chatbean.setTimer(WhisperUtil.getTimer());
			oos.writeObject(chatbean);
			oos.flush();
			
			//加载音频:消息提示音
			file1=new File("sounds/叮.wav");
			file2=new File("sounds/呃欧.wav");
			
			//转化音频文件为URL格式
			sound1=file1.toURL();
			sound2=file2.toURL();
			
			//包装音频URL
			audioClip1=Applet.newAudioClip(sound1);
			audioClip2=Applet.newAudioClip(sound2);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try {
			//通知服务器,客户端上线了
			ChatBean cb=new ChatBean();
			cb.setType(0);
			cb.setName(name);
			//发送给服务器
			oos=new ObjectOutputStream(socket.getOutputStream());
			oos.writeObject(cb);
			oos.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		//读取服务器发送过来的消息(用一个线程,因为不知道什么时候要接收服务器发送的消息)
		new ClientInputThread().start();
		
		JFrame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				int result = JOptionPane.showConfirmDialog(JFrame.getContentPane(), "您确定要离开聊天室嘛?");
				if (result == 0) {
					ChatBean chatBean = new ChatBean();
					chatBean.setType(-1);
					chatBean.setName(name);
					chatBean.setTimer(WhisperUtil.getTimer());
					sendMessage(chatBean);
//					jFrame.setVisible(false);
				}
			}
		});
	}
	
	//聊天室界面属性初始化
	private void init() {
		JFrame = new JFrame("轻语聊天室");
		JFrame.setSize(800, 600);
		JFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		JFrame.setResizable(false);
		JFrame.setLocationRelativeTo(null);
		this.setLayout(null);

		imageUtil = new ImageUtil("images/bc.jpg");
		imageUtil.setBounds(0, 0, 800, 600);

		// 页面布局
		// 接收框的布局
		receiveInfo = new JTextArea();
		receiveInfo.setEditable(false);  //关闭编辑
		receiveInfo.setLineWrap(true);   //自动换行
		receiveInfo.setFont(new Font("宋体", Font.BOLD, 15));
		
		//添加文本域到滚动条里
		receiveMsg = new JScrollPane();
		receiveMsg.setBounds(30, 10, 520, 380);
		receiveMsg.setViewportView(receiveInfo);

		//发送框布局
		sendInfo = new JTextArea();
		sendInfo.setLineWrap(false);
		sendInfo.setFont(new Font("宋体", Font.BOLD, 15));
	
		//添加到滚动条里
		sendMsg = new JScrollPane(sendInfo);
		sendMsg.setBounds(30, 400, 520, 120);
		//发送按钮
		send = new JButton("发送");
		send.setBackground(Color.green);
		send.setBounds(450, 520, 100, 30);
		send.addActionListener(this);//绑定事件
		//关闭按钮
		close = new JButton("关闭");
		close.setBackground(Color.yellow);
		close.setBounds(345, 520, 100, 30);
		close.addActionListener(this);//绑定事件

		//显示当前用户的名字
		currentUser = new JLabel("你好," + name + "!");
		//设置字体水平居中
		currentUser.setHorizontalAlignment(JLabel.CENTER);
		currentUser.setFont(new Font("楷体", Font.BOLD, 20));
		currentUser.setBounds(560, 10, 230, 50);

		//好友列表
		list = new JList<>();
		//设置选择模式——表示可以选择不相邻的几页
		list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);// 表示可以选择不相邻的几项
		list.setFont(new Font("华文行楷", Font.BOLD, 18));
		list.setBackground(Color.white);
		
		// 设置虚边框样式
		Border etch = BorderFactory.createEtchedBorder();
		list.setBorder(BorderFactory.createTitledBorder(etch, "在线用户:", TitledBorder.LEADING, TitledBorder.TOP,new Font("楷体", Font.BOLD, 20), Color.green));

		//初始化滚动条
		friendList = new JScrollPane();
		friendList.setViewportView(list);      //不直接将子集添加到滚动窗口
		friendList.setBounds(560, 60, 230, 330);

		this.add(send);
		this.add(close);
		this.add(currentUser);
		this.add(receiveMsg);
		this.add(sendMsg);
		this.add(friendList);
		this.add(imageUtil);

		JFrame.add(this);
		JFrame.setVisible(true);
	}
	
	/**
	 * 传入Vector,创建ListModel
	 * 为了更新页面的list集合,封装了一个model类
	 */
	class ListModel extends AbstractListModel{
		private Vector vs;
		
		public ListModel(Vector vs) {
			this.vs=vs;
		}
		
		@Override
		public int getSize() {
			return vs.size();
		}

		@Override
		public Object getElementAt(int index) {
			return vs.get(index);
		}
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==close) {
			int status = JOptionPane.showConfirmDialog(null, "您要离开聊天室吗?");
			System.out.println(status);
			if (status == 0) {
				close.setEnabled(false);
				ChatBean chatBean = new ChatBean();
				chatBean.setType(-1);
				chatBean.setName(name);
				chatBean.setTimer(WhisperUtil.getTimer());
				sendMessage(chatBean);
                //JFrame.setVisible(false);
			}
		}else if(send==e.getSource()) {
			//发送信息
			String string = sendInfo.getText();
			List<String> to = list.getSelectedValuesList();
			if (to.size() < 1) {
				JOptionPane.showMessageDialog(null, "请选择聊天对象!");
				return;
			} else if (to.toString().contains(name + "(我)")) {
				JOptionPane.showMessageDialog(null, "不能向自己发送信息!");
				return;
			} else if (string.equals("")) {
				JOptionPane.showMessageDialog(null, "不能发送空信息!");
				return;
			}

			ChatBean chatBean = new ChatBean();
			HashSet<String> set = new HashSet<>();
			set.addAll(to);
			chatBean.setClients(set);
			chatBean.setName(name);
			chatBean.setInfo(string);
			chatBean.setType(1);
			String time = WhisperUtil.getTimer();
			chatBean.setTimer(time);
			sendMessage(chatBean);

			receiveInfo.append(time + "我对" + to + "说:\r\n" + string + "\r\n\n");
			sendInfo.setText(null);
		}
	}
	public static void main(String[] args) {
		
	}
	
	
	/**
	 * 用户读取服务器发送的信息
	 * 客户端接收服务器端传送过来的消息
	 * @author Administrator
	 *
	 */
	class ClientInputThread extends Thread{
		public void run() {
			try {
				while(true) {//表示一直可以接收消息
					//读取服务器的对象流
					ois=new ObjectInputStream(socket.getInputStream());
					ChatBean cb=(ChatBean)ois.readObject();
					switch(cb.getType()) {
					//更新上线
					case 0:{
						onlines.clear();//清空在线用户列表
						HashSet<String>clients=cb.getClients();
						Iterator<String>it=clients.iterator();
						while(it.hasNext()) {
							String clientName=it.next();
						if(clientName.equals(name)) {
								onlines.add(clientName+"(我)");
							}else {
								onlines.add(clientName);
							}
						}
						listmodel=new ListModel(onlines);
						list.setModel(listmodel);
						//在消息接收文本域添加消息
						audioClip1.play();
						receiveInfo.append(cb.getInfo());
						receiveInfo.selectAll();
						break;
					}	
					case 1:     //聊天
					{
						String info = cb.getTimer() + "  " + cb.getName() + " 对 " + cb.getClients() + "说:\r\n";
						if (info.contains(name)) {
							info = info.replace(name, "我");
						}
						audioClip1.play();
						receiveInfo.append(info + cb.getInfo() + "\r\n\n");
						receiveInfo.selectAll();
						break;
					}
					case -1:    //下线
					{
						return;
					}
					default:
						break;
					}
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally {
				close();
				System.exit(0);
			}
		}
	}
	
	/**
	 * 关闭流
	 */
	public void close() {
		if (oos != null) {
			try {
				oos.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (ois != null) {
			try {
				ois.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (socket != null) {
			try {
				socket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 发送信息
	 */
	private void sendMessage(ChatBean chatBean) {
		try {
			oos = new ObjectOutputStream(socket.getOutputStream());
			oos.writeObject(chatBean);
			oos.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

到这好像就没了,就是将上课学的例子稍微改了下,完整项目下载地址://download.csdn.net/download/qq_45100706/12269480
侵权联系删。

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值