新闻详情

新闻详情

首页 / 资讯中心 / 详情

SSM银行叫号系统实战:状态机+行锁+实时推送

发布时间:2026/10/1 11:46:23来源:尧图网络
SSM银行叫号系统实战:状态机+行锁+实时推送
简介这是一套面向Java初学者与Web开发入门者的银行排队叫号系统实战项目基于SSM框架SpringSpringMVCMyBatis构建完整覆盖前台用户取号、后台叫号管理及状态实时展示等核心业务场景适用于课程设计、毕业设计或企业级轻量级排队系统原型开发。资源包共856个文件含87个Java后端逻辑类、49个JSP页面、217个JS交互脚本、160个PNG图标资源及97个CSS样式文件辅以MySQL 5.7数据库脚本、Tomcat7部署配置与Eclipse项目元数据.classpath、.project等整体压缩包仅29.65MB结构规范、开箱即用。已有465人学习下载配套高清MP4演示视频直观呈现取号、叫号、重呼、暂停等全流程操作源码注释清晰关键模块如号段生成策略、窗口状态同步机制均有良好实现便于理解MVC分层设计与前后端协同逻辑。1. 银行窗口排队叫号系统一个被低估的SSM实战练手项目专治“只会写CRUD却搞不定真实业务流”的Java新手你有没有试过在银行大厅等号——取号、叫号、过号、重叫、插队、VIP优先、临时暂停服务……这些看似简单的动作背后是一套强状态、高并发、低延迟、带人工干预的实时调度逻辑。而这个基于JSPSpringSpringMVCMyBatisSSM的银行排队叫号系统不是玩具Demo它完整跑通了从号源生成、窗口绑定、语音播报、LED屏同步、超时重排到管理员后台干预的全链路。它用JDK1.8 Tomcat7 MySQL5.7搭建所有代码可直接导入Eclipse运行附带演示视频验证流程闭环。适合两类人一是刚学完SSM但没做过真实业务模块的Java初学者用来补上“业务状态流转”这一课二是准备Java面试的开发者里面藏着大量高频考点——事务边界设计比如叫号失败如何回滚号段、Session与Cookie协同控制多窗口登录隔离、JSP自定义标签封装叫号状态渲染、MySQL行锁实践号池原子扣减。别被“JSP”吓退——它恰恰是理解Web层原始交互逻辑的绝佳切口。2. 项目结构拆解与环境复现从Eclipse导入到Tomcat启动的六步实操2.1 项目目录结构还原识别核心模块与隐藏依赖拿到压缩包后先解压观察文件层级。这不是标准Maven结构没有pom.xml而是典型的Eclipse动态Web项目布局BankQueueSystem/ ├── WebContent/ # JSP页面、静态资源主目录 │ ├── index.jsp.bak # 主入口页面备份注意.bak后缀 │ ├── topNav.jsp.bak # 顶部导航栏备份 │ ├── styles.css.bak # 样式表备份 │ ├── bootstrap.min.css # 前端框架Bootstrap 3.x │ ├── ueditor.css # 富文本编辑器样式说明后台有公告管理模块 │ └── ... ├── src/ # Java源码含controller/service/dao/entity ├── WEB-INF/ │ ├── web.xml # Servlet配置中枢关键需检查servlet-mapping │ ├── applicationContext.xml # Spring核心配置bean扫描、事务管理器 │ └── springmvc-servlet.xml # SpringMVC配置视图解析器、拦截器 ├── .classpath # Eclipse类路径定义决定哪些jar被加载 ├── org.eclipse.wst.common.component # WTPWeb Tools Platform部署描述 └── lib/ # 手动引入的jar包重点看mysql-connector-java-5.1.47.jar提示.bak后缀文件是原始开发者的备份习惯实际运行需重命名为index.jsp等。org.eclipse.wst.common.component文件决定了Eclipse如何将项目发布到Tomcat——若缺失或错误会导致“404找不到JSP”。2.2 JDK与Tomcat版本锁定为什么必须是JDK1.8 Tomcat7项目明确要求JDK1.8和Tomcat7这不是随意指定而是由技术栈兼容性决定的JSP语法限制项目中大量使用c:forEach、fmt:formatDate等JSTL标签这些在JDK1.8Tomcat7组合下默认启用。若升级到JDK17Tomcat10JSP引擎Jasper已移除对javax.servlet.*旧包的支持会报java.lang.NoClassDefFoundError: javax/servlet/jsp/JspFactory。Spring版本锚定从applicationContext.xml中context:component-scan和tx:annotation-driven标签推断此项目使用Spring 4.x非5.x。Spring 4.3.x是最后一个支持Tomcat7的主版本且其AOP代理机制依赖JDK1.8的invokedynamic指令优化。MySQL驱动匹配lib/目录下mysql-connector-java-5.1.47.jar仅支持MySQL 5.7协议。若强行连接MySQL 8.0会因认证插件caching_sha2_password不兼容而报Access denied for user。实操步骤下载JDK1.8u361官方最后安全更新版配置JAVA_HOME下载Apache Tomcat 7.0.109最后维护版解压后在Eclipse中Window → Preferences → Server → Runtime Environments添加在Eclipse中File → Import → Existing Projects into Workspace选择解压目录勾选“Copy projects into workspace”避免路径权限问题右键项目 →Properties → Project Facets确认Dynamic Web Module版本为3.0对应Tomcat7Java版本为1.8右键项目 →Build Path → Configure Build Path检查Libraries页签中JRE System Library指向JDK1.8Web App Libraries包含mysql-connector-java-5.1.47.jar。2.3 数据库初始化Navicat11建库、导入SQL、校验字符集项目未提供SQL脚本别急——src/目录下通常藏有sql/子目录或DBScript.txt。若无可从WEB-INF/web.xml中查找数据库连接配置反向定位建库语句。本项目典型配置如下!-- WEB-INF/web.xml -- context-param param-namecontextConfigLocation/param-name param-valueclasspath:applicationContext.xml/param-value /context-param进入src/main/resources/applicationContext.xml或src/applicationContext.xml找到bean iddataSourcebean iddataSource classorg.springframework.jdbc.datasource.DriverManagerDataSource property namedriverClassName valuecom.mysql.jdbc.Driver/ property nameurl valuejdbc:mysql://localhost:3306/bankqueue?useUnicodetrueamp;characterEncodingutf8/ property nameusername valueroot/ property namepassword value123456/ /bean建库与初始化步骤启动MySQL 5.7服务确保端口3306空闲用Navicat11新建连接用户名root密码123456新建数据库bankqueue字符集选utf8mb4排序规则utf8mb4_unicode_ci比utf8更彻底支持emoji避免中文乱码执行建表SQL若无现成脚本根据实体类src/entity/Number.java等反推CREATE TABLE t_number ( id int(11) NOT NULL AUTO_INCREMENT, number_code varchar(20) NOT NULL COMMENT 号码编号如A001, window_id int(11) DEFAULT NULL COMMENT 当前分配窗口ID, status tinyint(1) NOT NULL DEFAULT 0 COMMENT 0-待叫1-已叫2-过号3-完成, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_number_code (number_code) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;插入初始测试数据INSERT INTO t_number (number_code, status) VALUES (A001, 0), (A002, 0), (B001, 0);参数说明useUnicodetruecharacterEncodingutf8在URL中是必需的否则JSP页面提交的中文参数会变成??utf8mb4字符集能完整存储微信昵称等四字节UTF-8字符避免插入时报错。2.4 Eclipse部署与启动绕过常见404陷阱的三处关键配置即使代码无误Eclipse常报HTTP Status 404。根源往往不在代码而在部署配置检查web.xml中的welcome-file-list确保首页面指向正确路径welcome-file-list welcome-fileindex.jsp/welcome-file !-- 注意不是index.html -- /welcome-file-list若index.jsp仍404右键项目 →Properties → Web Project Settings确认Context root为/bankqueue而非默认/访问地址应为http://localhost:8080/bankqueue/。验证springmvc-servlet.xml的mvc:annotation-driven/是否启用此标签开启SpringMVC注解驱动如Controller、RequestMapping。若缺失所有Controller方法不会被扫描导致请求无响应mvc:annotation-driven / context:component-scan base-packagecom.bankqueue.controller /Tomcat部署路径修正Eclipse默认将项目发布到Tomcat/wtpwebapps/但有时会生成冗余目录。手动清理关闭Tomcat删除Tomcat/wtpwebapps/bankqueue/及Tomcat/wtpwebapps/bankqueue.war在Eclipse中右键项目 →Run As → Run on Server选择Tomcat7启动后观察Console输出确认出现INFO: Server startup in [xxx] ms且无ClassNotFoundException。3. 核心业务逻辑实现号源管理、窗口调度与状态机设计3.1 号源生成与原子扣减MySQL行锁保障并发安全银行叫号最怕“重复取号”或“号段跳号”。本项目采用“预生成号段数据库行锁”双保险号段预生成管理员在后台设置每日号段范围如A001-A500系统启动时批量插入t_number表取号原子操作用户点击“取号”时执行以下SQL在NumberService.java中UPDATE t_number SET status 1 WHERE id ( SELECT id FROM ( SELECT id FROM t_number WHERE status 0 AND number_code LIKE A% ORDER BY create_time ASC LIMIT 1 ) AS tmp ) LIMIT 1;逻辑说明先子查询找到最早待叫号的id再用UPDATE ... LIMIT 1更新其状态。LIMIT 1防止并发时多个线程同时更新同一行WHERE status 0确保只处理未分配号。Java层校验NumberService.getNumber()方法中update返回值为int若为0说明无可用号需抛出业务异常int rows numberMapper.updateStatusById(id); if (rows 0) { throw new BusinessException(当前无可用号码请稍后再试); }3.2 窗口叫号状态机五种状态流转与事务边界叫号不是简单“查-改”而是涉及多表联动的状态迁移。t_number表status字段定义了严格状态机状态码状态名触发条件关联操作0待叫取号成功无1已叫窗口点击“叫号”更新window_id触发语音播报2过号超时未应答定时任务扫描发送短信提醒允许重叫3完成用户点击“完成”记录服务时长释放窗口4暂停管理员手动暂停窗口窗口停止接收新号事务设计要点叫号操作必须包含更新t_number.status、更新t_window.current_number、插入t_log日志——三者在一个Transactional内过号由独立定时任务OverTimeJob.java执行不加事务避免长事务阻塞采用SELECT ... FOR UPDATE锁定待处理记录完成操作需校验status1防止重复完成使用Transactional(propagation Propagation.REQUIRED)确保原子性。3.3 LED屏与语音播报集成通过Servlet推送实时消息前端LED屏和语音播报不是轮询实现而是利用HttpServletResponse流式推送LED屏控制器LedServlet.java监听/led/update请求将JSON格式号段信息写入响应流response.setContentType(text/event-stream); response.setCharacterEncoding(UTF-8); PrintWriter out response.getWriter(); out.write(data: {\current\:\A005\,\next\:\A006\}\n\n); out.flush();前端JavaScript监听const eventSource new EventSource(/bankqueue/led/update); eventSource.onmessage function(event) { const data JSON.parse(event.data); document.getElementById(current).innerText data.current; document.getElementById(next).innerText data.next; };语音播报调用Windows系统TTS文本转语音VoiceUtil.java中执行命令String cmd C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -Command \Add-Type –AssemblyName System.Speech; $speak New-Object System.Speech.Synthesis.SpeechSynthesizer; $speak.Speak(请A零零五号到一号窗口)\; Runtime.getRuntime().exec(cmd);参数说明text/event-stream是Server-Sent EventsSSE协议比WebSocket轻量适合单向实时推送PowerShell调用TTS需确保服务器启用.NET Framework 3.5。4. 避坑指南EclipseTomcatMySQL组合下五个血泪经验4.1 现象Eclipse启动Tomcat后Console无日志浏览器报404原因web.xml中servlet-mapping的url-pattern与Controller的RequestMapping不匹配或springmvc-servlet.xml未正确加载。解决检查web.xml中servlet的servlet-class是否为org.springframework.web.servlet.DispatcherServlet确认init-param中contextConfigLocation指向classpath:springmvc-servlet.xml在springmvc-servlet.xml中添加mvc:default-servlet-handler/让静态资源CSS/JS可被Tomcat原生Servlet处理。4.2 现象取号成功但LED屏不刷新语音无反应原因SSE连接被浏览器缓存或PowerShell执行权限被禁用。解决前端EventSource URL后加时间戳参数new EventSource(/bankqueue/led/update?t Date.now())Windows服务器需以管理员身份运行PowerShell执行Set-ExecutionPolicy RemoteSigned -Scope CurrentUser解除脚本限制替代方案改用Java TTS库如FreeTTS避免依赖系统组件。4.3 现象MySQL插入中文变??日志显示Incorrect string value原因数据库、表、字段三级字符集未统一为utf8mb4或JDBC URL缺少useUnicodetruecharacterEncodingutf8mb4。解决执行ALTER DATABASE bankqueue CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;对所有表执行ALTER TABLE t_number CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;JDBC URL改为jdbc:mysql://localhost:3306/bankqueue?useUnicodetruecharacterEncodingutf8mb4serverTimezoneGMT%2B8。4.4 现象Eclipse中修改JSP后刷新无效仍显示旧内容原因Tomcat的JSP编译缓存未清除或Eclipse的自动构建被禁用。解决清理Tomcat工作目录删除Tomcat/work/Catalina/localhost/bankqueue/Eclipse中Project → Clean整个项目确保Project → Build Automatically已勾选。4.5 现象管理员登录后无法看到窗口列表报NullPointerException原因WindowService.java中Autowired的windowMapper为nullSpring未正确扫描Mapper接口。解决检查applicationContext.xml中mybatis:scan base-packagecom.bankqueue.mapper/是否配置确认WindowMapper.java接口上有Mapper注解若用MyBatis注解方式或mapper目录在src/main/resources下且XML文件命名规范WindowMapper.xml对应WindowMapper.java若用XML映射检查WindowMapper.xml中namespace是否等于com.bankqueue.mapper.WindowMapper。5. 进阶技巧从演示系统到生产可用的四个加固点5.1 号池扩容策略支持多业务类型与优先级队列当前系统仅支持单一字母前缀如A/B但真实银行有VIP、企业、个人、外币等多队列。改造方案扩展t_number.number_code字段增加business_type列TINYINT值为1(VIP)、2(企业)、3(个人)叫号算法升级窗口叫号时按优先级查询SELECT * FROM t_number WHERE status 0 ORDER BY business_type ASC, create_time ASC LIMIT 1;VIP号business_type1永远排在最前前端分离展示LED屏分区域显示VIP当前V001、普通当前A005需修改LedServlet组装JSON逻辑。5.2 防过号机制基于Redis的分布式超时监控当前过号依赖单机定时任务存在单点故障。引入Redis实现高可用取号时写入RedisredisTemplate.opsForValue().set(number: numberCode, waiting, 120, TimeUnit.SECONDS);独立服务监听过期Key利用Redis Keyspace Notifications当number:A001过期时触发事件自动更新数据库状态优势毫秒级响应避免定时任务扫描延迟支持集群部署。5.3 日志审计增强记录关键操作的完整上下文现有日志仅记录INFO级别无法追溯问题。在LogAspect.java中增强操作类型记录字段示例取号用户IP、设备指纹、号段、时间192.168.1.100叫号窗口ID、操作员账号、被叫号码WIN1完成服务时长、评价星级若有A001Around(annotation(org.springframework.web.bind.annotation.RequestMapping)) public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start System.currentTimeMillis(); Object result joinPoint.proceed(); long end System.currentTimeMillis(); // 获取Request对象获取IP ServletRequestAttributes attributes (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); String ip attributes.getRequest().getRemoteAddr(); logger.info(IP:{} | Method:{} | Time:{}ms, ip, joinPoint.getSignature(), end - start); return result; }5.4 安全加固防止越权访问与SQL注入演示系统未做权限控制生产环境必须补上URL级拦截在web.xml中配置security-constraint限制/admin/*路径仅ROLE_ADMIN可访问Mapper层防护所有LIKE查询使用#{}而非${}避免拼接SQL!-- 安全 -- if testsearchKey ! null and searchKey ! AND number_code LIKE CONCAT(%, #{searchKey}, %) /if !-- 危险SQL注入 -- !-- AND number_code LIKE %${searchKey}% --密码加密User实体类中password字段存储BCrypt加密结果登录时用BCryptPasswordEncoder.matches()校验。从那以后我每次接手老项目第一件事就是检查web.xml的welcome-file-list和servlet-mapping是否匹配再验证springmvc-servlet.xml里context:component-scan的包路径有没有写错——这两个地方占了80%的404问题。另外只要看到.bak文件我都会立刻重命名并对比内容因为很多“功能失效”其实是备份文件覆盖了主文件。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Ubuntu Desktop 从零到能干活:安装、分区与调优指南 2026/10/1 13:26:04

Ubuntu Desktop 从零到能干活:安装、分区与调优指南

1. 装前把账算清楚:Desktop版到底装给谁用 Ubuntu Desktop版本,说白了就是把一套完整的图形桌面环境打包好的发行版,装上之后你能看到任务栏、文件管理器、设置面板,像用Windows一样点鼠标就能操作。它和Server版最大的区别就在这…

阅读更多 →
嵌入式内存管理实战:从内存泄露排查到优化指南 2026/10/1 13:26:04

嵌入式内存管理实战:从内存泄露排查到优化指南

干了几年嵌入式开发,几乎每个项目都会遇到一类让人熬夜的问题:系统跑着跑着就卡死、内存占用缓缓爬升、偶尔复位重启,最后调了一周发现只是一小块buffer忘了释放。这类问题的根源都指向同一个地方——内存。对嵌入式开发者来说,内…

阅读更多 →
Spring Messaging 消息抽象层详解:核心模型与 WebSocket/RabbitMQ 实战 2026/10/1 13:26:04

Spring Messaging 消息抽象层详解:核心模型与 WebSocket/RabbitMQ 实战

Spring 系列学到这里,很多人会被一个“隐形的模块”卡住——它叫 Spring Messaging。你翻 Spring 官方文档时经常看到它,但真正写业务却很少直接调它;你搜 RabbitMQ、Kafka、WebSocket 的资料时又总能看到它的影子。不少朋友以为 Spring Mess…

阅读更多 →
Spring Messaging核心抽象与实战:从MessageChannel到异步消息处理 2026/10/1 13:26:04

Spring Messaging核心抽象与实战:从MessageChannel到异步消息处理

做后端开发这些年,Spring Messaging一直是我觉得“人人都用过,但很少有人专门聊”的模块。你很可能已经在WebSocket、STOMP、RSocket甚至Spring Integration里间接接触过它,只是没意识到背后那套统一的抽象模型就是Spring Messaging在起作用。…

阅读更多 →
国产8位RISC18单片机选型指南:超低功耗USB+LCD集成方案 2026/10/1 13:26:04

国产8位RISC18单片机选型指南:超低功耗USB+LCD集成方案

1. 项目概述:为什么8位RISC18架构在国产单片机选型中突然“冒头”最近三个月,我在给十多家中小电子方案公司做MCU选型咨询时,明显感觉到一个变化:原本清一色问“STM32用哪个型号”,现在有近四成客户开口就是&#xff1…

阅读更多 →
Spring构造注入与循环依赖:从原理到项目重构避坑指南 2026/10/1 13:25:57

Spring构造注入与循环依赖:从原理到项目重构避坑指南

1. 先弄清楚:构造注入到底解决了什么问题写过几年Spring的人,多少都会遇到一种情况:一个Service里塞了五六个依赖,清一色Autowired字段注入,代码倒是写起来爽了,可一旦要写单元测试、要复现某个并发问题、要…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉