资讯动态

基于JSP的银行排队叫号系统:SSM框架实现与部署避坑指南

发布时间:2026/10/29 15:33:27 来源:尧图企业网站定制
简介这是一套面向Java Web初学者与课程设计需求的银行排队叫号系统完整项目采用SSM框架搭配JSP技术实现运行于JDK1.8与Tomcat7环境数据库使用MySQL5.7。项目涵盖取号、叫号、窗口管理与业务统计等典型银行场景模块适合作为毕业设计、课程实训或SSM框架练手参考。压缩包共856个文件约29.65MB包含87个Java源文件、49个JSP页面、217个JavaScript脚本、97个CSS样式及大量png、gif、jpg图片素材另有sql建表脚本、xml配置与properties文件前端还集成了Bootstrap与UEditor等组件结构完整、层次清晰。资源同时附带演示视频方便直观了解系统运行效果与交互流程。目前已有465人学习下载读者可据此快速搭建环境、梳理SSM整合思路、参考页面布局与业务逻辑实现并借助源码排查常见配置问题。1. 从一次银行网点改造说起这套 JSP 叫号系统到底能跑通什么去年帮一个做系统集成的朋友看现场某农商行支行要换掉用了七八年的老叫号机原厂报价高得离谱功能还锁死。他手里只有一台旧服务器和一堆零散需求取号、叫号、窗口呼叫、语音播报、数据统计。翻遍手头资源最后落到了这套基于 JSP 的银行排队叫号系统上。它不是什么高精尖的东西但胜在完整——SSM 框架打底JSP 做视图MySQL 存业务数据Tomcat 跑服务源码加演示视频一起给拿过来改改就能往网点里塞。这套东西适合两类人一是做 Java 课程设计或毕业设计的学生需要一套能跑通、有业务逻辑、能讲清楚流程的完整项目二是接私活或做小型集成的一线开发想快速搭一个叫号原型省去从零写取号排队算法的功夫。它解决的核心问题很具体把线下排队这件事数字化让取号、排队、叫号、统计四个环节在浏览器里闭环。别指望它扛住大流量但一个网点几十个窗口、日均几百个号它够用。2. 环境选型与依赖锁定为什么 JDK 1.8 MySQL 5.7 不能乱换2.1 版本组合的硬约束从哪来这套项目标注的版本组合是 JDK 1.8、Tomcat 7、MySQL 5.7、Maven 3.3.9开发工具给了 Eclipse、MyEclipse、IDEA 三个选项。很多人第一反应是“我本地有 JDK 17直接上不行吗”血泪经验告诉你不行。原因在 JSP 和 SSM 的依赖链上项目用的 Spring 版本较老JDK 9 之后模块化系统对反射和类加载做了限制老版本 Spring 在启动时扫描注解会直接抛InaccessibleObjectException。Tomcat 7 对应的是 Servlet 3.0 规范Tomcat 9 之后 JSP 编译器的行为有变化web.xml里的一些配置会失效。MySQL 5.7 这个点更关键项目里大概率用了utf8而不是utf8mb4且连接串没配时区参数换到 MySQL 8 会报Unknown system variable query_cache_size或者时区错误。所以最稳的做法是本地装一个 JDK 1.8单独配一个 Tomcat 7MySQL 用 5.7 的安装版而不是绿色版Navicat 11 用来导数据。2.2 依赖安装与项目导入的实操步骤先确认本地 Java 环境命令行敲java -version # 期望输出java version 1.8.0_xxx javac -version # 期望输出javac 1.8.0_xxx如果版本不对去配JAVA_HOME和Path这一步网上教程很多不展开。接着装 MySQL 5.7安装时字符集选utf8root 密码设简单点方便调试。装完用 Navicat 11 连上新建一个数据库名字按项目里 SQL 文件里的CREATE DATABASE语句来通常是bank_queue之类。然后导入 SQL 文件右键数据库选“运行 SQL 文件”选中项目里的.sql编码选utf8执行。Maven 依赖这块项目根目录有pom.xml在 IDEA 里打开后等它自动下载。如果卡在某个依赖下不来检查 Maven 的settings.xml里镜像配的是不是阿里云。常见做法是在settings.xml的mirrors里加一段mirror idaliyunmaven/id mirrorOf*/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror这段配置的作用是把中央仓库请求重定向到国内镜像mirrorOf写*表示所有仓库都走这个镜像。参数上唯一要注意的是id不能和已有镜像重复否则 Maven 会报Duplicate mirror id。2.3 Tomcat 7 的配置与项目部署Tomcat 7 解压后在 IDEA 里配 Run Configuration选 Tomcat Server指向解压目录。部署方式选war exploded这样改 JSP 不用重启。Application context设成/或者/bank看项目里web.xml的display-name。启动前检查web.xml里的welcome-file-list通常是index.jsp。启动后浏览器访问http://localhost:8080/如果看到取号界面说明部署成功。如果报 404先看 Tomcat 日志里有没有ClassNotFoundException多半是 Maven 依赖没打进WEB-INF/lib在 IDEA 的 Project Structure 里把 Maven 依赖加到 Artifact 的WEB-INF/lib下即可。3. 取号排队叫号的业务闭环从 index.jsp 到窗口呼叫的代码链路3.1 取号逻辑与号池生成取号的核心在index.jsp提交后走的那个 Controller。常见做法是用户点“取号”前端发一个 POST 到/ticket/get后端从数据库里查当前最大号加一插入一条新记录返回号票信息。号池的生成有两种策略一种是每天凌晨定时任务重置一种是按业务类型分前缀比如个人业务 A 开头对公业务 B 开头。项目里大概率是前者在 Service 层有一个Scheduled或者手动触发的重置方法。看代码时重点看TicketService里的getNextNumber方法它决定了并发下会不会重号。如果用的是SELECT MAX(number) FROM ticket再INSERT高并发下会翻车正确做法是用数据库自增或者加锁。一个典型的取号 Controller 片段RequestMapping(/get) ResponseBody public MapString, Object getTicket(RequestParam String businessType) { MapString, Object result new HashMap(); // 查询当前该类业务最大号 Integer maxNum ticketService.getMaxNumber(businessType); int nextNum (maxNum null ? 0 : maxNum) 1; Ticket ticket new Ticket(); ticket.setNumber(nextNum); ticket.setBusinessType(businessType); ticket.setStatus(WAITING); ticket.setCreateTime(new Date()); ticketService.insert(ticket); result.put(code, 200); result.put(number, nextNum); return result; }这段代码的逻辑是先查当前业务类型的最大号加一作为新号插入数据库返回给前端。参数businessType区分业务窗口status标记为等待中。问题在于getMaxNumber和insert之间没有事务隔离两个请求同时进来会拿到同一个 maxNum。改进方式是在getMaxNumber的 SQL 里加FOR UPDATE或者直接用INSERT INTO ticket(number, business_type) SELECT IFNULL(MAX(number),0)1, ? FROM ticket WHERE business_type ?这种原子写法。3.2 窗口呼叫与状态流转窗口呼叫的逻辑在call.jsp或对应的 Controller 里。柜员登录后点“呼叫下一位”后端从ticket表里查status WAITING且business_type匹配的第一条记录把status改成CALLING同时更新window_id和call_time。前端轮询或者用 WebSocket 推送给显示屏。项目里如果是 JSP 老架构大概率是轮询每 3 秒发一次 AJAX 查当前叫号。状态流转是WAITING→CALLING→DONE或MISSED。柜员点“完成”后置为DONE点“过号”置为MISSED。这里有个坑如果柜员点了呼叫但客户没来过号后这个号是回到队首还是队尾项目里通常置为MISSED不再参与排队但有些网点要求过号后顺延三位这个逻辑得自己改。3.3 语音播报与显示屏对接语音播报这块项目里一般用前端SpeechSynthesisAPI 或者后端生成音频文件。JSP 页面里嵌一段 JavaScriptfunction speak(number, windowName) { // 检查浏览器是否支持语音合成 if (speechSynthesis in window) { var msg new SpeechSynthesisUtterance(); msg.text 请 number 号到 windowName 办理业务; msg.lang zh-CN; msg.rate 0.9; window.speechSynthesis.speak(msg); } else { console.warn(当前浏览器不支持语音合成请使用 Chrome); } }这段代码用浏览器的语音合成接口播报叫号信息rate控制语速lang设成zh-CN保证中文发音。参数上rate建议 0.8 到 1.0太快听不清。注意这个 API 在部分国产浏览器里被阉割了现场部署时最好用 Chrome 或者 Edge。如果网点要求用 LED 屏那就得走串口或者网络协议项目里通常留了一个display.jsp做轮询展示改造成本不高。4. 数据库表结构与 SQL 导入五个核心表怎么改才不崩4.1 核心表清单与字段含义项目 SQL 文件里通常有五张核心表字段和用途如下表名用途关键字段ticket号票记录id,number,business_type,status,window_id,create_timewindow窗口信息id,window_name,status,user_iduser柜员账号id,username,password,rolebusiness业务类型id,type_name,prefixrecord叫号历史id,ticket_id,call_time,finish_timeticket表是核心status字段的取值决定了整个系统的状态机。window表里的status标记窗口是否开放。user表存柜员登录信息密码通常是 MD5 或者明文如果是明文上线前必须改。business表定义业务类型和号票前缀。record表用于统计报表。4.2 导入 SQL 时的字符集与引擎设置导入前先确认数据库的字符集SHOW VARIABLES LIKE character_set_database; -- 期望输出 utf8 SHOW VARIABLES LIKE collation_database; -- 期望输出 utf8_general_ci如果不是utf8在my.ini里改character-set-serverutf8然后重启 MySQL。导入时用 Navicat 的“运行 SQL 文件”编码选utf8不要选自动否则中文会变问号。表引擎默认 InnoDB如果 SQL 文件里写了 MyISAM改成 InnoDB否则事务不生效。导入后检查ticket表的AUTO_INCREMENT值如果是 0 或者 1没问题如果很大说明之前有数据清空表再重置。4.3 改表结构的三个安全操作第一个加字段。比如要加一个priority字段标记优先号用ALTER TABLE ticket ADD COLUMN priority INT DEFAULT 0 COMMENT 优先级0普通1优先;DEFAULT 0保证老数据不受影响COMMENT方便后续维护。第二个改字段类型。比如number从int改成varchar支持字母前缀ALTER TABLE ticket MODIFY COLUMN number VARCHAR(20) NOT NULL COMMENT 号票号码;改之前先备份MODIFY会重建表数据量大时锁表。第三个加索引。排队查询频繁按status和business_type过滤加联合索引CREATE INDEX idx_status_type ON ticket(status, business_type);索引顺序不能反status区分度高放前面。加完用EXPLAIN看查询计划确认走了索引。5. 避坑与排查这套老项目最容易翻车的五个地方5.1 启动报 404 或 ClassNotFoundException现象Tomcat 启动没报错但访问页面 404日志里翻到ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet。原因Maven 依赖没打进WEB-INF/libIDEA 的 Artifact 配置里漏了。解决打开 Project Structure → Artifacts → 选中 war exploded → 在WEB-INF/lib下点加号 → Library Files → 全选 Maven 依赖 → 确定 → 重新部署。5.2 中文乱码从取号到显示全链路现象取号页面输入中文业务类型存到数据库变问号或者 JSP 显示乱码。原因三个环节的编码不一致——JSP 页面pageEncoding、数据库连接串characterEncoding、MySQL 服务端字符集。解决JSP 头部确保% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8 %JDBC 连接串加?useUnicodetruecharacterEncodingutf8MySQL 的my.ini里character-set-serverutf8。三处都对齐后重启 Tomcat 和 MySQL。5.3 叫号重复或跳号现象两个窗口同时点呼叫叫到同一个号或者号票从 5 直接跳到 7。原因取号时的MAX1并发问题或者AUTO_INCREMENT步长被改过。解决取号改用原子 SQL 或者加锁检查SHOW VARIABLES LIKE auto_increment_increment正常是 1如果是 2 说明被主从配置改过改回 1。5.4 Tomcat 7 启动慢或内存溢出现象启动要两三分钟或者跑一会儿报OutOfMemoryError: PermGen space。原因Tomcat 7 默认 PermGen 太小老项目类加载多。解决在catalina.bat或catalina.sh里加 JVM 参数set JAVA_OPTS-Xms512m -Xmx1024m -XX:PermSize256m -XX:MaxPermSize512mPermSize是 JDK 7 及以前的永久代JDK 8 换成了 Metaspace但 Tomcat 7 配 JDK 8 时这两个参数仍能生效。Xmx别超过物理内存一半。5.5 语音播报没声音现象叫号后显示屏更新了但没声音。原因浏览器自动播放策略限制或者speechSynthesis被禁用。解决确保页面有过用户交互比如柜员点了按钮Chrome 才允许语音检查系统音量合成器里浏览器没被静音如果是无头模式或者远程桌面语音 API 可能不可用换成本地音频文件播放。6. 从能跑到好用三个进阶改造与验证方法第一个改造把轮询改成 WebSocket。轮询每 3 秒一次一个网点 20 个窗口一天下来请求量不小。用 Spring 的WebSocketHandler推叫号消息前端onmessage收到后更新显示和播报。改造后验证方法开两个浏览器一个取号一个呼叫看另一个页面是否秒级更新。第二个改造加一个简单的统计报表。用record表按天分组统计每个窗口的叫号量和平均办理时长。SQL 这么写SELECT w.window_name, COUNT(r.id) AS total_calls, AVG(TIMESTAMPDIFF(SECOND, r.call_time, r.finish_time)) AS avg_seconds FROM record r JOIN window w ON r.window_id w.id WHERE DATE(r.call_time) CURDATE() GROUP BY w.window_name;TIMESTAMPDIFF算两个时间戳的秒差AVG求平均。验证方法手动造几条record数据跑一下看结果对不对。第三个改造把密码从明文改成 BCrypt。项目里user表的password如果是明文用 Spring Security 的BCryptPasswordEncoder在登录时比对。改完记得把存量密码批量加密写个临时接口跑一遍。从那以后我每次拿到这种老项目都强制走一遍“先锁版本、再导数据、最后改配置”的流程顺序反了必翻车。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑