java課程設(shè)計做一個多人聊天室(socket+多線程)
大一下學期的java期末課程設(shè)計,分享一下
課設(shè)要求
多人聊天工具 服務(wù)器要求1:能夠看到所有在線用戶(25%) 服務(wù)器要求2:能夠強制用戶下線(25%) 客戶端要求1:能夠看到所有在線用戶(25%) 客戶端要求2:能夠向某個用戶發(fā)送消息(25%)
相關(guān)知識點
1.服務(wù)端能夠看到所有在線用戶
服務(wù)端繼承了JFrame,實現(xiàn)可視化,通過socket實現(xiàn)服務(wù)端與客戶端的連接,服務(wù)端每接收一個連接,把傳進來的用戶名和對應(yīng)的socket連接封裝成一個User對象,把User對象存進一個ArrayList的用戶列表并把User對象通過取用戶名方法取得用戶名存進一個ArrayList的用戶名列表,添加一個JPanel組件,將ArrayList中的內(nèi)容通過循環(huán)顯示JPanel中并布局在窗體的右邊,在每當有人上線或者下線,刷新JPanel組件。
2.服務(wù)端能夠強制用戶下線
創(chuàng)建一個布局在窗體的下方的JPanel,在此JPanel中分別添加JLabel用于顯示提示文字,添加JTextField用于獲取服務(wù)端想要強制用戶下線的ID,添加JButton用于綁定強制用戶下線的事件監(jiān)聽,事件監(jiān)聽中將獲取的JTextField的內(nèi)容與用戶名列表進行逐一匹配,匹配上則創(chuàng)建JSON格式的鍵值對對象,通過用戶列表循環(huán)廣播告知其他用戶,并在用戶列表和用戶名列表中分別刪除該用戶信息。
3.客戶端能夠看到所有在線用戶
客戶端繼承了JFrame,實現(xiàn)可視化,添加了一個布局在窗口右邊的JPanel,把從服務(wù)端接收到的用戶名列表中的信息放進去。
4.客戶端要求能夠向某個用戶發(fā)送消息
客戶端私發(fā)消息通過在消息后面加入-和目標用戶名,傳給服務(wù)端,服務(wù)端截取目標用戶名,在用戶名列表中判斷是否存在此人,有則判斷是否是私發(fā),私發(fā)則向目標用戶發(fā)送消息,沒有則向全部用戶發(fā)送消息。
5.運用JDBC實現(xiàn)持久化存儲用戶信息
數(shù)據(jù)庫連接池運用了阿里巴巴的durid,定義一個JDBCUtils類,提供靜態(tài)代碼塊加載配置文件,初始化連接池對象,通過Spring框架的JDBCTemplate對象進行sql語句的執(zhí)行,在UserDao中提供了登錄和注冊方法,登錄方法運用queryForObject方法進行登錄查詢,如果查到返回一個User對象,查不到則返回空,注冊方法直接插入新記錄,此處建表語句中把用戶名設(shè)置成了主鍵,保證了用戶名的唯一性,注冊失敗有警告彈窗提示。這里加了一個ChatTest類用于繞過數(shù)據(jù)庫賬號校驗,可以直接進入客戶端進行連接。
6.使用JSONObject對象封裝數(shù)據(jù)
在數(shù)據(jù)的傳輸中運用了鍵值對的形式進行傳輸,客戶端傳輸給服務(wù)端的數(shù)據(jù)包中,通過判斷private鍵的值來確認是否私發(fā),通過username鍵告知服務(wù)端客戶端的用戶名,通過msg鍵傳輸具體消息,服務(wù)端傳輸給客戶端的數(shù)據(jù)包中,通過判斷user_list鍵的值來確認在線用戶及人數(shù)
7.使用Maven構(gòu)建管理項目
項目中運用到了JDBC相關(guān)內(nèi)容和JSONObject對象,導(dǎo)入了一些依賴jar包,其中倉庫和配置文件都是用的idea默認配置。
類圖

項目框架

核心代碼
1.maven配置文件pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>MyChat</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>15</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.6</version>
</dependency>
</dependencies>
</project>
2.服務(wù)器端Server.java
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.*;
import java.util.*;
import java.awt.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import net.sf.json.JSONObject;
//繼承JFrame實現(xiàn)可視化
public class Server extends JFrame{
//用戶列表,用于存放連接上的用戶信息
ArrayList<User> user_list = new ArrayList<>();
//用戶名列表,用于顯示已連接上的用戶
ArrayList<String> username_list = new ArrayList<>();
//消息顯示區(qū)域
JTextArea show_area = new JTextArea();
//用戶名顯示區(qū)域
JTextArea show_user = new JTextArea(10, 10);
//socket的數(shù)據(jù)輸出流
DataOutputStream outputStream = null;
//socket的數(shù)據(jù)輸入流
DataInputStream inputStream = null;
//從主函數(shù)里面開啟服務(wù)端
public static void main(String[] args) {
new Server();
}
//構(gòu)造函數(shù)
public Server() {
//設(shè)置流式布局
setLayout(new BorderLayout());
//VERTICAL_SCROLLBAR_AS_NEEDED設(shè)置垂直滾動條需要時出現(xiàn)
//HORIZONTAL_SCROLLBAR_NEVER設(shè)置水平滾動條不出現(xiàn)
//創(chuàng)建信息顯示區(qū)的畫布并添加到show_area
JScrollPane panel = new JScrollPane(show_area,ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
//設(shè)置信息顯示區(qū)標題
panel.setBorder(new TitledBorder("信息顯示區(qū)"));
//布局到中央
add(panel,BorderLayout.CENTER);
//設(shè)置信息顯示區(qū)為不可編輯
show_area.setEditable(false);
//創(chuàng)建用于顯示用戶的畫布
final JPanel panel_east = new JPanel();
//添加流式布局
panel_east.setLayout(new BorderLayout());
//設(shè)置標題
panel_east.setBorder(new TitledBorder("在線用戶"));
//在用戶顯示區(qū)添加show_uesr
panel_east.add(new JScrollPane(show_user), BorderLayout.CENTER);
//設(shè)置用戶顯示區(qū)域為不可編輯
show_user.setEditable(false);
//將顯示用戶的畫布添加到整體布局的右側(cè)
add(panel_east, BorderLayout.EAST);
//創(chuàng)建關(guān)于踢下線用戶的畫布
final JPanel panel_south = new JPanel();
//創(chuàng)建標簽
JLabel label = new JLabel("輸入要踢下線用戶的ID");
//創(chuàng)建輸入框
JTextField out_area = new JTextField(40);
//創(chuàng)建踢下線按鈕
JButton out_btn = new JButton("踢下線");
//依次添加進畫布
panel_south.add(label);
panel_south.add(out_area);
panel_south.add(out_btn);
//將踢下線用戶的畫布添加到整體布局的下側(cè)
add(panel_south,BorderLayout.SOUTH);
//設(shè)置踢下線按鈕的監(jiān)聽
out_btn.addActionListener(e -> {
try {
//用于存儲踢下線用戶的名字
String out_username;
//從輸入框中獲取踢下線用戶名
out_username = out_area.getText().trim();
//用于判斷蓋用戶是否被踢下線
boolean is_out=false;
//遍歷用戶列表依次判斷
for (int i = 0; i < user_list.size(); i++){
//比較用戶名,相同則踢下線
if(user_list.get(i).getUsername().equals(out_username)){
//獲取被踢下線用戶對象
User out_user = user_list.get(i);
//使用json封裝將要傳遞的數(shù)據(jù)
JSONObject data = new JSONObject();
//封裝全體用戶名,廣播至所有用戶
data.put("user_list", username_list);
//廣播的信息內(nèi)容
data.put("msg", out_user.getUsername() + "被管理員踢出\n");
//服務(wù)端消息顯示區(qū)顯示相應(yīng)信息
show_area.append(out_user.getUsername() + "被你踢出\n");
//依次遍歷用戶列表
for (User value : user_list) {
try {
//獲取每個用戶列表的socket連接
outputStream = new DataOutputStream(value.getSocket().getOutputStream());
//傳遞信息
outputStream.writeUTF(data.toString());
} catch (IOException ex) {
ex.printStackTrace();
}
}
//將被踢用戶移出用戶列表
user_list.remove(i);
//將被踢用戶移出用戶名列表
username_list.remove(out_user.getUsername());
//刷新在線人數(shù)
show_user.setText("人數(shù)有 " + username_list.size() + " 人\n");
//刷新在線用戶
for (String s : username_list) {
show_user.append(s + "\n");
}
//判斷踢出成功
is_out=true;
break;
}
}
//根據(jù)是否踢出成功彈出相應(yīng)提示
if(is_out){
JOptionPane.showMessageDialog(null,"踢下線成功","提示",
JOptionPane.WARNING_MESSAGE);
}
if(!is_out){
JOptionPane.showMessageDialog(null,"不存在用戶","提示",
JOptionPane.WARNING_MESSAGE);
}
//重置輸入框
out_area.setText("");
} catch(Exception ex) {
ex.printStackTrace();
}
});
//設(shè)置該窗口名
setTitle("服務(wù)器 ");
//引入圖片
BufferedImage img;
try {
//根據(jù)圖片名引入圖片
img = ImageIO.read(Server.class.getResource("/a.jpg"));
//設(shè)置其為該窗體logo
setIconImage(img);
} catch (IOException exception) {
exception.printStackTrace();
}
//設(shè)置窗體大小
setSize(700, 700);
//設(shè)置窗體位置可移動
setLocationRelativeTo(null);
//設(shè)置窗體關(guān)閉方式
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//設(shè)置窗體可見
setVisible(true);
//socket連接相關(guān)代碼
try {
//開啟socket服務(wù)器,綁定端口11111
ServerSocket serverSocket = new ServerSocket(11111);
//信息顯示區(qū)打印服務(wù)器啟動時間
show_area.append("服務(wù)器啟動時間 " + new Date() + "\n");
//持續(xù)接收連接
while (true) {
//接收連接
Socket socket = serverSocket.accept();
//創(chuàng)建用戶對象
User user = new User();
//判斷是否連接上
if (socket != null) {
//獲取輸入流
inputStream = new DataInputStream(socket.getInputStream());
//讀取輸入流
String json = inputStream.readUTF();
//創(chuàng)建信息對象
JSONObject data = JSONObject.fromObject(json);
//信息顯示區(qū)打印用戶上線
show_area.append("用戶 " + data.getString("username") + " 在" + new Date() + "登陸系統(tǒng)"+"\n");
//創(chuàng)建新用戶
user = new User();
//存儲socket對象
user.setSocket(socket);
//獲取輸入流用戶名
user.setUsername(data.getString("username"));
//添加進用戶列表
user_list.add(user);
//添加進用戶名列表
username_list.add(data.getString("username"));
//刷新在線人數(shù)
show_user.setText("人數(shù)有 " + username_list.size() + " 人\n");
//刷新在線用戶
for (String s : username_list) {
show_user.append(s + "\n");
}
}
//封裝信息對象
JSONObject online = new JSONObject();
//設(shè)置接收信息對象
online.put("user_list", username_list);
//設(shè)置信息內(nèi)容
online.put("msg", user.getUsername() + "上線了");
//依次遍歷,將信息廣播給所有在線用戶
for (User value : user_list) {
//獲取輸出流
outputStream = new DataOutputStream(value.getSocket().getOutputStream());
//給所有用戶輸出上線信息
outputStream.writeUTF(online.toString());
}
//開啟新線程,持續(xù)接收該socket信息
new Thread(new ServerThread(socket)).start();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
//線程代碼
class ServerThread implements Runnable {
//存放全局變量socket
private final Socket socket;
//構(gòu)造函數(shù),初始化socket
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//獲取輸入流
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
//持續(xù)接收信息
while (true) {
//獲取傳遞進來的信息
String json = inputStream.readUTF();
//封裝成json格式
JSONObject data = JSONObject.fromObject(json);
//通過json里面的private判斷是否私發(fā)
boolean is_private = false;
//私發(fā)處理
for (int i = 0; i < user_list.size(); i++) {
//找到私發(fā)對象
if (user_list.get(i).getUsername().equals(data.getString("private"))) {
//構(gòu)建私發(fā)信息內(nèi)容
String msg = data.getString("time") +"\n" + data.getString("username")
+ " 給你發(fā)了一條私密消息,其它用戶看不到" + "\n" + data.getString("msg");
//用該方法指定對象發(fā)送信息
send_msg(i, msg);
//將發(fā)送成功反饋給原用戶
for (int j = 0; j < user_list.size(); j++) {
//找到發(fā)信息用戶
if(user_list.get(j).getUsername().equals(data.getString("username"))){
//構(gòu)建反饋信息內(nèi)容
String msg2 = data.getString("time")+"\n你成功向"+user_list.get(i).getUsername()
+"發(fā)送了一條私密消息\n" +data.getString("msg");
//用該方法指定對象發(fā)送信息
send_msg(j,msg2);
}
}
//將該操作打印到服務(wù)器監(jiān)視窗
show_area.append(data.getString("username") +data.getString("time")+ "私發(fā)給"
+ data.getString("private") + ":\n" + data.getString("msg") + "\n");
//判斷是私發(fā)
is_private = true;
break;
}
}
//非私發(fā)的情況
if (!is_private) {
//構(gòu)建信息內(nèi)容
String msg = data.getString("username") + " " + data.getString("time") + ":\n"
+ data.getString("msg");
//添加到服務(wù)器顯示
show_area.append(msg + "\n");
//依次發(fā)給所有在線用戶
for (int i = 0; i < user_list.size(); ) {
send_msg(i, msg);
i++;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
//發(fā)送信息給指定用戶的方法
public void send_msg(int i, String msg) {
//構(gòu)建對象
JSONObject data = new JSONObject();
//封裝信息
data.put("user_list", username_list);
data.put("msg", msg);
//獲取目標對象
User user = user_list.get(i);
try {
//獲取輸出流
outputStream = new DataOutputStream(user.getSocket().getOutputStream());
//寫信息
outputStream.writeUTF(data.toString());
} catch (IOException e) {
//如果沒有找到,則說明該用戶已經(jīng)下線
User out_user = user_list.get(i);
//重復(fù)刪除操作
user_list.remove(i);
username_list.remove(out_user.getUsername());
//重新構(gòu)建信息
JSONObject out = new JSONObject();
out.put("user_list", username_list);
out.put("msg", out_user.getUsername() + "下線了\n");
//將其下線通知廣播給所有用戶
for (User value : user_list) {
try {
outputStream = new DataOutputStream(value.getSocket().getOutputStream());
outputStream.writeUTF(out.toString());
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
}
代碼太多了,懶得注釋了,大家應(yīng)該看得懂
3.客戶端登錄界面Client.java
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class Client extends JFrame{
public static void main(String[] args) {
new Client();
}
public Client(){
setTitle("登陸界面");
BufferedImage img;
try {
img = ImageIO.read(Server.class.getResource("/a.jpg"));
setIconImage(img);
} catch (IOException exception) {
exception.printStackTrace();
}
setLayout(null);
setSize(500,500);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
setResizable(false);
JLabel username_label = new JLabel("用戶名");
username_label.setBounds(60,100,100,50);
add(username_label);
JLabel password_label = new JLabel("密碼");
password_label.setBounds(60,200,100,50);
add(password_label);
JTextField username_field = new JTextField();
username_field.setBounds(110,100,300,50);
add(username_field);
JPasswordField password_field = new JPasswordField();
password_field.setBounds(110,200,300,50);
add(password_field);
JButton login = new JButton("登陸");
login.setBounds(130,300,100,50);
add(login);
JButton register = new JButton("注冊");
register.setBounds(280,300,100,50);
add(register);
setVisible(true);
login.addActionListener(e -> {
String username = username_field.getText();
String password = String.valueOf(password_field.getPassword());
if(username.length()!=0 && password.length()!=0){
User user = new User();
user.setUsername(username);
user.setPassword(password);
UserDao dao = new UserDao();
User u = dao.login(user);
if(u!=null){
setVisible(false);
new Chat(username);
}else{
JOptionPane.showMessageDialog(null,"登錄失敗,賬號或密碼錯誤","提示",
JOptionPane.WARNING_MESSAGE);
}
}else {
JOptionPane.showMessageDialog(null,"登錄失敗,賬號或密碼不能為空","提示",
JOptionPane.WARNING_MESSAGE);
}
});
register.addActionListener(e -> {
setVisible(false);
new Register();
});
}
}
4.客戶端注冊界面Register.java
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class Register extends JFrame {
public Register(){
setTitle("注冊界面");
BufferedImage img;
try {
img = ImageIO.read(Server.class.getResource("/a.jpg"));
this.setIconImage(img);
} catch (IOException exception) {
exception.printStackTrace();
}
setLayout(null);
setSize(500,500);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
setResizable(false);
JLabel username_label = new JLabel("用戶名");
username_label.setBounds(60,50,100,50);
add(username_label);
JLabel password_label = new JLabel("密碼");
password_label.setBounds(60,150,100,50);
add(password_label);
JLabel password_label2 = new JLabel("請再次輸入密碼");
password_label2.setBounds(20,250,100,50);
add(password_label2);
JTextField username_field = new JTextField();
username_field.setBounds(110,50,300,50);
add(username_field);
JPasswordField password_field = new JPasswordField();
password_field.setBounds(110,150,300,50);
add(password_field);
JPasswordField password_field2 = new JPasswordField();
password_field2.setBounds(110,250,300,50);
add(password_field2);
JButton register_success = new JButton("注冊");
register_success.setBounds(130,350,100,50);
add(register_success);
JButton back = new JButton("返回");
back.setBounds(280,350,100,50);
add(back);
setVisible(true);
register_success.addActionListener(e -> {
String username = username_field.getText();
String password = String.valueOf(password_field.getPassword());
String password2 = String.valueOf(password_field2.getPassword());
System.out.println(password);
System.out.println(password2);
if(username.length()==0 || password.length()==0){
JOptionPane.showMessageDialog(null,"注冊失敗,賬號或密碼不能為空","提示",
JOptionPane.WARNING_MESSAGE);
}else if (!password.equals(password2)) {
JOptionPane.showMessageDialog(null,"注冊失敗,前后密碼不匹配","提示",
JOptionPane.WARNING_MESSAGE);
}else{
System.out.println();
System.out.println(password);
User user = new User();
user.setUsername(username);
user.setPassword(password);
UserDao dao = new UserDao();
int flag = dao.register(user);
if(flag!=0){
JOptionPane.showMessageDialog(null,"注冊成功,歡迎您登錄","提示",
JOptionPane.WARNING_MESSAGE);
}else{
//建表語句中設(shè)置了user為主鍵,重復(fù)則建表失敗
JOptionPane.showMessageDialog(null,"注冊失敗,賬號已經(jīng)存在","提示",
JOptionPane.WARNING_MESSAGE);
}
}
});
back.addActionListener(e ->{
setVisible(false);
new Client();
});
}
}
5.客戶端聊天界面Chat.java
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.awt.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
public class Chat extends JFrame{
JTextArea show_area = new JTextArea();
JTextArea show_user = new JTextArea(10, 10);
DataOutputStream outputStream;
DataInputStream inputStream;
String username;
ArrayList<String> username_list = new ArrayList<>();
boolean is_stop = false;
public Chat(final String username) {
this.username = username;
final JPanel panel_south = new JPanel();
panel_south.setLayout(new BorderLayout());
panel_south.setBorder(new TitledBorder("寫消息區(qū),若私聊,在內(nèi)容后添加(-用戶名)"));
JTextField send_area = new JTextField(40);
panel_south.add(send_area, BorderLayout.CENTER);
JButton send_btn = new JButton("發(fā)送");
panel_south.add(send_btn,BorderLayout.EAST);
add(panel_south, BorderLayout.SOUTH);
send_btn.addActionListener(e -> {
try {
if (is_stop) {
show_area.append("你已被踢出,不能發(fā)送消息\n");
JOptionPane.showMessageDialog(null,"你已被踢出,不能發(fā)送消息,進程已經(jīng)關(guān)閉","提示",
JOptionPane.WARNING_MESSAGE);
System.exit(0);
} else {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(new Date());
String msg = send_area.getText().trim();
if (!msg.equals("")) {
String[] msg1 = msg.split("-");
JSONObject data = new JSONObject();
data.put("username", username);
data.put("msg", msg1[0]);
data.put("time", time);
try {
data.put("private", msg1[1]);
} catch (ArrayIndexOutOfBoundsException e1) {
data.put("private", "");
}
outputStream.writeUTF(data.toString());
}
}
send_area.setText("");
} catch (Exception ex) {
ex.printStackTrace();
}
});
JScrollPane panel = new JScrollPane(show_area,ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
panel.setBorder(new TitledBorder("信息顯示區(qū)"));
add(panel,BorderLayout.CENTER);
show_area.setEditable(false);
final JPanel panel_east = new JPanel();
panel_east.setLayout(new BorderLayout());
panel_east.setBorder(new TitledBorder("在線用戶"));
panel_east.add(new JScrollPane(show_user), BorderLayout.CENTER);
show_user.setEditable(false);
add(panel_east, BorderLayout.EAST);
setTitle("用戶 " + username);
BufferedImage img;
try {
img = ImageIO.read(Server.class.getResource("/a.jpg"));
this.setIconImage(img);
} catch (IOException exception) {
exception.printStackTrace();
}
setSize(500, 500);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
JSONObject data = new JSONObject();
data.put("username", username);
data.put("msg", null);
try {
Socket socket = new Socket("127.0.0.1", 11111);
inputStream = new DataInputStream(socket.getInputStream());
outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF(data.toString());
new Thread(new Read()).start();
} catch (IOException e) {
show_area.append("服務(wù)器無響應(yīng)");
JOptionPane.showMessageDialog(null,"服務(wù)器無響應(yīng)","提示",
JOptionPane.WARNING_MESSAGE);
}
}
public class Read implements Runnable {
@Override
public void run() {
try {
while (true) {
String json = inputStream.readUTF();
JSONObject data = JSONObject.fromObject(json);
String msg = data.getString("msg");
if (msg.contains("踢出") && msg.contains(username)) {
is_stop = true;
show_area.append(username + ",你已經(jīng)被踢出群聊\n");
JOptionPane.showMessageDialog(null,"你已經(jīng)被踢出群聊","提示",
JOptionPane.WARNING_MESSAGE);
System.exit(0);
} else {
show_area.append(msg + "\n");
show_area.selectAll();
username_list.clear();
JSONArray jsonArray = data.getJSONArray("user_list");
for (Object o : jsonArray) {
username_list.add(o.toString());
}
show_user.setText("人數(shù)有 " + jsonArray.size() + " 人\n");
for (String s : username_list) {
show_user.append(s + "\n");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
6.用戶實體User.java
import java.net.Socket;
public class User {
private String username;
private String password;
private Socket socket;
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;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
}
7.JDBC工具類
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.util.Properties;
public class JDBCUtils {
private static DataSource ds;
static {
try {
Properties pro = new Properties();
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (Exception exception) {
exception.printStackTrace();
}
}
public static DataSource getDataSource(){
return ds;
}
}
8.UserDao.java連接數(shù)據(jù)庫
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
public class UserDao {
private final JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
public User login(User login_user) {
try {
//編寫sql
String sql = "select * from user where username = ? and password = ?";
User user = template.queryForObject(sql,
new BeanPropertyRowMapper<User>(User.class),
login_user.getUsername(), login_user.getPassword());
return user;
} catch (DataAccessException e) {
e.printStackTrace();
return null;
}
}
public int register(User register_user) {
try {
String sql = "insert into user values (null ,?,?)";
int count = template.update(sql,register_user.getUsername(),register_user.getPassword());
return count;
} catch (DataAccessException e) {
e.printStackTrace();
return 0;
}
}
}
運行結(jié)果




到此這篇關(guān)于java課程設(shè)計做一個多人聊天室(socket+多線程)的文章就介紹到這了,更多相關(guān)java多人聊天室內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java發(fā)送kafka事務(wù)消息的實現(xiàn)方法
本文主要介紹了java發(fā)送kafka事務(wù)消息的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07
Java多種方式實現(xiàn)生產(chǎn)者消費者模式
這篇文章主要介紹了Java多種方式實現(xiàn)生產(chǎn)者消費者模式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-07-07
Java中資源加載的方法及Spring的ResourceLoader應(yīng)用小結(jié)
在Java開發(fā)中,資源加載是一個基礎(chǔ)而重要的操作,這篇文章主要介紹了深入理解Java中資源加載的方法及Spring的ResourceLoader應(yīng)用,本文通過實例代碼演示了通過ClassLoader和Class獲取資源的內(nèi)容,以及使用Spring的ResourceLoader加載多個資源的過程,需要的朋友可以參考下2024-01-01
Mybatis-plus selectByMap條件查詢方式
這篇文章主要介紹了Mybatis-plus selectByMap條件查詢方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
Java內(nèi)存劃分:運行時數(shù)據(jù)區(qū)域
聽說Java運行時環(huán)境的內(nèi)存劃分是挺進BAT的必經(jīng)之路,這篇文章主要給大家介紹了關(guān)于Java運行時數(shù)據(jù)區(qū)域(內(nèi)存劃分)的相關(guān)資料,需要的朋友可以參考下2021-07-07

