(一)配置
(1)下载jar包
1.选择Platform Independent
2.点击第二个Download
3.点击红框部分
4.下载jar包进行解压
(2)将jar包导入Java项目
1. 打开eclipse创建一个新项目
2.右击 项目名在 New 下点击 Folder,创建 lib 文件夹
3.将下载好的驱动包用鼠标左键拖入lib文件中
出现该选项框,点击 OK 即可
lib 目录下出现该驱动包
4.右击该驱动包, Build Path —> Add to Build Path
项目目录下出现 Referenced Libraries 文件夹
5.右击 src 新建一个包 Package取名为 JavaJdbc,点击 Finish,然后将打包的项目中的Java文件放到包里。
6.将图片mount.jpg放入src文件夹下。
(3)新建Java数据库导入sql文件
1.使用小P面板打开MYSQL数据库
2.右键localhost新建一个数据库
3.名称改为java后点击确定
4.右键新建的Java数据库,点击输入SQl文件(已上传资源)
5.点击打包的项目里的java.sql,然后点击打开
6.前置条件完成,可以进行项目功能验证
(二)效果展示
用户可以通过注册界面输入用户名、密码等信息进行注册,并保存到数据库中。。
1. 运行server.java文件
弹出服务器界面
2. 运行login.java文件弹出登陆界面后点击注册
输入完用户名、密码后回车或点击注册
弹出注册成功界面则点击返回登陆回到登陆界面进行登录
用户输入用户名和密码后,系统会验证其信息的正确性,如果验证通过,则用户可以登录到聊天室。
3.回到登陆界面,输入注册的用户名和密码点击登录
4. 用户名和密码正确,用户登陆到聊天室
如果用户名或者密码错误,则会出现弹窗
5. 在线用户列表
在聊天室和服务器界面上,系统会实时显示当前在线用户的列表。
用户登录成功,服务器的列表会显示所有用户的用户名
用户登录成功,聊天室的用户列表会显示除自己以外的所有用户
6. 公聊
用户登录后可以在聊天室公聊板块中与其他用户进行交流,由于支持文本消息的发送和接收。
在文本框输入信息进行回车或者点击发送大厅消息
消息发送完毕,会显示在文本区域
对其他用户,消息发送方则会显示用户昵称
7. 私聊
用户可以向其他用户发起私聊请求,并进入私聊界面进行一对一的交流,私聊内容只有双方可见。
选中聊天室界面的用户列表在线的用户,点击私发消息
显示私聊界面,在输入框中输入消息后回车,或者点击发消息按钮发送消息
接收方收到系统提示
接收方弹出私聊界面
8. 保存聊天记录
系统会将聊天室公聊和私聊的内容保存到文件中,方便用户查看历史记录。
用户登录后,右键javajdbc,点击Refresh
在聊天记录文件夹下就能看到不同用户的聊天记录
聊天记录有标记私聊和公聊
9. 踢人
管理员可以通过后台管理界面选择将某个用户踢出聊天室,以维护聊天室的秩序。
选中服务器用户列表的用户,点击踢出聊天室
该用户出现弹窗提示被移出聊天室
用户收到该用户下线信息,用户列表更新
(三)源代码
1.server.java
package javajdbc;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
class server extends JFrame implements Runnable, ListSelectionListener, ActionListener {
private Socket s = null;
private ServerSocket ss = null;
private ArrayList<ChatThread> users = new ArrayList<ChatThread>(); //容量能够动态增长的数组
DefaultListModel<String> dl = new DefaultListModel<String>();
private JList<String> userList = new JList<String>(dl);//显示对象列表并且允许用户选择一个或多个项的组件。单独的模型 ListModel 维护列表的内容。
private JPanel jpl = new JPanel();
private JButton jbt = new JButton("踢出聊天室");
private JButton jbt1 = new JButton("群发消息");
//群发消息输入栏
JTextField jtf = new JTextField(20);
JLabel input2 = new JLabel("请输入:");
//private JAreaText jtx=new JAreaText();
public server() throws Exception{
this.setTitle("服务器端");
SwingUtilities.invokeLater(new Runnable() { // 在事件分派线程中执行初始化操作和界面布局
public void run() {
userList.setBackground(new Color(224,224,239)); // 设置列表背景色
userList.repaint(); // 强制重新绘制界面,以显示新的背景色
add(userList, BorderLayout.CENTER); // 添加到北面
add(jpl, "South"); // 添加到南面
jpl.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10)); // 设置布局为FlowLayout,并指定对齐方式
jpl.add(input2); // 添加标签到jpl面板
jpl.add(jtf); // 添加文本框到jpl面板
// 创建一个新的面板,并设置其布局为FlowLayout
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0));
// 将jbt1和jbt添加到这个新的面板中
buttonPanel.add(jbt1);
buttonPanel.add(jbt);
// 将这个新的面板添加到原来的面板(即jpl)中,并设置其位置为BorderLayout.CENTER
jpl.add(buttonPanel, BorderLayout.CENTER);
setVisible(true); // 设置窗口为可见状态
}
});
//实现群发
jbt1.addActionListener(this);
//实现踢人
jbt.addActionListener(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLocation(400,200);
this.setSize(540, 400);
this.setVisible(true);
this.setAlwaysOnTop(true);
ss = new ServerSocket(9999);
new Thread(this).start();//监听用户端的加入
// 添加滚动条
JScrollPane scrollPane = new JScrollPane(userList);
this.add(scrollPane, BorderLayout.CENTER); // 将滚动条添加到界面中心
}
@Override
public void run() {
while(true){
try{
s = ss.accept();
ChatThread ct = new ChatThread(s); //新用户新线程
users.add(ct); //将每个线程加入到users
//发送Jlist里的用户登陆信息,为了防止后面登陆的用户无法更新有前面用户的好友列表
ListModel<String> model = userList.getModel();//获取Jlist的数据内容
for(int i = 0; i < model.getSize(); i++){
ct.ps.println("USERS#" + model.getElementAt(i));
}
ct.start();
}catch (Exception ex){
ex.printStackTrace();
javax.swing.JOptionPane.showMessageDialog(this,"服务器异常!");
System.exit(0);
}
}
}
//群发消息按钮点击事件监听
@Override
public void actionPerformed(ActionEvent e) {
String label = e.getActionCommand();
if(label.equals("群发消息")){
handleAll();
}else if(label.equals("踢出聊天室")){
try {
handleExpel();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public void handleAll(){
if(!jtf.getText().equals("")){
sendMessage("ALL#" + jtf.getText());
//发送完后,是输入框中内容为空
jtf.setText("");
}
}//群发消息
public void handleExpel() throws IOException {
sendMessage("OFFLINE#" + userList.getSelectedValuesList().get(0));
dl.removeElement(userList.getSelectedValuesList().get(0));//更新defaultModel
userList.repaint();//更新Jlist
}//踢人
public class ChatThread extends Thread{
Socket s = null;
private BufferedReader br = null;
private PrintStream ps = null;
public boolean canRun = true;
String nickName = "";
public ChatThread(Socket s) throws Exception{
this.s = s;
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
ps = new PrintStream(s.getOutputStream());
}
public void run(){
while(canRun){
try{
String msg = br.readLine();//接收客户端发来的消息
String[] strs = msg.split("#");
if(strs[0].equals("LOGIN")){//收到来自客户端的上线消息
nickName = strs[1];
dl.addElement(nickName);
userList.repaint();
sendMessage(msg);
}else if(strs[0].equals("MSG") || strs[0].equals("SMSG") || strs[0].equals("FSMSG")){
sendMessage(msg);//发送消息
}else if(strs[0].equals("OFFLINE")){//收到来自客户端的下线消息
sendMessage(msg);
//System.out.println(msg);
dl.removeElement(strs[1]);
// 更新List列表
userList.repaint();
}
}catch (Exception ex){}
}
}
}
public void sendMessage(String msg){ //服务器端发送给所有用户
for(ChatThread ct : users){
ct.ps.println(msg);
}
}
@Override
public void valueChanged(ListSelectionEvent e) {
// TODO 自动生成的方法存根
}
public static void main(String[] args) throws Exception{
new server();
}
}
2.login.java
package javajdbc;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.LayoutManager;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JPasswordField;
import javax.swing.JButton;
import javax.swing.JDialog;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.ActionEvent;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class login {
private JFrame frame;
private JTextField textField;
private JPasswordField passwordField;
private JButton quitBt;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
login window = new login();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public login() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(400, 200, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setResizable(false);
frame.getContentPane().setLayout(null);
JLabel j1=new JLabel("**********欢迎登陆**********");
j1.setBounds(75, 30, 330,20);
j1.setFont(new Font("宋体", Font.PLAIN,20));
frame.getContentPane().add(j1);
JLabel lblNewLabel = new JLabel("用户名:");
lblNewLabel.setBounds(105, 90, 54, 15);
frame.getContentPane().add(lblNewLabel);
JLabel lblNewLabel_1 = new JLabel("密 码:");
lblNewLabel_1.setBounds(105, 140, 54, 15);
frame.getContentPane().add(lblNewLabel_1);
textField = new JTextField();
textField.setBounds(201, 85, 100, 21);
frame.getContentPane().add(textField);
textField.setColumns(10);
passwordField = new JPasswordField();
passwordField.setBounds(201, 135,100, 21);
frame.getContentPane().add(passwordField);
JButton btnNewButton = new JButton("登录");
btnNewButton.setBounds(30, 205, 93, 23);
frame.getContentPane().add(btnNewButton);
JButton btnNewButton_1 = new JButton("注册");
btnNewButton_1.setBounds(175, 205, 93, 23);
frame.getContentPane().add(btnNewButton_1);
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new add();
frame.removeNotify();
}
});
JButton j2 = new JButton("退出");
j2.setBounds(320, 205, 93, 23);
frame.getContentPane().add(j2);
//添加背景图片
JLabel background = new JLabel(new ImageIcon("src/mount.jpg"));
background.setBounds(0, 0, 450, 300);
frame.getContentPane().add(background);
textField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
passwordField.requestFocusInWindow(); // 请求焦点移动到下一个输入框
}
});
passwordField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
connectionlain c = new connectionlain();
Connection conn = c.getConnect();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn
.prepareStatement("select *from user where name=? and passwd=?");
ps.setString(1, textField.getText());
ps.setString(2, passwordField.getText());
String name=textField.getText();
rs = ps.executeQuery();
if (rs.next()) {
//new login();
client1 cli=new client1(name);
frame.removeNotify();
} else {
JOptionPane pane = new JOptionPane("用户或密码错误");
JDialog dialog = pane.createDialog("警告");
dialog.show();
}
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
connectionlain c = new connectionlain();
Connection conn = c.getConnect();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn
.prepareStatement("select *from user where name=? and passwd=?");
ps.setString(1, textField.getText());
ps.setString(2, passwordField.getText());
String name=textField.getText();
rs = ps.executeQuery();
if (rs.next()) {
//new login();
client1 cli=new client1(name);
frame.removeNotify();
} else {
JOptionPane pane = new JOptionPane("用户或密码错误");
JDialog dialog = pane.createDialog("警告");
dialog.show();
}
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
j2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
if(e.getActionCommand().equals("退出")){
System.exit(0);
}
}
});
}
private void add(JButton quitBt2) {
// TODO Auto-generated method stub
}
private Container getContentPane() {
// TODO Auto-generated method stub
return null;
}
}
3.add.java
package javajdbc;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class add {
private JFrame frame;
private JTextField textField;
private JTextField textField_1;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
add window = new add();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public add() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(400, 200, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setResizable(false);
frame.getContentPane().setLayout(null);
JLabel lblNewLabel = new JLabel("用户名:");
lblNewLabel.setBounds(135, 60, 54, 15);
frame.getContentPane().add(lblNewLabel);
JLabel lblNewLabel_1 = new JLabel("密 码:");
lblNewLabel_1.setBounds(135, 120, 54, 15);
frame.getContentPane().add(lblNewLabel_1);
textField = new JTextField();
textField.setBounds(215, 60, 100, 21);
frame.getContentPane().add(textField);
textField.setColumns(10);
textField_1 = new JTextField();
textField_1.setBounds(215,120,100, 21);
frame.getContentPane().add(textField_1);
textField_1.setColumns(10);
JButton btnNewButton = new JButton("注 册");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
connectionlain c = new connectionlain();
Connection conn = c.getConnect();
PreparedStatement ps = null;
try {
ps = conn
.prepareStatement("insert into user values(?,?)");
ps.setString(1, textField.getText());
ps.setString(2, textField_1.getText());
ps.execute();
new prompt();
frame.removeNotify();
// System.out.println("成功");
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
btnNewButton.setBounds(80, 205, 93, 23);
frame.getContentPane().add(btnNewButton);
JButton returnButton = new JButton("返 回");
returnButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new login();
frame.removeNotify();
}
});
returnButton.setBounds(270, 205, 93, 23);
frame.getContentPane().add(returnButton);
textField_1.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
connectionlain c = new connectionlain();
Connection conn = c.getConnect();
PreparedStatement ps = null;
try {
ps = conn
.prepareStatement("insert into user values(?,?)");
ps.setString(1, textField.getText());
ps.setString(2, textField_1.getText());
ps.execute();
new prompt();
frame.removeNotify();
// System.out.println("成功");
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
//移动光标
textField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
textField_1.requestFocusInWindow(); // 请求焦点移动到下一个输入框
}
});
//添加背景图片
JLabel background = new JLabel(new ImageIcon("src/mount.jpg"));
background.setBounds(0, 0, 450, 300);
frame.getContentPane().add(background);
}
}
4.prompt
package javajdbc;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class prompt {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
prompt window = new prompt();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public prompt() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(400, 200, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.getContentPane().setLayout(null);
JLabel lblNewLabel = new JLabel("注册成功!");
lblNewLabel.setFont(new Font("宋体", Font.PLAIN, 35));
lblNewLabel.setBounds(140, 51, 215, 46);
frame.getContentPane().add(lblNewLabel);
JButton btnNewButton = new JButton("返回登录");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new login();
frame.removeNotify();
}
});
btnNewButton.setBounds(170, 160, 103, 33);
frame.getContentPane().add(btnNewButton);
//添加背景图片
JLabel background = new JLabel(new ImageIcon("src/mount.jpg"));
background.setBounds(0, 0, 450, 300);
frame.getContentPane().add(background);
}
}
5.connectionlain.java
package javajdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class connectionlain {
public Connection getConnect() {
Connection conn=null;
String url="jdbc:mysql://127.0.0.1:3306/java";
String user="root";
String password="root";
try{
Class.forName("com.mysql.cj.jdbc.Driver");
conn=DriverManager.getConnection(url, user, password);
return conn;
}catch(ClassNotFoundException e){
System.out.println("错误");
e.printStackTrace();
return null;
}catch(Exception e){
e.printStackTrace();
return null;
}
}
}
6.client1.java
package javajdbc;
import javax.swing.*;
//import com.sun.org.apache.bcel.internal.generic.NEW;
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;
public class client1 extends JFrame implements Runnable,ActionListener {
private static final Graphics Graphics = null;
//north
private JMenuBar bar = new JMenuBar();
private JMenu menu = new JMenu("点击菜单");
private JMenuItem about = new JMenuItem("软件介绍");
private JMenuItem exit = new JMenuItem("退出");//退出
JPanel north = new JPanel();
//west
JPanel west = new JPanel();
DefaultListModel<String> dl = new DefaultListModel<String>();//用来修改JList
private JList<String> userList = new JList<String>(dl);//用来展示和选择
JScrollPane listPane = new JScrollPane(userList);
JLabel list = new JLabel("用户列表");
//center
JLabel show = new JLabel("公共频道");
JPanel center = new JPanel();
JTextArea jta = new JTextArea(10,20);
JScrollPane js = new JScrollPane(jta);
JPanel operPane = new JPanel();//发送消息的操作面板
JLabel input = new JLabel("请输入:");
JTextField jtf = new JTextField(40);
JButton jButton = new JButton("发消息");//私聊
private JButton jbt = new JButton("发送大厅消息");//大厅发送
private JButton jbt1 = new JButton("私发消息");
private BufferedReader br = null;
private PrintStream ps = null;
//私聊面板
JTextArea jTextArea = new JTextArea(11,45);
JScrollPane js1 = new JScrollPane(jTextArea);
JTextField jTextField = new JTextField(25);
String suser = new String();
JLabel input2 = new JLabel("请输入:");
double MAIN_FRAME_LOC_X;//父窗口x坐标
double MAIN_FRAME_LOC_Y;//父窗口y坐标
boolean FirstSecret = true;//是否第一次私聊
String sender=null;//私聊发送者的名字
String receiver=null;//私聊接收者的名字
private static String nickName = null;
public client1(String name) throws Exception{
//north 菜单栏
bar.add(menu);
menu.add(about);
menu.add(exit);
about.addActionListener(this);
exit.addActionListener(this);
BorderLayout bl = new BorderLayout();
north.setLayout(bl);
north.add(bar,BorderLayout.NORTH);
add(north,BorderLayout.NORTH);
//east 好友列表
Dimension dim = new Dimension(100,150);
west.setPreferredSize(dim);//在使用了布局管理器后用setPreferredSize来设置窗口大小
BorderLayout bl2 = new BorderLayout(1,1);
west.setLayout(bl2);
west.add(listPane,BorderLayout.CENTER);//显示好友列表
add(west,BorderLayout.EAST);
userList.setFont(new Font("隶书",Font.BOLD,18));
//userList.setBackground(new Color(224,224,239));
//center 聊天消息框 发送消息操作面板
jta.setEditable(false);//消息显示框是不能编辑的
jta.setBackground(new Color(218,218,241));
jTextArea.setEditable(false);
jta.setFont(new Font("宋体", Font.PLAIN,15));
BorderLayout bl3 = new BorderLayout(10,5);
center.setLayout(bl3);
FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
operPane.setLayout(fl);
operPane.add(input);
operPane.add(jtf);
operPane.add(jbt);//发送消息
//operPane.add(jbt1);
list.setBackground(new Color(224,224,239));
west.add(list,BorderLayout.NORTH);//用户列表
west.add(jbt1,BorderLayout.SOUTH);//私发消息
west.setBackground(Color.LIGHT_GRAY);
center.add(show,BorderLayout.NORTH);
center.add(js,BorderLayout.CENTER);//js是消息展示框JScrollPane
center.add(operPane,BorderLayout.SOUTH);
add(center,BorderLayout.CENTER);
center.setBackground(Color.LIGHT_GRAY);
js.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);//需要时才显示滚动条
//if(nickName!=null||(!nickName.equals(""))) {
//鼠标事件,点击
//jbt.addActionListener(this);
jbt1.addActionListener(this);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
//this.setAlwaysOnTop(true);
nickName=name;
String path="聊天记录/" +nickName+"聊天记录.txt";
if (!Files.exists(Paths.get(path))) {
Files.createFile(Paths.get(path));
}
this.setTitle(nickName + "的聊天室");
this.setSize(700,400);
this.setVisible(true);
Socket s = new Socket("127.0.0.1", 9999);
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
ps = new PrintStream(s.getOutputStream());
new Thread(this).start();//run()
ps.println("LOGIN#" + nickName);//发送登录信息,消息格式:LOGIN#nickName
//}else {
// System.out.println("buxing");
//}
jtf.setFocusable(true);//设置焦点
//jbt.addActionListener(null);
//键盘事件,实现当输完要发送的内容后,直接按回车键,实现发送
//监听键盘相应的控件必须是获得焦点(focus)的情况下才能起作用
jtf.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
if(jtf.getText().equals("")||jtf.getText()=="") {
JOptionPane.showMessageDialog(null, "消息不能为空!");
}else {
ps.println("MSG#" + nickName + "#" + jtf.getText());//发送消息的格式:MSG#nickName#message
//发送完后,是输入框中内容为空
jtf.setText("");
}
}
}
});
jbt.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if(jtf.getText().equals("")||jtf.getText()=="") {
JOptionPane.showMessageDialog(null, "消息不能为空!");
}else {
ps.println("MSG#" + nickName + "#" + jtf.getText());//发送消息的格式:MSG#nickName#message
//发送完后,是输入框中内容为空
jtf.setText("");
}
}
});
//私聊消息框按回车发送消息
jTextField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
if(jTextField.getText()==""||jTextField.getText().equals("")) {
JOptionPane.showMessageDialog(null, "消息不能为空!");
}else {
handleSS();
}
}
}
});
jButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if(jTextField.getText()==""||jTextField.getText().equals("")) {
JOptionPane.showMessageDialog(null, "消息不能为空!");
}else {
handleSS();
}
}
});
//监听系统关闭事件,退出时给服务器端发出指定消息
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
ps.println("OFFLINE#" + nickName);//发送下线信息,消息格式:OFFLINE#nickName
}
});
this.addComponentListener(new ComponentAdapter() {//监听父窗口大小的改变
public void componentMoved(ComponentEvent e) {
Component comp = e.getComponent();
MAIN_FRAME_LOC_X = comp.getX();
MAIN_FRAME_LOC_Y = comp.getY();
}
});
}
public void run(){//客户端与服务器端发消息的线程
while (true){
try{
String msg = br.readLine();//读取服务器是否发送了消息给该客户端
String[] strs = msg.split("#");
Date date = new Date();
SimpleDateFormat dateFormat= new
SimpleDateFormat("yyyy-MM-dd:hh:mm:ss");
String da1=dateFormat.format(date);
//判断是否为服务器发来的登陆信息
if(strs[0].equals("LOGIN")){
if(!strs[1].equals(nickName)){//不是本人的上线消息就显示,本人的不显示
jta.append(strs[1] + "上线啦!\n");
dl.addElement(strs[1]);//DefaultListModel来更改JList的内容
userList.repaint();
}
}else if(strs[0].equals("MSG")){//接到服务器发送消息的信息
if(!strs[1].equals(nickName)){//别人说的
jta.append(strs[1] + "说"+"("+da1+")"+":"+ strs[2] + "\n");
printToFile("公聊:"+strs[1] + "说" +"("+da1+")"+":" +strs[2]); // 将消息打印到文件
}else{
jta.append("我说"+"("+da1+")"+":" + strs[2] + "\n");
printToFile("公聊:我说" + "("+da1+")"+":"+strs[2]); // 将消息打印到文件
}
}else if(strs[0].equals("USERS")){//USER消息,为新建立的客户端更新好友列表
dl.addElement(strs[1]);
userList.repaint();
} else if(strs[0].equals("ALL")){
jta.append("系统消息:" + strs[1] + "\n");
printToFile("系统消息:" + strs[1]); // 将消息打印到文件
}else if(strs[0].equals("OFFLINE")){
if(strs[1].equals(nickName)) {//如果是自己下线的消息,说明被服务器端踢出聊天室,强制下线
javax.swing.JOptionPane.showMessageDialog(this, "您已被系统请出聊天室!");
System.exit(0);
}
jta.append(strs[1] + "下线啦!\n");
dl.removeElement(strs[1]);
userList.repaint();
}else if((strs[2].equals(nickName) || strs[1].equals(nickName)) && strs[0].equals("SMSG")){
if(!strs[1].equals(nickName)){
jTextArea.append(strs[1] + "说"+"("+da1+")"+":" + strs[3] + "\n");
printToFile("私聊:"+strs[1] + "说" +"("+da1+")"+":" +strs[3]); // 将消息打印到文件
jta.append("系统提示:" + strs[1] + "私信了你" + "\n");
}else{
jTextArea.append("我说"+da1+":" + strs[3] + "\n");
printToFile("私聊:我说" +da1+":" +strs[3]); // 将消息打印到文件
}
}else if((strs[2].equals(nickName) || strs[1].equals(nickName)) && strs[0].equals("FSMSG"))
{
sender = strs[1];
receiver = strs[2];
//接收方第一次收到私聊消息,自动弹出私聊窗口
if(!strs[1].equals(nickName)) {
FirstSecret = false;
jTextArea.append(strs[1] + "说"+"("+da1+")"+":" + strs[3] + "\n");
printToFile("私聊:"+strs[1] + "说" +"("+da1+")"+":" +strs[3]); // 将消息打印到文件
jta.append("系统提示:" + strs[1] + "私信了你" + "\n");
handleSec(strs[1]);
}
else {
jTextArea.append("我说"+"("+da1+")"+":" + strs[3] + "\n");
printToFile("私聊:我说" +da1+":" +strs[3]); // 将消息打印到文件
}
}
}catch (Exception ex){//如果服务器端出现问题,则客户端强制下线
javax.swing.JOptionPane.showMessageDialog(this, "您已被系统请出聊天室!");
System.exit(0);
}
}
}
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//public static String path="聊天记录/" +nickName+"聊天记录.txt";
//System.out.println(""+path);
//将聊天记录写入"聊天记录.txt"
private void printToFile(String msg) {
String path="聊天记录/" +nickName+"聊天记录.txt";
try {
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(Paths.get(path), StandardOpenOption.APPEND))) {
writer.println(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void deleteOldChatRecords(int months) {
String path="聊天记录/" +nickName+"聊天记录.txt";
try {
// 读取文件的创建日期
Date fileCreationDate = getFileCreationDate(path);
if (fileCreationDate == null) {
System.out.println("No chat records found.");
return;
}
LocalDate expirationDate = convertToLocalDate(fileCreationDate).plusMonths(months);
if (LocalDate.now().isAfter(expirationDate)) {
// 删除文件
Files.deleteIfExists(Paths.get(path));
System.out.println("Old chat records deleted successfully.");
} else {
System.out.println("No old chat records found.");
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static LocalDate convertToLocalDate(Date fileCreationDate) {
// TODO Auto-generated method stub
return null;
}
//定时删除
private static Date getFileCreationDate(String filePath) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(Paths.get(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
// 假设文件的创建日期是第一行,格式为 "Created on: yyyy-MM-dd HH:mm:ss"
if (line.startsWith("Created on: ")) {
String dateStr = line.substring("Created on: ".length());
return DATE_FORMAT.parse(dateStr);
}
}
return null; // 没有找到创建日期
} catch (Exception e) {
throw new IOException("Error reading file", e);
}
}
@Override
public void actionPerformed(ActionEvent e){//鼠标点击事件
String label = e.getActionCommand();
if(label.equals("发送消息")){//群发
handleSend();
}else if(label.equals("私发消息") && !userList.isSelectionEmpty()){//未点击用户不执行
suser = userList.getSelectedValuesList().get(0);//获得被选择的用户
handleSec(suser);//创建私聊窗口
sender = nickName;
receiver = suser;
}else if(label.equals("发消息")){
handleSS();//私发消息
}else if(label.equals("软件介绍")){
JOptionPane.showMessageDialog(this, "1.可以在聊天框中进行群聊\n\n2.可以点击选择用户进行私聊");
}else if(label.equals("退出")){
JOptionPane.showMessageDialog(this, "您已成功退出!");
ps.println("OFFLINE#" + nickName);
System.exit(0);
} else{
System.out.println("不识别的事件");
}
}
public void handleSS(){//在私聊窗口中发消息
String name=sender;
if(sender.equals(nickName)) {
name = receiver;
}
if(FirstSecret) {
ps.println("FSMSG#" + nickName + "#" + name + "#" + jTextField.getText());
jTextField.setText("");
FirstSecret = false;
}
else {
ps.println("SMSG#" + nickName + "#" + name + "#" + jTextField.getText());
jTextField.setText("");
}
}
public void handleSend(){//群发消息
//发送信息时标识一下来源
ps.println("MSG#" + nickName + "#" + jtf.getText());
//发送完后,是输入框中内容为空
jtf.setText("");
}
public void handleSec(String name){ //建立私聊窗口
JFrame jFrame = new JFrame();//新建了一个窗口
JPanel JPL = new JPanel();
JPanel JPL2 = new JPanel();
FlowLayout f2 = new FlowLayout(FlowLayout.LEFT);
JPL.setLayout(f2);
JPL.add(input2);
JPL.add(jTextField);//文本
JPL.add(jButton);
JPL2.add(js1,BorderLayout.CENTER);
JPL2.add(JPL,BorderLayout.SOUTH);
jFrame.add(JPL2);
// jButton.addActionListener(this);
jTextArea.setFont(new Font("宋体", Font.PLAIN,15));
jTextArea.setBackground(new Color(224,224,239)); // 设置文本区域的背景色
jFrame.setSize(400,300);
jFrame.setLocation((int)MAIN_FRAME_LOC_X+20,(int)MAIN_FRAME_LOC_Y+20);//将私聊窗口设置总是在父窗口的中间弹出
jFrame.setTitle("与" + name + "私聊中");
jFrame.setVisible(true);
jTextField.setFocusable(true);//设置焦点
jFrame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
jTextArea.setText("");
FirstSecret = true;
}
});
}//私聊窗口
public static void main(String[] args)throws Exception{
deleteOldChatRecords(1);
new client1(nickName);
}
}