十几年前我读大学那会儿,安卓开发刚火起来,Java相关的毕业设计大多还是SSH(Struts+Spring+Hibernate)那套老框架,做的也无非是图书管理、学生选课这些老面孔。如今再看热门毕设榜单,SpringBoot已经成了事实上的标配,而“智慧公交”“城市公交调度”这类题目,也从当年的“高端玩法”变成了很多同学能落地、能讲清楚、还方便演示的优质选题。
我今天想掰开揉碎聊的,就是这类标题的典型代表:SpringBoot + Java架构下的智能公交车管理系统,或者叫城市公交智慧调度与信息服务平台。标题看着长,核心其实就三层:车辆数据实时采集与监控、基于数据的智慧调度决策、面向乘客和运营方的信息服务。它不是单纯做个CRUD,也不是纯粹搞算法,而是把物联网设备接入、实时通信、业务规则引擎、可视化大屏这些技术栈都串在了一起。对毕设而言,这种“上下都有延展空间”的题目,特别适合用来展示一个计算机专业学生的综合工程能力,无论是写论文还是做答辩演示,素材都远比普通管理系统丰富得多。
这篇文章,我会用实际做过的类似项目的思路,把题目后半段“隐藏”的功能模块、数据模型、技术选型、开发顺序、测试要点一一展开,希望能给正在做这个题目的同学指明方向,也让打算选这个方向的朋友提前知道坑在哪里。
1. 从标题拆出真实需求
1.1 “智能调度”四个字背后是三套业务
拿到题目先别急着写代码。很多同学看到“调度”两个字就慌了,觉得自己要去实现一套人工智能排班算法,其实不是这样。毕设里的“智慧调度”更多是指“信息化支撑下的调度管理流程”,核心是把原来靠微信群、Excel表格、口头沟通完成的排班发车工作,搬到系统里来。
具体可以拆成三个层面来看:第一是基础数据层,包括线路信息、站点信息、车辆信息、驾驶员信息、班次计划;第二是实时运营层,包括车辆的实时定位、到离站状态、运行轨迹、异常告警;第三是调度决策层,包括自动生成发车计划、临时加车、跳站调度、驾驶员排班等。
对应到系统功能上,就是线路管理、车辆管理、班次管理、司机管理、实时监控大屏、调度指令下发、乘客端查询服务这几大模块。我见过不少同学的代码里,把“调度”做成了一个孤立的增删改查页面,点几下按钮生成一个发车时间表就完事,这就把题目做小了。真正的调度应当以“当日运营计划”为核心,让车辆、班次、司机都挂靠在计划上运转,计划变了,所有数据联动变化,这才叫系统。
1.2 服务对象不同,功能侧重完全不同
“信息服务平台”这个表述点出了系统的另一重要属性——它不只是给公交公司内部用的,还要面向乘客提供服务。明确服务对象是做系统架构的第一前提。
对运营调度人员而言,系统核心是效率与掌控力:需要看到全部车辆的实时分布,需要知道某条线路堵车后下一班车该不该提前发,需要快速给某位临时请假的司机找替补。对乘客而言,核心则是准确与便捷:等车的时候想知道车还有几站到,末班车过去没有,或者站点调整了走哪个门上车。这两个角色对“实时”二字的理解完全不同:调度员要的是秒级的状态刷新和异常提醒,乘客要的是稳定的查询响应和可读性强的结果展示。
我建议系统设计成两个甚至三个端:管理后台(Web端)面向调度员和系统管理员,乘客小程序或H5页面向普通用户,数据大屏用来看全局态势。这样分层下来,论文里写“系统设计”时模块边界清楚,答辩时也能清楚解释每个页面给谁用、解决了什么问题。
1.3 标题里没写但必须有的隐性模块
这类综合管理系统类毕设,有几个模块是“行业惯例”,浏览器里看不到,但是在数据库和后台里必须存在。
一是用户与权限模块。一个系统里如果没有区分管理员、调度员、驾驶员、乘客这些角色,那在答辩时就容易被问住。大多数成熟方案是引入Spring Security + JWT做认证授权,将角色权限控制到按钮级或接口级,这部分本身也能成为论文里的亮点章节。
二是日志与审计模块。谁在什么时间修改了某条线路的发车时间,这些操作留痕在真实运营场景中是刚需。即便做简化版本,至少要有基础的登录日志、操作日志表,毕竟调度指令要修改行车计划,没有追溯可不行。
三是统计报表模块。信息平台的价值很大程度体现在数据沉淀后给出的报表上,例如线路单日客流趋势、发车准点率、车辆在线率、司机出勤统计。这些数据将来可以作为调度决策优化的依据,有了它们,论文中才能围绕“基于数据的调度”展开更深一层的分析。
不提前规划好这些隐性模块,到后期就会面临“加功能推翻表结构”的尴尬。常见的坑是:数据库中用户表只有管理员一个角色,车辆表没有状态字段,实时位置数据不知道怎么存——这些细节我们在数据库设计小节细说。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与架构设计逻辑
2.1 为什么是SpringBoot而不是别的?
Java方向的毕设选SpringBoot,几乎是如今最稳妥的选择。但稳妥并不代表默认,我自己做项目时也反复权衡过,最终选定它并不仅仅是“大家都用”。
SpringBoot真正解决的是Spring框架长期以来配置繁琐的问题。做SSH时代的老项目,写几十行XML配置那是家常便饭,一个配置文件写错,启动直接报错,排查半天还找不到原因。SpringBoot用自动配置和约定优于配置的理念,把大部分基础配置收敛到application.yml里,一键启动内嵌Tomcat,这能大大缩短项目搭建时间。尤其对毕设而言,时间是最大的敌人,把精力花在功能设计上远比花在框架整合配置上值得多,选SpringBoot能让开发效率明显提升。
再从性能与生态角度来说,基于Java的企业级应用在Web开发方面不但生态完善,而且社区活跃,遇到问题基本都能在网络上找到解决方案。SpringBoot在整合MyBatis、Redis、WebSocket、定时任务、消息队列等常用模块时都很成熟——官方有大量Starter,一段依赖一配,功能即刻生效。做实时公交系统,后面要上WebSocket推送车辆位置,SpringBoot对WebSocket的原生支持也很到位,开发复杂度并不高。
2.2 经典前后端分离架构怎么分层?
这套系统按照目前主流的前后端分离方案来搭,结构会比较清晰,既能提高前后端并行开发效率,演示时也可以独立运行。
后端部分按现在的标准实践分成Controller层、Service层、Mapper层。Controller只负责接收请求、参数校验、统一响应;Service封装业务逻辑,比如生成调度计划时校验司机是否重复排班;Mapper负责数据库操作,配合MyBatis Plus使用的时候几乎不需要手写SQL,简单查询直接调用封装好的方法。这种分层带来的直接好处是测试容易——我想要验证调度算法,只需要写Service的单元测试,不必走HTTP接口;想要排查某个查询慢的问题,也能迅速定位到具体的SQL语句。
前端部分选Vue 3 + Element Plus搭建管理后台仍然是主流方案,配合Vite作为构建工具,开发体验流畅,npm run dev起来就能连后端联调。ECharts用于图表渲染,做实时监控大屏和统计报表都很顺手。
这里要提醒一点:选型时不要太追求“生僻技术”来显得厉害。比如有人为了体现高并发,引入了一套完整的微服务架构(Spring Cloud Alibaba全家桶),就做几个简单业务接口,把服务拆成三四个子模块,结果开发和部署成本直接翻倍。毕设的重心永远是“业务完整性+工程规范性”,单体SpringBoot应用足以支撑每秒百级的并发请求,先把单体应用做扎实了,比空谈微服务更有说服力。真要体现自己的工程能力,把Redis缓存、MQ削减峰值这种模块用到位,效果会比强行上微服务好得多。
2.3 实时定位、站距计算这些关键技术怎么落地?
这套系统区别于普通管理系统的核心,在于“实时”二字。要让“实时公交”这几个字不只是网页标题上的装饰,选对通信手段非常重要。
车辆位置的采集和更新路径主要有两条思路。第一条是前端定时轮询,车辆端每隔几秒上报一次位置到后端接口,后端存入数据库或缓存;乘客端查询时再通过后端接口读取。这样做简单可靠,但存在数据库压力大、数据不够实时的问题。第二条是后端做WebSocket推送,车辆上报位置后,后端实时推送给正在查看该车辆的所有客户端(调度大屏、乘客端、司机端)。
实际项目里更合理的做法是两者结合:车辆端上报位置走HTTP或TCP/MQTT协议到后端;后端将最新位置写入Redis并广播至相关WebSocket会话;页面端实时收到的车辆位置用于渲染大屏动画,历史轨迹则通过HTTP接口读取数据库中的数据回放。核心要点是数据库不能存热点位置数据,高并发写入会拖垮整个系统。
至于车辆到站距离和时间预测,完整实现会涉及路况判断、历史通行时长分析等复杂算法,但毕设阶段可以做一个简化版本:基于线路站点经纬度列表,用Haversine公式计算车辆与当前站点直线距离,再结合线路限速做一个估算时间。只要能把路线距离、预计到达时间显示出来,已经具备演示效果,论文中也可以如实写明这套方法的应用前提与局限性,体现专业素养。
2.4 容器化部署价值很大,但别在答辩前硬上
部署方案上,SpringBoot打一个fat JAR,服务器装好JDK17或JDK8直接java -jar运行,这是最基础也最稳妥的玩法。如果你对Docker有一定熟悉度,写一个Dockerfile,把后端容器化,再配合docker-compose把MySQL、Redis一起编排起来,在论文中写“系统支持容器化一键部署”,是实打实的加分项。
但我要提醒一点:不要在答辩前两天才开始折腾Docker。这类部署方案需要反复验证,容器里时区不对、MySQL初始化脚本没执行、宿主机访问不到容器,分分钟能让人心态崩溃。如果时间紧张,宁可把全部精力放在功能完善和数据演示上,也不要在部署环节栽跟头。毕竟答辩现场用本机演示,本地运行完全不是问题。
3. 核心功能模块设计与实操细节
3.1 线路站点班次,基础数据建模决定后续开发效率
很多人一上来就写车辆管理界面,先把车的增删改查做得漂漂亮亮,结果到后面做线路规划、站点排序时才发现车辆和线路之间关系混乱,返工成本巨大。基础数据建模是这类系统的地基,顺序绝对不能乱,建议按照线路 → 站点 → 车辆 → 驾驶员 → 班次计划的次序逐层推进。
线路上要维护线路名称、类型(常规/快速/夜班)、首末班时间、票价等信息。如果系统面向多城市运营,还需要城市字段,虽然毕设一般是单城市演示,但留出这个字段,以后扩展会方便很多。
站点不要简单存一个名称,必须存经纬度这两个字段,哪怕你在模拟数据阶段用拾取器粗略填值。因为后续车辆的到离站判断、站距计算、乘客端“附近站点”查询全要依赖于经纬度。建议站点表包括站点名称、所属区域、经度、纬度、站点序号,同时配置一张line_station关联表来记录某线路经过哪些站点、顺序如何、站间距离是多少。
公交线路通常有上行和下行两个方向,这是很多同学容易忽略的细节。同一辆车从始发站开到终点站,和从终点站开回始发站,经过的站点列表是相反的,班次表的字段必须能区分direction。如果忽略了这一层,后面做调度计划的时候会出现“上一秒去程下一秒回程但站点顺序没变化”的严重逻辑错误。我第一次做公交项目时就吃过这个亏,所以专门提醒大家:凡是涉及线路线网的数据表,都要有方向字段。
3.2 车辆实时定位与轨迹回放怎么做?
车辆实时定位是整个系统的数据底座,调度大屏上的车辆分布、乘客端的车辆到站提醒,全都依赖这个模块。不建议一开始就接触真实GPS硬件和MQTT通信协议,那会使前期复杂度陡增,建议用模拟数据先跑通整条链路。
先设计一张bus_vehicle表,核心字段包括车牌号、设备编号(IMEI)、车辆状态(运营中、维修、停运)、上线时间等。设备编号在真实项目中对应车载终端,模拟阶段我们直接用设备编号查对应的车。
后端设计一个模拟上报接口,例如 POST /api/vehicle/report,接收设备编号、经度、纬度、车速、方向角、上报时间这些参数。模拟器可以是一个简单的Java定时任务,按固定间隔读取预先录制的某辆车行驶轨迹点并上报;也可以做得更直观一点——写一个前端页面模拟驾驶员客户端,用定时器在地图上每隔几秒移动一个小车图标,把经纬度实时推送过来。
收到车辆上报的数据后,不能直接就存MySQL。合理的设计是:Redis中维护一个hash结构,key是bus:location:{deviceId},value包括经纬度、时间、速度;同时把历史运行数据异步写入一张bus_gps_record表,用于轨迹回放。这块业务真正体现了“实时系统与普通管理系统的架构差异”,在论文里写清楚这两个存储的各自职责,能向评委展示你的系统设计能力。
轨迹回放模块通常用一个专门页面实现,通过选择车辆和时间范围,从bus_gps_record表读取轨迹点位,前端使用Map地图或Canvas绘制路线。点可以少一点,但时间字段要有毫秒精度,不然前端动画会跳帧。
3.3 调度管理实现要点:排班、调令、联动
调度是本系统业务逻辑最厚的地方,我把这个模块拆成两条线:一条是例行的基础排班计划,另一条是运营过程中的动态调整。
基础排班发生在“运营日”开始时(通常收班后规划)。输入某条线路当日可用车辆数和司机数、首末班时间、发车间隔参数,系统自动生成当日所有班次。每一条班次记录包括:所属线路、方向、车牌、司机、计划发车时间、计划到达时间、当前执行状态(待发车/运行中/已到达/已取消)。如果同一辆车要跑多个班次,系统需要自动检查相邻班次之间是否有足够的间隔时间,司机不能连续跑完去程马上跑回程,中间强制需要休息时间。这些规则写在脑子里容易,写成代码条件后,再配以批量生成算法的循环逻辑,你会发现它本质上是一个变种的区间排班问题。
动态调整发生在运营过程中,是实时公交更核心的价值点。比如某线路遇到临时堵车,原定10:00发车的班次已经延误了15分钟,调度员可以在系统里发起一个“临时加车”指令——选择一辆空闲车辆、选择一位当前空闲司机、下发临时任务到司机端;也可以选择“跳站调度”,将后续班次的部分站点跳过以恢复间隔。每次调令的发起、确认、执行都要记录到数据库,形成一条完整的调度指令流。
这块实操时的核心难点在于“状态流转”。一辆车的状态可能是待发车、运行中、已到达、维修中、临时任务中。一个班次也可能出现延误、取消、增发的情形。没有经验的开发者很容易写成随意修改状态字段,导致业务数据错乱。我的做法是引入状态机思路:先罗列所有状态节点,再明确哪些变迁是被允许的,把状态流转逻辑收敛到Service中统一管理,禁止在Controller层直接修改状态。
3.4 乘客端和信息发布平台如何设计?
做乘客端,不用一开始就上微信小程序(涉及注册审核,开发调试也比较费周折),可以先做一个H5页面或者一个基于Vue的简易WebApp,在手机浏览器里访问,也能达到相当不错的演示效果。
乘客查询的最核心动作是“查线路”和“查车辆到哪了”。查线路就是用户选择一条线路,前端显示该线路上下行所有站点,以及当前线路上所有正在运行的车辆,每辆车显示车牌号和预计到下一站的时间。查“车到哪了”则需要更精确:用户选一个站点,系统显示出经过该站点的所有线路,以及每条线下一班车距离本站还有几站和预计分钟数。
这个功能看上去简单,背后的数据查询却要好好设计:根据所选线路ID,找到该线路当前运行中的所有车辆,根据车辆当前所在站序号和目标站点序号,算出剩余站点数,用累加站间距离估算时间,并按方向分组排序。将计算结果写入Redis缓存,设置30秒过期,能有效降低数据库压力。没有这一层缓存设计,大量乘客查询一旦涌进来,数据库会率先扛不住,这部分逻辑在答辩时也是亮点。
信息发布则是运营方与乘客之间的桥梁。管理员在后台发布线路调整公告、临时绕行通知、节假日运营时间变化,乘客在首页可以看到消息列表。为了评分有亮点,可以把重要消息做成置顶模式,并设置生效时间段,过期消息后台自动结束展示。这样比普通公告板看上去更像真实运营系统。
3.5 数据大屏:演示环节的“颜面”担当
数据大屏在整个系统中扮演的角色很特殊——它不承载具体业务,却是整个项目演示时的视觉焦点,也是答辩PPT里最拿得出手的截图。一个布局合理的调度大屏,通常包含:左侧展示某条线路的实时车辆动态列表,中间是地图区域(车辆位置分布一目了然),右侧展示今日运营统计指标(发车总班次、准点率、在线车辆率、客流估算),下方可放置客流趋势折线图或线路准点率排名。
大屏技术选型常见可以选DataV或纯ECharts。地图可以考虑使用高德地图或Leaflet,点位使用车辆图标标注,车辆移动时更新Marker。页面上用WebSocket接收后端推送实时位置,帧间隔建议2秒以上,避免数据量过大造成浏览器卡顿,尤其是同时展示几十辆车时。
实时数据跑起来之后,大屏上的地图轨迹动线确实非常直观,车辆往前开、站点图钉闪烁、指标数字跳动,这一个画面顶过你PPT里几千字的系统介绍。这个视效的震撼感,会让评委印象深刻。
4. 数据库设计要点与关键表剖析
4.1 核心表整体架构一览
做这类系统,表数量在18到25张之间比较常见,既覆盖了完整业务,又不至于太过琐碎。按照业务域划分,可将表分成五组:系统管理域(sys_user、sys_role、sys_user_role、sys_operation_log)、基础资料域(bus_line、bus_station、bus_line_station、bus_vehicle、bus_driver)、运营调度域(bus_schedule、bus_dispatch_command、bus_gps_record)、乘客服务域(bus_notice、bus_feedback)、统计报表域(可基于运营数据实时聚合,不必单独设计明细表)。
一个容易犯的错误是:把所有字典项用Java枚举写死在代码里,没有设计字典表。比如车辆状态、班次状态、线路类型等字段,做一个sys_dict_type和sys_dict_data两张表统一管理,好处是以后扩展状态时不需要改代码重启系统,管理界面直接加一条记录即可。也让论文的“系统设计”一栏看起来完整得多。
4.2 调度计划表是业务核心,怎么设计不返工?
我建议把每日计划设计成主从两张表来管理:bus_schedule_plan(调度计划头表)和bus_schedule_plan_detail(计划明细行表)。
头表存运营日期、线路名称、运营方向、计划状态、生成时间;明细表存每一个具体的“班次”:车牌号、驾驶员、计划发车时间、计划到达时间、发车间隔或者班次序号。
为什么用主从结构?因为业务上常常需要整体调整某天某条线路的发车计划,比如临时缩减全部班次。如果直接在明细表上逐条修改,操作分散且难维护;有了头表后,可以一键作废整条计划的全部班次,再重新生成一组新班次,数据的一致性就容易保障。另外头表字段中引入运营日期后,已经排好的计划不会因为修改当天其他线路计划而被误操作,数据隔离性更好。
4.3 车辆GPS轨迹数据存哪张表、要不要做冷热分离?
GPS轨迹数据是这个系统中增长最快的表,也是很多同学最容易处理不当的一张表。每次上报一条记录,每辆车如果按5秒上报一次,1辆车1小时就有720条记录,若接入100辆车,一天就是170多万条。直接单表存储对于毕设来说倒不至于崩,但如果数据量大了查询自然会变慢。
两个实用建议:第一,GPS明细表跟上“上报时间”这个datetime索引,所有“查某辆车某时间段”的查询都必须命中索引,不要做无谓的全表扫描。第二,支持点位的批量插入(MyBatis Plus的saveBatch或foreach批量SQL)。模拟数据时经常要一次性灌入大量轨迹点,逐条插入是典型的性能杀手,批量插入性能提升很明显。
“是否做冷热分离”在真正的生产环境中答案无疑是肯定的,热数据进入Redis,分钟级以上的历史数据落库。但在毕设阶段,位置上报并发量不大,把数据直接写入MySQL也可以接受。不过建议还是保留redis缓存实时位置的架构,一方面是展示对实时数据流的理解,另一方面答辩时“Redis如何与数据库分工”是一个很好展开的话题。
4.4 系统管理域数据设计中的常见坑
sys_user表的设计要防止“万能管理员”陷阱。不要简单把角色概念塞在user表的一个字段里,而是以user_role中间表结构来关联。菜单表sys_menu与权限表关联,前端路由的生成依赖后端返回的菜单权限树,Vue端通过指令控制按钮级别的操作权限。
在设计密码时需要考虑到的是,明文密码不仅会给人不专业的印象,还存在严重的安全风险。用BCrypt加密存储,Spring Security自带此能力,无需自己实现。密码重置逻辑可在管理界面做“重置为初始密码”,而不是直接修改数据库。
日志表建议做成两张:sys_login_log记录登录成功失败;sys_operation_log记录业务操作。操作日志的采集可以用Spring的AOP切面来实现,拦截标注了@OperationLog注解的Controller方法,自动记录操作人、操作模块、操作类型、IP等。这样一个“小甜点”功能,写起来代码不多,但能明显提升系统的完整度和工程水准。
5. 实操开发中的关键方法与避坑实录
5.1 车辆定位模拟器怎么写得自然?
真实项目里的定位数据来自车辆安装的GPS终端,但我们做开发时手里没有真实终端硬件,所以一个优秀的模拟器是开发和测试的关键。核心思路是:提前编辑好一条或几条线路的坐标点序列,模拟器的定时任务让车在这些坐标点之间“移动”。
模拟坐标数据不必每5秒都手工录入,这样工作量太大。有两个高效方法:第一,用高德地图或百度地图的API拾取器,沿线手工标记10到20个关键转向点,然后程序在相邻转向点之间做线性插值,让车辆位置平滑移动。第二,如果只想尽快跑通流程,就在线上任选十几个点存到一张excel里,由导入脚本批量写入曲线数据表,模拟器程序依次读取坐标更新上报,如此操作即可,位置是准确的,只是车会用直线“飞”过转弯处,现实中不存在这种路线。
报告频率我建议默认3到5秒一次:低于一秒车辆移动不明显画面太碎,高于十秒位置跳动明显,画面看了让人不适。模拟器可以做成一个独立的长驻线程,后台启动多个线程模拟多辆车,也可以做成一个独立的小程序进程(例如Java控制台程序),跟主业务解耦,避免调试业务接口时还要去停一个定时器。
5.2 车辆“幽灵定位”和脏数据问题
开发中常见的问题之一,是车辆明明已经停止发车,但大屏上那辆车还停在路边甚至还在缓慢移动。这就是“幽灵车”问题。原因一般是业务状态和定位数据没有联动:车辆虽然已结束今日运营,但GPS上报的线程还在跑。
合理的处理策略是,GPS上报接口先验证车辆运营状态:状态不是“运营中”时,只记录不入实时缓存,也可以逻辑上忽略上报。所有数据展示模块(大屏、乘客端、调度页)都要在SQL查询时联表判断车辆运营状态,保证展示的只是“正在运营的车辆”。代码协作时,不只是写接口的同事要清楚这一点,前端调用列表接口时也要做状态过滤,尽可能在后端一次性处理清楚,使脏数据无法穿过接口层。
另一个常见脏数据是车牌号或设备编号维度不一致:车辆表里录入的是完整车牌“京A12345”,模拟上报提交时填的却是“A12345”,造成明明有车辆,地图上却一直找不到。我的做法是在设备上报字段中直接用车辆的数据库自增ID作为关联键,模拟阶段不存在设备注册过程,这样就不容易出现关联键不一致的情况。
5.3 WebSocket连接管理实战
WebSocket是实时推送模块的常用技术手段,也是很多同学的薄弱点。后端需要做到三点——鉴别身份、管理会话、异常断开处理。
建议引入一个简单的会话管理器,用ConcurrentHashMap维护userId与WebSocketSession的映射。用户登录后建立连接时携带token,后端校验后将本次连接绑定到用户ID维度;车辆位置上报后服务端根据线路订阅关系找到所有关心该线路的用户会话,推送位置数据。会话断开时从Map中移除并关闭连接,防止内存泄漏。
一个细节:WebSocket长连接往往会被Nginx或云服务商的空闲超时机制自动断开,如果只做了浏览器端断线重连逻辑,客户端一般30秒内发起Ping包即可保活。开发时可以考虑前端每隔10秒发送心跳,后端返回pong;若连续3次心跳无响应,前端主动断开重连。这个机制能明显减少开发中“怎么数据不刷新了”的困惑。
5.4 如何高效造测试数据?
测试数据的质量直接决定演示效果。很多系统现场演示时每条线路上只有寥寥几辆车在运行,乘客端查一下“最近一班”显示距离还有几十公里,整个体验就很空。我建议准备数据时注意几点:
线路方面准备4到6条,覆盖城区、郊区、夜间线路等不同类型,每条线站点在12到20站之间,站点间距离控制在300到800米,注意设置不同差异。车辆方面每条线路配5到10辆,总车辆超过20辆为宜。驾驶员数量建议在线路配车数的1.5倍左右,保证排班能形成“轮班”的效果。最重要的,要让8到10辆车在系统演示期间持续处于“运营中”状态,并模拟其在线路上运行,打车点查询就能实时显示动态位置。
如果想让报表看起来更有分析价值,可以预先造上两周的运营历史数据。核心的做法是写一个数据生成脚本,随机产生每天的各线路班次计划执行情况:部分准点、部分延误、少数取消,落库到计划表和GPS记录表。数据不需要完全符合真实物理规律,但要看得出趋势,比如工作日晚高峰客流量明显高于白天,某条郊区线路准点率相对较低——这些“合理的随机”是报表页面演示能否出效果的分水岭。
5.5 权限控制与接口安全的几个细节
毕设虽不是真正的商用项目,但基本的安全防护必须要有。如果连“未登录调接口”都不防,答辩时几乎一定会被问到且减分。
我建议使用Spring Security结合JWT做认证。最基础的防线是接口全部要求携带token,除登录接口与乘客查询接口外,管理端接口需要相应角色权限才能访问。Swagger(springdoc-openapi)在开发联调阶段非常方便,但部署演示前要确认生产环境的Swagger访问已关闭,防止评审老师现场打开API文档页面对你进行随机接口试探,把自己未完善的接口暴露出来。
密码接口请求建议加日志脱敏:打印日志时不要把密码明文写进log文件,操作日志模块同样要隐匿敏感数据。这在“信息平台”类项目中容易被忽略,又容易在代码规范检查中被扣分,提前按规范写可以省掉返工。
6. 一次完整的“从零到演示”实操路线参考
6.1 阶段一:环境准备与项目初始化
我在开做这类项目时,第一周不会写任何业务代码,先集中精力把项目骨架和基础能力跑通。如果你的机器上还没有环境,比较推荐的组合是:JDK 1.8或JDK 17,Maven 3.6以上,Spring Boot 2.7.x或3.x,MySQL 5.7或8.0,Redis 6.x以上,前端用Vue3。
初始化工程时直接访问Spring Initializr,Group填com.example,Artifact填smart-bus,依赖勾选Spring Web、MyBatis Framework(或MyBatis Plus)、MySQL Driver、Redis、Validation、Spring Security。把工程导入Idea并配置好数据库连接后,可以先写一个HelloController确认接口跑通,再整合MyBatis Plus使其能够成功查询数据库中的用户表数据,这一步相当于把“地基”打牢了,后续的需求开发和功能调试才踏实。
6.2 阶段二:按依赖关系分轮次开发
很多同学的开发节奏是今天想做一个功能就加一个实体,这种顺序容易造成后来返工。我的建议是按照数据依赖的顺序分轮开发,遵守五轮推进法:
第一轮做系统管理:用户、角色、菜单、登录认证,把管理后台的“壳”搭起来。这个阶段不依赖公交车相关的业务表,可以完全在通用工程上先跑通认证。第二轮做基础数据:线路、站点、车辆、驾驶员、线路站点关联。先把这些资料录好,后续做调度和查询才有数据可用。第三轮做实时定位链路:包含模拟终端,实时位置接口,Redis缓存,WebSocket推送,大屏的轮播地图。有了这条链路,系统才开始“活”起来。第四轮做调度业务:班次计划生成、动态调整、状态流转、调度指令的下发和处置。第五轮做服务平台:乘客查询接口(线路、车辆位置、预计到站),公告管理,乘客反馈,以及统计报表的配合实现。
每轮做完基本都要跑到前后端联通、页面数据正常显示再进入下一轮。如果顺序反了,先把乘客端的页面设计得琳琅满目,后面接不上数据就会出现一个接一个的报错,调整成本极高。
6.3 阶段三:系统测试与性能准备
很多同学给毕设做测试就是“演示路径手动点一遍”,这其实远远不够。建议准备一份简单的测试用例表,包含功能模块、测试步骤、预期结果、实际结果、是否通过这几列,针对关键路径如“登录—创建线路—添加站点—排班—模拟上报—大屏展示—乘客端查询”走一遍全链路测试,并顺手截几张图,这些截图也是论文中“系统测试”章节的素材。
性能层面的准备工作更偏向实用:模拟器同时多开20辆车的线程批量上报接口,观察接口响应有没有变慢,如果有必要可以看看数据库连接池是否够用。乘客端的查询接口重点测“缓存命中”是否正常,连续请求同一线路时,第二次起应该走缓存不再查数据库。
测试阶段建议顺便输出一套可直接演示的已知数据快照:只保留几条线正式上线,把其它多余测试数据清除,避免展示时发现一个线路站点乱七八糟、车在楼顶运行的现象。
6.4 阶段四:论文写作与演示答辩的若干建议
论文框架上,智能公交管理系统方向的常见逻辑是“选题背景与意义 → 相关技术综述 → 系统需求分析 → 系统设计(架构+模块+数据库)→ 系统实现 → 系统测试”,其中“系统设计”和“系统实现”占了差不多一半的页数。注意论文层次感清晰,截图要精选、有代表性。有些同学的论文明明实现了不少功能,展示出来却全是零碎的页面截图,缺少从整体架构角度说明模块关系的图,实在可惜。
准备答辩演示时我提供一个常用流程供参考:用自己的账号登录,先说系统定位和模块划分(30秒)→ 展示基础数据页面(介绍各模块)→ 打开模拟器并上大屏,看车辆动态变化(现场感最强)→ 乘客端查询“下一班车距本站还有几站”(体现实时性)→ 调度中心模拟一个临时加车指令(说明业务流程)→ 展示统计报表(说明数据价值)。整条路线在4到6分钟讲完,详略得当,节奏紧凑。
针对评委老师的常见提问,需要提前准备好:为什么要用Redis?WebSocket相比轮询优势在哪?调度算法是否考虑客流约束?GPS数据存MySQL会不会有性能问题?回答时不必讲大理论,先描述自己的实现思路,然后指出“毕设当前方案在简化背景下足够支撑演示,如果后续要解决XX问题可以做XX优化”,这比强行说“高并发没问题”从容得多。
我在做这种“偏工程实践”的毕设时,最深的一个体会是:系统能不能顺利演示,往往不取决于有没有炫酷的算法,而在于那些最基础的地方有没有做扎实。车辆状态一致、数据关联正确、报错不堆栈、缓存清得干净、数据像真实运营场景,这些做好了,演示过程基本不会掉链子。至于调度的优化算法、GPS轨迹的数据挖掘,那是值得继续深入的方向,在当前阶段先把系统完整地跑起来,在跑起来之后自然知道下一步怎么走。最后提醒一句,开发过程中记得常用Git提交,做完一轮就提交一个版本,有了不小心改崩功能随时回退的底气,开发心态会稳很多。祝顺利。
