ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Java银行排号系统源码解析:Socket通信与数据库实战

2026/9/23 4:35:10 拓冰建站 浏览量
Java银行排号系统源码解析:Socket通信与数据库实战 简介本资源为基于Java的银行排号系统完整毕业设计资料包面向计算机相关专业学生及需要Java桌面/网络编程实战案例的开发者帮助解决排队叫号场景下的取号、叫号、统计与查询等业务建模问题。系统按服务器端与客户端划分服务器端实现取号、统计、删除、查询与通知功能客户端支持多工作台并发办理涵盖业务员登录、叫号、统计、删除与查询等模块数据库层负责号票与处理状态的持久化。压缩包为rar格式整体约69.98MB内含源码、演示视频、数据库脚本与论文文档可支撑从环境搭建到答辩演示的完整流程。目前已有468人学习下载适合作为课程设计或毕业设计的参考方案便于读者理解C/S架构下的通信机制、数据库访问层设计及多工作台协同逻辑快速复用并二次开发。1. 从一份 Java 银行排号系统源码说起它到底能跑通什么很多人做课程设计或毕业设计时最头疼的不是写不出代码而是找不到一个结构完整、能跑起来、还能对着写论文的参考项目。这份基于 Java 的银行排号系统恰好卡在这个需求点上。它不是一个只贴了几段核心逻辑的片段而是一套包含源码、视频、数据库脚本和论文的完整交付物。服务器端负责取号、统计、删除、查询和通知客户端负责业务员登录、叫号、统计、删除和查询两端通过数据库和通信机制联动。换句话说它模拟的是银行网点里“顾客取号—等待—被叫—到窗口办理”的完整闭环。适合谁正在做 Java 课程设计、毕业设计或者想找一个多线程、Socket 通信、数据库增删改查综合案例练手的人。你拿到手后最该先确认的不是界面好不好看而是服务器和客户端能不能在同一台机器上先跑通一次取号和叫号。2. 服务器端与客户端如何分工先理清通信模型再动手2.1 为什么这个系统把“取号”放在服务器端项目正文里有一句很关键的话“由于把服务器设置到了用户的一端所以在服务器端进行取号然后把号存到数据库中。”这句话初看有点绕实际意思是服务器端程序同时承担了“取号终端”的角色。顾客在服务器端点击取号服务器生成一个号码写入数据库然后等待客户端业务员来叫号。这种设计在课程设计里很常见因为它避免了单独再写一个取号机程序降低了部署复杂度。从技术选型上看服务器端需要做几件事接收取号请求、生成递增号码、把号码和状态写入数据库、响应客户端的叫号请求、更新号码状态为“已处理”。客户端则需要业务员登录验证、向服务器请求下一个待处理号码、显示当前办理号码、统计已取号和未处理数量、支持删除记录和查询记录。常见做法是服务器端用ServerSocket监听某个端口客户端用Socket连接上来双方约定一套简单的文本协议比如TAKE表示取号CALL表示叫号LOGIN|用户名|密码表示登录。也有用 RMI 或者直接共享数据库连接的但 Socket 方式最能体现“通信”这个考点也最容易被答辩老师追问。2.2 数据库表结构怎么设计才够用这个系统的数据库不需要太复杂但几张核心表必须清晰。我一般会建议至少设计三张表号码表、业务员表、操作日志表。号码表存号票信息业务员表存登录凭证操作日志表可选但能加分。表名关键字段用途ticketid, number, status, create_time, handle_time存储号票status 0 未处理 1 已处理clerkid, username, password, workbench业务员登录信息和工作台编号logid, ticket_id, clerk_id, action, action_time记录取号、叫号、删除等操作号码生成策略上常见做法是用MAX(number)1但并发取号时可能重复。更稳妥的是用数据库自增主键或者用一张单独的技术表配合UPDATE ... SET value value 1再查询。课程设计里如果并发量不大直接查最大值加一也能过但答辩时被问到“两个人同时取号会不会拿到同一个号”就很容易翻车。2.3 服务器端取号与通知的实现步骤下面这段代码演示服务器端接收取号请求、生成号码并写库的核心逻辑。假设用 JDBC 操作 MySQL端口监听用 ServerSocket。// 服务器端主循环监听客户端连接 ServerSocket serverSocket new ServerSocket(8888); System.out.println(服务器已启动等待连接...); while (true) { Socket socket serverSocket.accept(); // 每个客户端一个线程处理 new Thread(new ClientHandler(socket)).start(); } // ClientHandler 中处理取号请求 public void run() { try (BufferedReader in new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out new PrintWriter(socket.getOutputStream(), true)) { String request; while ((request in.readLine()) ! null) { if (request.startsWith(TAKE)) { // 生成新号码 int newNumber ticketDao.getMaxNumber() 1; ticketDao.insertTicket(newNumber, 0); out.println(TAKEN| newNumber); } else if (request.startsWith(CALL)) { // 叫号取最早未处理的号 Ticket ticket ticketDao.getFirstWaiting(); if (ticket ! null) { ticketDao.updateStatus(ticket.getId(), 1); out.println(CALLED| ticket.getNumber()); } else { out.println(EMPTY); } } } } catch (IOException e) { e.printStackTrace(); } }逻辑说明服务器用ServerSocket在 8888 端口监听每个连接开一个线程避免一个客户端卡住影响其他客户端。TAKE请求到来时先查当前最大号码加一后插入数据库状态设为 0 表示未处理。CALL请求到来时取最早的一条未处理记录把状态改成 1返回号码给客户端。参数说明端口号 8888 可以改但要保证客户端一致。getMaxNumber()内部执行SELECT MAX(number) FROM ticket如果表为空返回 0。getFirstWaiting()执行SELECT * FROM ticket WHERE status 0 ORDER BY number ASC LIMIT 1。这里没有加锁高并发下会出问题但课程设计场景够用。如果想稳一点可以在getFirstWaiting和updateStatus外面加synchronized块。2.4 客户端登录与叫号的联动流程客户端启动后业务员先登录。登录信息在数据库clerk表里预先录入。登录成功后客户端保持与服务器的 Socket 连接点击“叫号”按钮时发送CALL请求收到号码后显示在界面上同时把该号码标记为正在办理。// 客户端登录 String loginCmd LOGIN| usernameField.getText() | passwordField.getText(); out.println(loginCmd); String response in.readLine(); if (LOGIN_OK.equals(response)) { // 登录成功启用叫号按钮 callButton.setEnabled(true); } else { JOptionPane.showMessageDialog(this, 用户名或密码错误); } // 叫号按钮事件 callButton.addActionListener(e - { out.println(CALL); try { String callResponse in.readLine(); if (callResponse.startsWith(CALLED)) { String number callResponse.split(\\|)[1]; currentNumberLabel.setText(正在办理 number 号); } else { currentNumberLabel.setText(暂无等待客户); } } catch (IOException ex) { ex.printStackTrace(); } });逻辑说明登录时客户端把用户名和密码拼成LOGIN|user|pass发给服务器服务器查clerk表验证返回LOGIN_OK或LOGIN_FAIL。叫号时发送CALL服务器返回CALLED|号码或EMPTY。客户端根据返回结果更新界面。参数说明usernameField和passwordField是 Swing 文本框。currentNumberLabel是显示当前号码的标签。注意in.readLine()是阻塞的如果服务器没返回界面会卡住。常见做法是把网络请求放到单独线程里或者用SwingWorker但课程设计里直接调用也能演示。3. 把源码跑起来环境配置与数据库初始化3.1 Java 环境与 IDE 选择这份资源是 Java 项目所以第一步是确认本机有 JDK。常见做法是装 JDK 8 或 JDK 11因为很多课程设计项目用这两个版本兼容性最好。装完后配置JAVA_HOME和PATH命令行输入java -version能看到版本号就算成功。IDE 用 Eclipse、IntelliJ IDEA 或者 MyEclipse 都行看学校要求。如果资源里带了视频视频里通常会用某个特定 IDE 演示跟着走能减少环境差异带来的问题。数据库方面项目正文提到“数据库”但没有指定具体是 MySQL 还是 SQL Server。从关键词和常见课程设计习惯看MySQL 概率更大。我一般会先看资源包里的.sql文件如果有CREATE TABLE语句直接导入就行。如果只有.mdf或.bak那就是 SQL Server。确认数据库类型后再改项目里的 JDBC 连接配置。3.2 导入数据库脚本并修改连接参数假设资源包里有一个bank_queue.sql文件里面包含建库建表语句和初始业务员数据。操作步骤如下# 登录 MySQL mysql -u root -p # 创建数据库 CREATE DATABASE bank_queue DEFAULT CHARACTER SET utf8mb4; # 导入脚本 USE bank_queue; SOURCE /path/to/bank_queue.sql; # 查看表是否创建成功 SHOW TABLES; SELECT * FROM clerk;逻辑说明先建一个空数据库再用SOURCE命令执行脚本文件。SHOW TABLES确认表存在SELECT * FROM clerk确认业务员账号已经录入。如果脚本里没有CREATE DATABASE语句就需要手动建库。参数说明utf8mb4是为了支持中文避免业务员姓名乱码。/path/to/bank_queue.sql要替换成实际路径。如果导入时报错“Unknown database”说明数据库没建成功如果报错“Table already exists”可以先DROP DATABASE bank_queue再重新来。然后找到项目里的数据库配置文件通常是db.properties或DBUtil.java修改 URL、用户名和密码。# db.properties 示例 jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/bank_queue?useSSLfalseserverTimezoneUTCcharacterEncodingutf8 jdbc.usernameroot jdbc.password你的密码逻辑说明jdbc.url里的localhost:3306是 MySQL 默认地址和端口bank_queue是数据库名。useSSLfalse关掉 SSL 警告serverTimezoneUTC解决时区报错characterEncodingutf8保证中文不乱码。参数说明如果 MySQL 是 8.0 以上驱动类用com.mysql.cj.jdbc.Driver如果是 5.x用com.mysql.jdbc.Driver。密码填自己本机的 MySQL 密码。改完后服务器端和客户端都要用同一份配置否则连不上同一个库。3.3 先启动服务器端再启动客户端运行顺序很重要。先跑服务器端主类看到“服务器已启动等待连接...”再跑客户端。如果先跑客户端会报连接拒绝。服务器端启动后在服务器界面点击取号数据库里应该多一条status0的记录。然后启动客户端用clerk表里的账号登录点击叫号服务器端界面上的等待人数应该减少客户端显示正在办理的号码。常见做法是服务器端和客户端分别打两个 jar 包或者直接在 IDE 里开两个运行实例。如果资源里带了视频视频通常会演示这个顺序。注意如果服务器端和客户端在同一台机器上跑端口不要冲突如果分两台机器客户端连接配置里的 IP 要改成服务器所在机器的局域网 IP。4. 避坑与排查那些答辩前容易翻车的地方4.1 现象客户端登录一直提示密码错误但数据库里明明有账号原因最常见的是密码字段在数据库里存了明文但代码里做了 MD5 加密后比对或者数据库连接到了另一个库clerk表是空的。还有一种可能是字符集问题中文用户名或密码在传输时乱码。解决先直接在数据库里SELECT * FROM clerk确认账号存在且密码字段值和代码里输入的一致。如果代码用了 MD5就把输入的密码用同样的 MD5 工具算一遍再存进去。如果是字符集问题检查 JDBC URL 有没有加characterEncodingutf8以及数据库和表的字符集是不是utf8mb4。4.2 现象取号时号码重复两个顾客拿到同一个号原因getMaxNumber()1不是原子操作。两个线程同时查到最大号是 5都加一得到 6然后都插入 6。课程设计演示时如果只有一个人操作通常不会触发但答辩老师如果让你同时点两次就可能翻车。解决简单做法是在取号方法上加synchronized关键字让同一时刻只有一个线程能取号。更稳妥的是用数据库自增主键插入时不用指定number让数据库自己生成然后SELECT LAST_INSERT_ID()拿到刚生成的号。或者用UPDATE sequence SET value value 1再查询利用数据库行锁保证原子性。4.3 现象叫号后客户端显示号码但服务器端统计的等待人数没变原因服务器端统计界面可能只在启动时查了一次数据库之后没有刷新。或者叫号时更新了status但统计查询的条件写错了比如把status0写成了status1。解决在服务器端加一个定时刷新比如用Timer每隔 2 秒查一次数据库更新界面。或者每次取号、叫号、删除操作后手动调用一次刷新方法。检查统计 SQL等待人数应该是SELECT COUNT(*) FROM ticket WHERE status 0已处理人数是status 1。4.4 现象删除功能把数据库所有记录都删了恢复不了原因项目正文里提到“业务员可以删除数据库中所有的记录”这个功能如果没加二次确认很容易误操作。更麻烦的是如果删除时没有备份答辩演示数据就没了。解决演示前先导出一次数据库备份用mysqldump -u root -p bank_queue backup.sql。代码里给“删除全部”按钮加一个JOptionPane.showConfirmDialog确认框。如果已经误删用备份文件恢复mysql -u root -p bank_queue backup.sql。我一般还会在删除方法里加一条日志记录谁在什么时候删了什么方便追溯。4.5 现象换一台电脑跑项目报 ClassNotFoundException 或 NoClassDefFoundError原因项目依赖的 MySQL 驱动 jar 包没有一起拷贝或者 IDE 的构建路径里引用了本机绝对路径的 jar换机器后路径失效。解决把mysql-connector-java-x.x.x.jar放到项目lib目录下然后在 IDE 里用相对路径添加依赖。如果打 jar 包确保驱动被打进去或者运行时用-cp指定驱动路径。常见做法是建一个lib文件夹把所有第三方 jar 放进去IDE 里统一添加为库。5. 从能跑到能讲论文与视频的配合用法5.1 论文框架怎么和源码对应资源里带了论文这比只有源码要省事得多。但论文不能直接照抄答辩时老师一问就露馅。我一般会先把论文的章节结构和源码模块对应起来论文里的“系统需求分析”对应服务器端和客户端的功能列表“系统设计”对应数据库表结构和通信协议“系统实现”对应关键代码“系统测试”对应你实际跑通的截图。具体操作上先跑通取号、叫号、查询、删除四个核心功能每个功能截一张图替换论文里的示例图。然后把论文里的数据库表字段和实际.sql文件核对一遍确保一致。如果论文里写了“使用 Socket 通信”但源码里其实是直接连数据库就要么改论文要么改代码别让两者矛盾。5.2 视频怎么用才不浪费时间视频的价值在于演示环境配置和运行顺序而不是让你从头看到尾。我一般会跳着看先看前 10 分钟确认 JDK 版本、数据库版本、IDE 版本然后看数据库导入那一段确认脚本执行方式最后看服务器端和客户端启动顺序。中间大段敲代码的过程可以倍速或者跳过遇到报错再回去查对应片段。如果视频里用的数据库版本和你本机不一致比如视频用 MySQL 5.7 而你装了 8.0驱动类和 URL 参数可能要改。视频里如果用了特定 IDE 的快捷键不用纠结用你熟悉的就行。关键是抓住“配置—导入—启动—验证”这条主线。5.3 一个验证系统是否真正跑通的检查清单跑通不是看到界面出来就算而是要确认数据流转正确。我一般会按这个顺序检查检查项预期结果验证方式服务器启动控制台输出监听端口看控制台取号数据库 ticket 表新增一条 status0查数据库客户端登录返回 LOGIN_OK看客户端提示叫号最早未处理记录 status 变 1查数据库统计等待人数和已处理人数正确对比数据库 count删除单条指定记录消失查数据库删除全部ticket 表清空查数据库如果每一步都符合预期说明系统核心逻辑没问题。答辩时老师如果让你现场演示按这个顺序走一遍比口头解释更有说服力。5.4 二次开发可以加什么如果想让项目更有亮点可以在现有基础上加两个小功能。一个是“优先级取号”在 ticket 表加一个priority字段叫号时优先取priority1的记录。另一个是“窗口状态显示”客户端登录后把业务员的工作台编号和当前办理号码写回数据库服务器端可以展示每个窗口在办几号。这两个改动都不大但能让答辩老师看到你不是只跑了原版而是真的理解了数据流。代码上优先级叫号只需要把getFirstWaiting的 SQL 改成ORDER BY priority DESC, number ASC。窗口状态显示需要在clerk表加current_ticket字段叫号时更新办理完成时清空。改完后记得同步更新论文里的表结构说明。从那以后我每次拿到这类课程设计资源都强制自己先跑通核心链路再动论文因为一旦代码跑不起来论文写得再漂亮也过不了演示那一关。希望帮到你。本文还有配套的精品资源点击获取