ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

基于Spring Boot+大数据:交叉路口行人非机动车流量调查统计分析系统实现

基于Spring Boot+大数据:交叉路口行人非机动车流量调查统计分析系统实现 前不久一个学弟拿着“基于Spring Boot大数据交叉路口行人非机动车流量调查统计分析系统”这个题目来找我说自己翻遍了网上下载的代码要么版本太老跑不起来要么只有几个孤零零的Controller连统计口径都讲不清楚。这个题目乍一看像普通管理系统实际上把交通调查、大数据离线分析和Web可视化串在了一起属于典型的“名字大气、实现容易跑偏”的毕设题。我做这一类毕设辅导也有几年了今天就把这个题目的完整拆解思路、技术选型、数据库设计、核心代码写法、文档撰写和答辩准备一次性讲清楚。不管是刚拿到题目的本科生还是想给学生指导的同行都可以照着这个思路去落地。系统本身并不复杂但要想做到“能演示、能答辩、能扩展”有几个关键点必须想明白否则很容易做成一个平平无奇的增删改查。1. 拿到这个毕设选题后先搞清楚它到底要做什么1.1 系统不是简单CRUD核心是“调查统计分析”这条业务主线很多学生看到“行人非机动车流量调查统计分析系统”第一反应就是做一个物资管理系统那种套路登录、增删改查、导出Excel。这种思路最大的问题是把业务做单薄了。这个题目的业务场景其实是某个交叉路口需要调查行人、非机动车电动车、自行车在不同时间段、不同方向的通行流量为交通信号配时、路口改造、拥堵治理提供数据依据。所以系统的核心价值不是“录入一条数据”而是“能不能把一个路口的流量规律统计清楚”。换句话说评审老师看这个系统重点看两件事一是统计维度是否专业比如早高峰、晚高峰、东西方向、南北方向、行人vs非机动车二是分析结果是否有说服力比如能不能展示出“东口直行电动车在17:00-18:00达到峰值”这种结论。如果只做到“表格里能查出来几条记录”那这个系统离及格线其实还有距离。1.2 谁能用这个系统用户角色和需求边界按照毕设项目常见的功能划分系统至少需要两类用户调查员负责录入或导入某个路口的流量调查数据可能是按15分钟为一个调查时段记录各进口方向、各转向的机动车、行人、非机动车数量。管理员/分析人员负责维护路口基础信息、审核数据、生成统计分析报表看看某个路段时间维度下的流量趋势。别忘了系统还需要一个数据录入的入口。交通流量调查在实际操作中通常使用调查表纸质表格或者Excel表格记录所以系统不只要手写录入还要支持批量导入。我建议把“Excel导入”做成核心功能因为这是交通调查业务的实际习惯也是评分中容易出彩的部分。1.3 我建议的技术选型以及为什么不是越重越好标题里带“大数据”很多学生第一反应是上Hadoop、Spark结果虚拟机一跑就崩最后演示的时候还被集群环境拖垮。这里要分清毕设和工业项目的区别。我的建议是主体用Spring Boot MyBatis Plus MySQL Redis ECharts把“大数据”体现在海量数据的批量导入、离线聚合统计和可视化分析上。如果指导老师明确要求引入Hadoop生态我建议用Docker部署一个轻量的Hive或Spark环境做离线ETL和统计但业务主流程还是走MySQL避免把所有鸡蛋放在集群一个篮子里。技术栈可参考下表层次技术选型作用前端Vue 2 Element UI ECharts页面渲染、图表展示后端Spring Boot 2.7.x业务接口、权限控制ORMMyBatis Plus 3.5.x数据访问、分页查询数据库MySQL 8.0基础数据、用户数据、统计明细存储缓存Redis高频查询缓存、验证码缓存导入阿里EasyExcel流量调查Excel批量导入大数据扩展Hive/Spark可选离线大规模数据统计分析部署Docker/Docker Compose环境统一、演示稳定这套方案的好处是难度曲线平缓核心功能用Spring Boot就可以完整落地大数据部分可以单独出一个模块不影响主流程演示。对本科生来说代码量可控对答辩来说也有可讲的亮点。2. 数据模型与统计口径系统能“统计得准”的前提2.1 路口、方向、车道、时段这些基础维度怎么建模交通流量统计分析最难的不是写代码而是把业务口径落到数据库表里。如果表结构设计错了后面所有统计SQL都会别扭。我建议至少设计这几张核心表intersection路口信息表字段包括路口名称、城市、经度、纬度、备注。flow_survey流量调查批次表一次调查活动字段包括调查日期、天气、开始时间、结束时间、调查员、状态。flow_detail流量明细表单条调查记录字段包括调查批次、路口、进口方向、转向、交通方式、时间点、数量。user用户表普通字段即可。这里重点说flow_detail。业务上一个路口的每个进口方向东、南、西、北可能分左转、直行、右转调查员按15分钟或者1小时记录行人、自行车、电动车的数量。如果每种交通方式都建一列表会非常宽而且后续加一种交通方式就要改表结构。我采用行式存储CREATE TABLE flow_detail ( id BIGINT PRIMARY KEY AUTO_INCREMENT, survey_id BIGINT NOT NULL COMMENT 调查批次ID, intersection_id BIGINT NOT NULL COMMENT 路口ID, import_direction VARCHAR(10) NOT NULL COMMENT 进口方向东/南/西/北, turn_type VARCHAR(10) NOT NULL COMMENT 转向左转/直行/右转, traffic_type VARCHAR(20) NOT NULL COMMENT 交通方式行人/自行车/电动车, stat_date DATE NOT NULL COMMENT 统计日期, time_slot VARCHAR(20) NOT NULL COMMENT 时段如07:00-08:00, flow_count INT NOT NULL DEFAULT 0 COMMENT 数量, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_intersection_date (intersection_id, stat_date), KEY idx_survey (survey_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;为什么要加上time_slot字符串而不是直接用时间戳因为交通调查的时段通常是固定的比如“07:00-08:00”按字符串存储直观也方便分组统计。如果后续要按分钟级分析可以再增加一个stat_time时间字段保留time_slot做展示。2.2 流量明细数据与聚合汇总表如何配合明细表解决的是“每一笔数据从哪来”但直接对明细表做统计数据量大时会很慢。而且毕设答辩时评委可能会问“你这个系统数据量大了怎么办”所以一定要设计聚合汇总表。常见做法是设计一张flow_stat_daily按路口、日期、进口方向、交通方式、时段汇总数量。每天晚上用定时任务或者每次导入完后触发一次增量汇总把明细表的数据聚合到汇总表。查询统计报表时优先查汇总表明细表只保留原始记录用于追溯。CREATE TABLE flow_stat_daily ( id BIGINT PRIMARY KEY AUTO_INCREMENT, intersection_id BIGINT NOT NULL, stat_date DATE NOT NULL, import_direction VARCHAR(10), traffic_type VARCHAR(20), time_slot VARCHAR(20), total_count INT DEFAULT 0, update_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_intersection_stat (intersection_id, stat_date, import_direction, traffic_type, time_slot) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这样的设计有个直接好处查询某个路口一周内不同时段的行人流量时只需要扫描汇总表而不是全表扫明细演示起来非常流畅。2.3 Excel批量导入的设计思路流量调查数据如果让学生一条条去页面上输入不仅效率低而且演示时容易出错。我建议用EasyExcel做Excel批量导入。导入模板至少包含以下列日期、进口方向、转向、交通方式、时段、数量。导入逻辑要做的校验包括路口是否存在、调查批次是否存在。进口方向和转向是否在枚举范围内。数量是否为非负整数。同一批数据重复导入时是否允许覆盖。先上传Excel到临时目录再用EasyExcel的监听器逐行读取校验最后批量插入数据库。不要使用逐条INSERT那会非常慢。MyBatis Plus的saveBatch或者其他批量插入方式都可以。插入完成后触发一次该路口、该日期的数据聚合保证汇总表与明细表一致。3. Spring Boot核心业务编码从数据采集到统计分析3.1 项目初始化和依赖清单我实际搭建项目时会比较看重依赖版本的稳定性。这里给一份可以参考的pom.xml核心依赖dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency dependency groupIdcom.alibaba/groupId artifactIdeasyexcel/artifactId version3.3.2/version /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies有几点想提醒Spring Boot版本不要用太新的3.x除非你兜得住新版本里的兼容问题。2.7.x资料多踩坑少适合毕设。Redis不是必须的如果本机没装可以先去掉。但保留之后可以做一个“热门路口流量排行缓存”的加分项。EasyExcel 3.x的API和2.x有些差异网上很多旧教程是2.x注意辨别。3.2 层次化结构Controller-Service-Mapper的分层与事务代码结构建议按照常见的web项目分层com.example.traffic ├── controller // 接口层 ├── service // 业务逻辑层 ├── mapper // 数据访问层 ├── entity // 数据实体 ├── dto // 接口入参出参对象 ├── vo // 视图对象比如统计结果封装 ├── config // 配置类 ├── handler // 全局异常处理 └── utils // 工具类flow_detail的插入和汇总操作需要事务控制。比如导入Excel时如果校验通过后先插明细再更新汇总中间任何一步出错都应该回滚否则数据会出现“明细有但汇总没更新”的情况。给导入方法加上Transactional只是第一步还要注意EasyExcel的监听器是在框架内部回调的事务不一定能覆盖到所以建议把“解析并校验数据”和“批量入库”分成两步入库方法单独加事务。3.3 统计报表接口的SQL聚合写法与性能优化统计接口是整个系统的门面一定要做好。我提供一个真实场景下的SQL示例统计某路口一周内每天各时段的行人流量。SELECT stat_date, time_slot, SUM(total_count) AS total_count FROM flow_stat_daily WHERE intersection_id #{intersectionId} AND stat_date BETWEEN #{startDate} AND #{endDate} AND traffic_type 行人 GROUP BY stat_date, time_slot ORDER BY stat_date, time_slot;如果要统计某路口各方向、各交通方式占比SELECT import_direction, traffic_type, SUM(total_count) AS total_count FROM flow_stat_daily WHERE intersection_id #{intersectionId} AND stat_date #{statDate} GROUP BY import_direction, traffic_type ORDER BY import_direction, traffic_type;在MyBatis Plus中我建议直接用自定义SQL而不是全部依赖QueryWrapper。复杂的聚合查询用QueryWrapper写起来可读性差后期维护非常痛苦。接口返回结构可以设计成public class TrafficStatVO { private String name; // 分类名比如“东口行人” private ListString times; // 时段列表 private ListInteger counts; // 对应数量列表 }前端ECharts直接拿这个结构生成折线图不需要再二次加工。3.4 ECharts可视化页面与后端数据对接前端我用Vue ECharts核心页面包括路口概览展示所有路口的基础信息卡片。流量趋势选择路口、日期范围、交通方式展示按时段的折线图。方向占比展示各进口方向、各交通类型的饼图/柱状图。高峰时段分析自动计算早高峰、晚高峰时段并高亮展示。ECharts部分有一个典型坑图表的数据更新时setOption不会完全覆盖旧数据所以使用前最好先chart.clear()再setOption否则切换条件后图上会有残留。this.chart.clear(); this.chart.setOption({ tooltip: { trigger: axis }, legend: { data: this.legendNames }, xAxis: { type: category, data: this.times }, yAxis: { type: value }, series: this.seriesData });可视化页面不需要做得多花哨但一定要保证演示网络环境下能正常加载。有些学生喜欢用CDN加载ECharts结果答辩现场没网页面图表全挂。建议把ECharts和Vue的JS文件下载到本地static目录下离线也能跑。4. 大数据部分怎么落到毕业设计里离线分析与海量数据支撑4.1 “大数据”在毕设中的合理呈现方式我知道很多指导老师看到“大数据”这个词就希望系统里出现Hadoop、Spark之类的组件。但你要明白毕设评分不是看名词数量而是看你是否能解释清楚“数据量大了以后单机能扛得住吗处理不过来怎么办”所以这个题目里的“大数据”我认为可以从三个层面体现数据规模层面系统支持几十万甚至上百万条流量明细记录的导入与存储。离线统计层面基于定时任务的批量聚合或者引入Spark离线计算框架对历史数据进行ETL。可视化分析层面对大数据集做抽取、汇总后用图表呈现规律。不要一上来就搭三节点Hadoop集群因为笔记本跑虚拟机再开三台Linux内存很容易爆。我见过不少学生为了演示集群结果机器卡死最后连登录页面都进不去非常尴尬。4.2 搭建轻量级离线统计模块的可行路径如果确实希望项目中出现“大数据处理”我推荐用Spring Boot定时任务 聚合表的方式模拟离线分析再把Hive或Spark作为扩展模块单独打包。离线统计的典型流程每天凌晨2点扫描昨天的流量明细表。按路口、日期、进口方向、交通方式、时段分组聚合写入flow_stat_daily。生成“昨日流量简报”包括早高峰时间、晚高峰时间、总流量、峰值流量。将结果缓存到Redis供首页大屏直接读取。Spring Boot里可以用Scheduled实现Component Slf4j public class TrafficStatJob { Scheduled(cron 0 0 2 * * ?) public void dailyStat() { // 1. 查询昨天有数据调查的批次 // 2. 批量聚合写入汇总表 // 3. 清理缓存 } }如果老师确实要看Spark或者Hive可以写一个独立的模块用Spark SQL对HDFS上的历史CSV文件做同样的聚合。但注意这个模块可以做成一个“附加演示包”而不是主系统的必要组件。答辩时如果老师没问可以主动提“为了体现大数据处理能力我另外实现了Spark离线分析模块”如果老师追问再把Spark跑一遍。4.3 模拟数据生成器让演示不再依赖“手造数据”做实操的时候我发现很多学生只能手动录几十条数据图表根本看不出趋势。交通调查数据的特点是周期性强早高峰7:30-9:00晚高峰17:30-19:00行人流量明显大于自行车电动车在非机动车中占比最高。建议写一个模拟数据生成器一键生成一个月甚至三个月的路口流量数据导入系统后再做统计分析图表会非常饱满。模拟生成器可以用一个简单的Java类实现Random random new Random(); String[] directions {东, 南, 西, 北}; String[] turns {左转, 直行, 右转}; String[] types {行人, 自行车, 电动车}; for (int day 0; day 30; day) { for (String timeSlot : timeSlots) { int baseCount isPeak(timeSlot) ? 150 : 40; for (String direction : directions) { // 生成一条符合业务特征的模拟记录 } } }生成器不只是随机数最好加入“高峰加大、平峰减少、夜间极低”的逻辑同时给不同方向设置一定差异比如主干道东口流量高于西口这样画出来的图表才像一个真实路口。4.4 大数据量下的导入与查询优化如果模拟数据生成30万条再走EasyExcel导入就会出现性能问题。这里有几个优化点监听器里不逐条insert而是累积到一定数量比如1000条后批量插入。关闭MySQL的自动提交导入完成后统一提交。大数量查询时优先查flow_stat_daily汇总表不要查明细。为常用查询条件建联合索引比如(intersection_id, stat_date, traffic_type)。我实测过一个3个月、约50万条记录的模拟数据集导入时间在30秒左右统计图表查询基本秒开。这个表现拿去答辩完全说得过去。5. 文档撰写和答辩准备的实操经验5.1 开题报告和任务书把“创新点”写清楚但不夸大很多学生写开题报告时喜欢堆砌“基于大数据技术的XXX系统”这种空话答辩老师一看就知道没想清楚。我建议在开题报告里把创新点落到三处一是“多维度交叉统计”系统同时支持路口、方向、转向、交通方式、时段五个维度组合分析二是“大数据离线聚合设计”数据明细与统计汇总分离用定时任务支撑大流量数据的统计分析三是“可视化调查分析”通过ECharts直观展示高峰时段、方向占比和流量趋势。这三个点都是系统里真实存在的答辩时能讲清楚实现原理就不怕追问。5.2 论文/说明书章节结构不要照抄网上千篇一律的模板我不知道大家注意到没有很多毕设论文的目录一眼看去就是“可行性分析、需求分析、系统设计、系统实现、系统测试”老师看了几年早就腻了。你可以按照系统实际内容调整章节比如第2章写“交叉路口行人非机动车流量调查的业务需求与统计口径”第3章写“流量数据模型设计与离线聚合策略”第4章写“基于Spring Boot的统计分析接口实现”第5章写“可视化分析与系统测试”这样做的好处是论文每一章都对应系统的实际问题而不是空谈理论。5.3 答辩演示二十分钟内让评委记住你的系统答辩时间通常有限不要把时间浪费在登录页面的演示上。我建议按这个顺序演示用一分钟讲清楚系统要解决的问题路口流量调查数据散落、统计困难。展示核心数据用模拟生成器提前准备好数据图表一定要饱满。演示重点功能按时段统计、按方向统计、高峰识别、Excel导入。留两分钟讲“大数据扩展”离线Aggregation任务、Spark模块。有一个答辩现场最容易翻车的是切换页面图表加载不出来。所以答辩前一定要断网测试一遍所有页面确保离线可用。6. 定制与扩展如果指导老师临时要求改需求怎么接得住6.1 常见需求变化增加机动车、地图展示、PDF报告毕设定制中最常遇到的需求变动有几种在交通方式中增加“机动车”这需要改枚举和统计维度数据库表不用大动。要求展示路口地理位置可以引入高德地图JS API在路口的经纬度字段基础上渲染地图标记。要求生成调查分析报告可以用POI或者iText生成PDF把统计图表嵌入文档。以“增加机动车”为例改动点集中在前端下拉选项加一项、后端枚举加一个值、统计SQL的traffic_type字段筛选条件自然兼容工作量不大。6.2 部署上线需要注意的环境问题系统开发完成后如果要在机房或者老师的服务器上部署一定注意以下问题确认JDK版本和Spring Boot兼容不要出现本机Java 17、服务器Java 8的情况。MySQL数据库字符集设置为utf8mb4否则导入中文会乱码。端口占用要在启动前检查Spring Boot默认8080端口经常被占用。Redis如果没装可以先禁用相关配置避免项目启动报错。Docker部署时注意容器间的网络连接MySQL容器和Spring Boot容器要放在同一个自定义网络里。我见过最离谱的一个案例是学生本地跑得好好的部署到老师机器上就是登录不进去最后发现是数据库密码配置文件用的本地密码环境变量没有替换。所以部署前检查配置文件的敏感项是个好习惯。6.3 一些容易踩的坑和最后的收尾建议最后分享几个实际操作中比较容易踩的坑第一时间字段要统一。数据库用DATE页面传输用字符串时要指定格式否则Java的LocalDate和前端字符串对不上容易出现JSON parse error。第二统计SQL里的SUM要注意空值。如果某一天某时段没有数据SUM结果是NULL前端ECharts会显示异常建议用IFNULL(SUM(total_count), 0)。第三不要为了展示大数据而把Hadoop环境装到开发机里。我建议大家用Docker Compose管理大数据组件用完之后随时可以停掉不影响Spring Boot主程序。第四代码一定要定期提交到Git仓库哪怕只是本地仓库。毕业设计周期长中间容易改来改去没有版本管理的话一个不小心改崩了很难恢复。这些经验是我多次带毕设项目总结出来的。这个题目说难不算难说容易也不算容易关键是把“交通调查业务”和“统计分析”这条主线把握好技术栈只要稳定能用即可。如果你正在做这个题目先花两天把表结构和统计口径定清楚再动手写代码后面会顺畅很多。
返回列表