ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot+Spark西南天气数据分析与可视化系统搭建指南

SpringBoot+Spark西南天气数据分析与可视化系统搭建指南 这些年我带过不少学生做大数据方向的毕业设计看到“基于SpringBootSpark的西南天气数据的分析与应用”这个题目第一反应是这题出得挺聪明但也很容易把人带沟里。乍一看是“Java后端框架”加“大数据计算框架”的组合很多人以为要同时精通两套东西结果把大量时间耗在框架版本冲突和集群搭建上最后系统没跑起来论文也不知道写什么。实际上这个题目的本质是一条非常清晰的数据流水线把西南地区的历史天气数据拿过来用Spark做清洗和分析再用SpringBoot做成Web系统把结果可视化展示出来。题目真正想考察的不是你会不会搭集群而是你能不能把一个完整的数据链路从头到尾打通。明白这一点之后项目就没那么可怕了。这篇内容我按自己实际带项目的经验来写覆盖了数据获取、Spark分析、SpringBoot接口、可视化、部署调试、文档答辩和扩展定制。无论你是打算自己独立做还是手头已经有一份参考源码但还没吃透都可以照着这个思路去梳理自己的项目。1. 项目拆解别被“SpringBootSpark”这个组合唬住1.1 题目在问什么从标题拆出六个模块拿到这个题目后我习惯先把标题拆成可落地的功能模块。不是直接去查“SpringBoot和Spark怎么整合”而是先问这个系统到底要做成什么样标题里信息量其实很大。“西南天气数据”代表数据源和分析范围“分析与应用”代表既要出分析结果也要有实际的前后端应用“SpringBootSpark”代表技术实现路线。把这句话翻译成功能需求至少包含以下六块数据采集获取西南区域历史天气数据通常以CSV、Excel或数据库表的形式落地数据存储原始数据和分析结果都要有地方放一般用MySQL存结果用文件或数据仓库存原始数据数据清洗处理缺失值、异常值、重复记录这是整个项目最容易被忽略但最占工作量的部分统计分析用Spark实现温度、降水、风速等指标的聚合计算比如月平均气温、极端天气频次、区域降水对比后台服务用SpringBoot提供查询接口把分析结果开放给前端调用可视化展示用ECharts等图表库把结果变成折线图、热力图、地图形成演示大屏。很多毕设翻车就是因为只盯着“Spark怎么算”、“SpringBoot怎么写接口”这些点忽略了数据采集和清洗。等做到最后发现数据是一堆脏数据分析出来的图表完全没法讲只能回头补数据治理的坑。1.2 两个框架为什么“各管一段”SpringBoot和Spark在这个项目里不是竞争关系也不存在“用Spark就不用SpringBoot”的说法。它们在数据流水线上各管一段。Spark负责的是“海量数据处理”。天气数据一旦按站点、按小时、按年份展开规模很容易达到几十万甚至上百万条记录。Spark的优势在于分布式内存计算可以用DataFrame API做复杂的过滤、分组、关联而且自带MLlib机器学习库方便做气温预测等加分功能。不过Spark本身没有提供适合业务系统的Web服务能力它算完结果之后需要有人把结果组织成接口给前端调用。SpringBoot负责的是“业务应用”。它的职责是接收前端请求、查数据库、返回JSON数据以及管理用户登录、图表配置、系统参数这些业务功能。SpringBoot的优势在于生态成熟、上手快、部署简单能快速把分析结果变成一个真正可交互的系统。这就像分工Spark是工厂里的加工车间负责把原材料处理成半成品SpringBoot是展厅和前台负责把半成品包装后展示给客户。两者之间通过MySQL结果表衔接Spark算完把结果写进表SpringBoot读表出接口。理解了这个关系你就不会纠结“要不要在SpringBoot里启动Spark”这种问题了。1.3 我最终敲定的技术栈项目做完之后我给出一套比较稳妥的组合既不会太老被答辩老师吐槽也不会太新导致找不到资料层次选型说明前端Vue 3 ECharts如果不想引入太复杂的前端工程也可以直接用纯HTML Thymeleaf ECharts省去跨域问题后端SpringBoot 2.7.x稳定、资料多和JDK8/11配合最好计算引擎Spark 3.3.x支持Scala 2.12和Java 8/11DataFrame API和MLlib齐全原始数据存储CSV文件 可选HDFS本地跑就直接放文件系统有集群环境再放HDFS结果存储MySQL 5.7/8.0用于存聚合统计结果SpringBoot直接查询元数据与缓存Redis可选缓存热点图表数据也能作为加分项版本上特别提醒一句Spark的发布版本和Scala版本是绑定的比如Spark 3.3对应Scala 2.12如果用Java开发就没什么影响但Spark的Maven依赖坐标里会带scala版本号下载时要注意一致。SpringBoot的依赖管理会统一很多jar包版本尽量避开那些比较激进的版本组合否则很容易出现类冲突或方法不存在的问题。2. 天气数据从哪来公开数据源、字段规范与清洗思路2.1 数据获取的三种主流方式做这个项目数据获取通常是第一道坎。我见过不少同学在数据上耗了两周最后发现是数据源选得不对。第一种方式也是最推荐的方式从中国气象数据网获取地面气象站观测资料。这个平台提供全国大部分站点的日值数据包括气温、气压、降水、风、湿度等要素可以按省份和日期范围筛选后下载CSV文件。缺点是部分数据需要注册申请审核要等一两天优点是权威、字段规范、答辩时数据来源站得住脚。第二种方式使用公开的数据集或第三方API。比如Kaggle上有不少全球历史天气数据按城市或国家整理成表格字段很完整。国内也有一些天气数据开放接口返回JSON格式可以写个小爬虫定时拉取。这里要提醒一句爬虫接口仅用于学习研究注意频率不要太高尽量下载离线数据而不是做实时依赖避免演示当天对方服务器出问题导致系统没数据。第三种方式自己模拟生成。这个方法有些同学会质疑但作为补充方案是可行的。你可以在真实站点的数据基础上把时间维度扩展、结合气象常识生成一部分数据或者直接构造符合字段规范的测试数据用来验证分析流程和可视化效果。答辩时不能说“数据是我编的”而要强调主数据来自公开官方来源模拟数据仅用于系统功能演示。不管你用哪种方式最终最好都转成统一的CSV或Parquet格式并存到一个固定目录里。别把数据散落到一堆子文件夹中后面Spark读起来会非常麻烦。2.2 字段与数据字典设计天气数据至少要覆盖以下这些字段才能支撑起一个有深度的分析系统字段名含义示例station_id站点编号57494station_name站点名称成都温江站province省份/直辖市四川city城市成都latitude / longitude纬度 / 经度30.7, 103.8record_date日期2023-06-01temp_max / temp_min最高气温 / 最低气温32.5 / 22.1precipitation日降水量12.6humidity相对湿度68wind_speed平均风速2.3pressure平均气压1005.2设计字段时尽量把“站点编号”和“日期”作为联合唯一键因为后面去重和关联都要用到。经纬度字段虽然不参与常规聚合但如果你想画地图或者做地理距离计算它是必不可少的。2.3 用Spark做清洗的常见步骤拿到原始数据后第一步不是急着分析而是写一个清洗作业。清洗流程通常包含四个环节我分别说一下去重。同一站点同一天的数据可能重复出现用DataFrame的dropDuplicates(seq(station_id, record_date))直接干掉。缺失值处理。气温字段缺失常用的做法是该站点的前后两天均值填充如果是降水字段缺失可以用0填充或者按同月份平均值填充。关键是要在文档里写清楚“为什么选择这种策略”答辩老师通常会追问。异常值过滤。气温超出物理可能的范围比如超过50度或低于-60度说明是传感器异常需要剔除降水量小于0也是异常。这些可以直接过滤掉。格式标准化。日期统一为yyyy-MM-dd省份城市名称统一去掉字符串里的空格和不可见字符避免后面分组时出现“四川”和“四川省”这种对不上号的情况。清洗完的数据我建议存储为Parquet格式。Parquet是列式存储对后续按字段做聚合非常友好读取速度远快于CSV。你可以用一个清洗Job输出“clean_weather.parquet”后续所有分析作业都基于这份数据跑。2.4 常见数据坑有一类坑几乎每个项目都会踩多源数据的日期格式不统一。有的文件里是“20230101”有的是“2023-01-01”还有的是“2023/1/1”。最好在数据导入阶段就统一成Date类型别把清洗逻辑散落到分析代码里。另一个坑是站点编码不一致。同一个气象站点在不同来源的数据里可能分别叫“57494”和“574940”这会直接导致关联失败。我建议维护一张站点的映射表在清洗阶段就把它处理好。还有个容易忽略的问题时区。中国统一使用北京时间但如果你的数据有一部分来自国际数据集可能混入UTC时间导致日期偏了一天。处理方式很简单统一在清洗阶段指定时区并转换别等到分析阶段再发现日期对不上。3. Spark分析层怎么落地从统计指标到预测模型的递进路线3.1 第一版用Spark SQL跑聚合指标我建议第一个版本做基础聚合指标因为这是整个项目的地基。你不需要一开始就上分布式集群Spark可以先用local模式跑即SparkSession的master设置为local[*]这就够应付几十万条天气数据了。举个例子计算西南地区各省份的月平均最高气温SparkSession spark SparkSession.builder() .appName(WeatherMonthlyAnalysis) .master(local[*]) .getOrCreate(); DatasetRow weather spark.read().parquet(hdfs:///clean_weather.parquet); DatasetRow result weather .withColumn(year, year(col(record_date))) .withColumn(month, month(col(record_date))) .groupBy(province, city, year, month) .agg(avg(temp_max).as(avg_temp_max), avg(temp_min).as(avg_temp_min), sum(precipitation).as(total_precip)) .orderBy(province, city, year, month);这段代码会输出一张“城市年月”级别的汇总表。分析结果不要只停留在控制台打印我建议直接写入MySQL用JDBC连接器写一个saveToMysql操作表结构预先设计好后面SpringBoot读起来就很顺手。3.2 第二版多表关联与地理维度分析有了月度汇总之后可以增加第二个维度的分析地理和城市群对比。你可以把西南区域的主要城市当成一组热点城市比如成都、重庆、昆明、贵阳、拉萨等然后针对这些城市做季度气温对比、年降水总量排行、极端温差分布等。这些指标很直观演示效果也好。这里有一个Spark性能经验在做Join之前先把不相关的城市过滤掉或者先聚合再关联避免全量数据shuffle。比如你要关联“站点表”和“天气数据”只需要从天气数据里select出需要的字段再和站点表join最后再分组这个顺序能省很多内存。聚合结果同样写入MySQL比如design一张region_analysis_result表字段包括region_name、statistics_type、statistics_value、statistics_month。这种宽表设计能让SpringBoot查询时非常简单不需要临时算。3.3 第三版预测模型加分项如果想让项目在答辩时更有竞争力建议加一个气温预测模块。不需要做得多复杂用Spark MLlib里的线性回归就能实现一个“基于历史天气数据预测未来7天最高气温”的功能。核心思路是特征选择前一天的时序特征以及周期性编码比如把日期中的月份、季节作为特征把湿度、气压、前一天最高气温作为数值特征。训练集和测试集按时间划分计算MAE平均绝对误差和RMSE均方根误差来评估模型。代码骨架大概是VectorAssembler assembler new VectorAssembler() .setInputCols(new String[]{prev_temp_max, humidity, pressure, month}) .setOutputCol(features); LinearRegression lr new LinearRegression() .setLabelCol(temp_max) .setFeaturesCol(features); LinearRegressionModel model lr.fit(trainData);这里提醒一句天气数据是时间序列划分训练集和测试集时必须按时间切分不能随机切分否则模型会“提前看到未来”评估指标虚高。答辩时这个细节很加分说明你真的理解了模型评估的边界。如果不想引入机器学习库也可以用“历史同期平均法”做基线预测即预测某城市某日气温直接取过去五年同一天的平均气温。这个方案简单可靠、容易解释适合作为对比基准。3.4 性能与稳定性提交作业而不是在IDE里硬跑分析代码写完后我强烈建议用spark-submit来提交作业而不是在IDE里反复运行。这不是形式主义而是原因有三第一Spark作业在IDE里运行时依赖和classpath容易和项目其他部分冲突尤其当你的项目还引用了SpringBoot全家桶时很容易出现jar包混乱。第二用spark-submit提交可以明确指定executor内存、并发度等参数方便观察日志和调优。比如spark-submit --class com.example.WeatherAnalysisJob \ --master local[4] \ --driver-memory 2g \ weather-analysis.jar第三提交作业的方式更接近生产环境。答辩时老师可能会问“你的分析任务是怎么跑的”如果回答“直接在IDEA里run”多少有点站不住脚如果回答“通过spark-submit提交结果落库”明显更专业。至于集群规模我个人建议毕设项目不用刻意搭三节点集群。你可以在文档里写清楚“本系统基于Spark local模式开发可扩展至YARN集群”然后把扩展方案写出来这比硬搭一个经常起不来的集群要好得多。4. SpringBoot后端与可视化让分析结果变成能演示的系统4.1 项目分层与目录结构SpringBoot端负责把Spark的分析结果通过接口暴露给前端。不要把它和Spark耦合在一起最简单的做法是Spark作业已经写好了MySQL结果表SpringBoot只管查询展示。我常用的包结构是这样包名职责controller接收HTTP请求返回统一结果service业务逻辑调用Mapper查询数据mapper数据访问层使用MyBatis或JPAentity对应MySQL结果表的实体类config跨域配置、Redis配置、定时任务配置dto给前端用的展示对象避免直接暴露数据库实体SpringBoot和Spark的衔接有两种方式。一种是在SpringBoot启动时发现结果表为空就调用一个外部脚本启动Spark作业另一种是提供一个后台管理接口点击“重新计算”时再调spark-submit。两种方式都不复杂但能体现你对系统集成的理解。4.2 API接口怎么设计接口设计要围绕可视化页面来不要设计得太“数据库”。前端需要什么数据你就提供什么数据。我通常会设计这几个接口GET /api/weather/summary 获取总体统计如年平均气温、降水总量、极端天气次数GET /api/weather/trend?city成都year2023 获取某城市某年的气温变化趋势GET /api/weather/compare?cities成都,重庆months2023-01,2023-02 获取多城市数据对比GET /api/weather/map?indicatorprecipitationmonth7 获取地图展示所需的省级或城市级数据。返回结构做成统一的Result 包含code、message、data三个字段。比如{ code: 0, message: success, data: { city: 成都, trend: [10.2, 12.1, 16.8] } }前端拿到这种数据可以直接绑定到ECharts的series里不需要在后端做额外拼装。4.3 缓存、定时任务与并发在纯查询之外建议加两个“看起来不起眼但很重要”的功能。第一个是Redis缓存。天气分析结果在一定时间范围内是不变的比如一个月的统计不会每天变化因此可以把相同参数的查询结果缓存30分钟或1小时。这样既提高了页面响应速度也能在项目介绍里多说一条“我处理了缓存穿透和数据一致性”的经验。第二个是定时重算。使用SpringBoot自带的Scheduled注解在每天凌晨触发一次Spark重算任务把前一天的数据纳入统计。这样系统就不是“一次性分析”而是有持续更新的能力在答辩演示时可以打开定时任务日志给老师看表明系统具备自动化处理能力。4.4 前端可视化ECharts为主可视化我建议用ECharts原因很简单图表类型丰富、文档全、免费而且地图支持特别好。一个完整的演示系统通常包含三个页面综合看板用折线图展示气温趋势用柱状图展示降水总量用雷达图展示风速、湿度等多个气象要素地理分布用中国地图或西南区域地图配合散点图或地图着色展示各省市降水量、平均气温对比分析用多系列折线图对比成都、重庆、昆明等城市的温度差异。有一件事要特别注意ECharts的data格式是数组后端响应的JSON里如果带了很多额外的嵌套字段前端需要写不少转换代码。所以我会专门定义DTO让后端接口返回的字段和ECharts需要的字段保持一致前端几乎可以“零转换”直接使用。5. 打包、部署与远程调试把毕设从“能跑”变成“能演示”5.1 环境搭建的“干净版本”很多学生卡在环境上我先给一个能走通的方案。毕设不要求生产级别的集群你可以选择一台轻量云服务器2核4G性能即可在上面装JDK8、MySQL、Spark。SpringBoot打成一个fat jar跑起来Spark作业用local模式通过命令行提交两者互不干扰。如果你的机器配置不高也可以把MySQL和SpringBoot放在本地只把Spark分析放在服务器上甚至全部都用本地环境也是可以的。关键不在于部署在哪而在于你能不能在答辩现场稳定复现整个流程。我比较推荐的做法是写一个环境准备脚本和一个启动脚本把MySQL建表、Spark作业执行、SpringBoot启动串起来。老师问“你的项目怎么跑起来”时你只需要说“执行这个脚本”这比手动敲一长串命令要专业得多。5.2 打包避坑SpringBoot和Spark同时出现在一个Maven工程中时最容易踩的坑是依赖冲突。SpringBoot的starter-web会引入内嵌Tomcat和其他一堆公共库而Spark也会引入Netty、Jackson等公共库两者版本不一致时经常报ClassNotFoundException或NoSuchMethodError。解决办法是把Spark的依赖作用域设为provided也就是只在编译和测试时使用不打包进SpringBoot的fat jar。分析作业单独打包成另一个jar用spark-submit提交。这样两个jar各管各的互不干扰。简单示意dependency groupIdorg.apache.spark/groupId artifactIdspark-sql_2.12/artifactId version3.3.2/version scopeprovided/scope /dependency5.3 远程调试三板斧远程调试这个词在毕设服务里经常出现但它的本意是排查线上问题不是让别人替你把代码写完。我自己排查环境问题时最常用的三招是第一SpringBoot远程Debug。在服务器上启动jar包时加上java -agentlib:jdwptransportdt_socket,servery,suspendn,address5005 \ -jar weather-system.jar然后在IDEA里配置Remote JVM Debug连上服务器5005端口就能像本地一样打断点调试。第二日志分离。Spark作业的日志和分析日志分开文件输出SpringBoot日志单独输出。否则混淆在一起根本分不清是计算层的问题还是接口层的问题。第三用端口检测和数据库连接测试来排除基础设施问题。比如用netstat检查3306/8080端口是否被占用或者被防火墙拦截用mysql命令行直接测试远程连接。很多“代码没问题但跑不起来”的情况最后都归结到端口没开放或者账号权限不对。需要说明的是远程调试是解决环境问题的手段不是写作手段。如果你手头有一份别人给的源码最好在当地跑通后自己再重写一部分逻辑确保答辩被追问时能讲清楚每个关键类的设计思路。5.4 演示前必须自测的清单每次演示前我会让学生按下面这个清单过一遍避免现场翻车冷启动能力把MySQL重启、SpringBoot重启后系统是否能自动展示数据空数据处理如果某个月份没有数据页面会不会报错刷新稳定性连续刷新页面接口响应时间是否稳定定时任务验证手动触发一次定时重算观察日志和数据库变化数据口径可解释任选一个图表你都能说出这个数字是怎么算出来的。6. 文档、讲解答辩与个性化扩展用完整交付物拉开差距6.1 论文文档结构怎么写毕设最终交付的不只是能跑的系统还有文档。文档写作有一个原则不要堆砌概念要围绕自己的系统写“你做了什么、为什么这么做、效果如何”。我建议按这样的结构组织绪论讲清题目背景和意义明确你研究的是西南天气数据分析与可视化系统需求分析分析系统的功能需求和非功能需求最好附上用例表系统设计包括总体架构、功能模块划分、数据库设计、Spark分析算法设计系统实现按数据采集、数据清洗、分析计算、接口实现、可视化展示的顺序写每个环节附上关键代码和截图系统测试包含功能测试、性能测试、结果验证不只写“测试通过”要写具体测试用例和结论总结与展望写项目中的收获、不足和可优化方向。数据库设计部分特别要用心。把每个表的结构、字段说明、主外键关系列清楚。答辩老师很爱看这页因为它能快速反映你对整个系统数据流的理解。6.2 讲解与答辩的七个问题答辩前可以先自己练一练以下问题这些都是我在模拟答辩时最爱问的为什么用Spark而不是MapReduce或Flink可以从内存计算、SQL开发效率、MLlib生态来回答你的数据量多大得到什么结论要准备几个实际数字比如“分析了西南地区5个省份30年共80万条记录”怎么保证清洗后的数据质量要能说出缺失值、异常值、重复数据的百分比和具体处理策略如果数据量增长到100倍系统哪里会成为瓶颈可以答Spark任务的并行度、MySQL查询压力、缓存策略需要调整预测模型准确率如何为什么选这个模型不需要说很高但要给出MAE的具体数值并解释误差的可接受范围定时重算会不会和用户查询冲突答Redis缓存和事务双写如果是团队完成你怎么划分模块和整合代码这个如实回答就好。6.3 个性化定制方向“定制”这个词在毕设里很容易变成“换皮”——改个名字、换张图片就完了。但真正有价值的定制是把项目和自己的兴趣、专业方向结合。比如你想往实时方向走可以接入一个公开天气API用Spark Streaming做实时温度采集和预警你想往数据分析深度走可以加入空气质量指数AQI做气象因素和空气质量的关联分析你想往算法方向走可以把线性回归升级成时间序列模型预测更长时间的气温趋势。还有一个思路是结合特定场景比如旅游气候舒适度分析通过温度、湿度、降水数据算出各城市不同季节的舒适度指数做成推荐列表。这种定制有实际意义答辩时也更容易讲出亮点。6.4 关于“远程调试讲解定制”的正确姿势最后想说两句关于“远程调试、讲解、定制”这类服务的态度。项目可以借鉴代码可以参考但最终答辩坐在那个位置上的人是你。拿到一个项目后至少要确保自己能完成三件事能在干净环境里从零部署一遍能改掉其中至少一个核心功能而不出错能对着文档把每个模块串讲一遍。远程调试能帮你解决环境问题但你要问清“为什么这里要这样配”讲解课能帮你梳理逻辑但你要自己对着文档练习两遍定制能让你项目看起来不一样但改过的代码一定要自己理解后再交。这套流程走完这个毕设才真正成为你的东西。最后再分享一个体会我见过不少技术能力很强的学生把Spark和SpringBoot玩得很溜但答辩时讲不清楚数据从哪来、指标怎么算出来的。反而是那些肯把每个环节都弄明白的学生哪怕用的技术没那么花哨也能靠清晰的逻辑拿到不错的评价。做这种综合项目最值钱的能力就是把一条数据流水线从源头到展示讲得明明白白。这条能力比多会一个框架有用得多。
返回列表