基于SSM+Vue的天气查询毕设:从选题架构到部署上线的完整实战

发布时间:2026/10/20 9:57:25

基于SSM+Vue的天气查询毕设:从选题架构到部署上线的完整实战 又一个毕设季后台经常有人问我“不想做商城系统也不想做博客了有没有一个题目既不像玩具、又不会把自己写崩”我的回答通常是同一个天气查询。别小看这个小题目它几乎没有支付、权限、并发这些“毕设杀手”却能把需求分析、前后端分离、接口设计、数据库建表、部署上线切成一条完整的链路。这篇文章就以一套基于SSM加Vue的简单天气查询App为例完整复盘毕设从选题、架构、编码、论文到打包交付的全过程。不管你现在是临时换题还是想把项目做得更稳这套思路都能直接用。1. 毕设选题为什么要选“天气查询”一个被低估的稳妥型题目1.1 为什么它比商城、外卖项目“抗造”很多同学对毕设难度的判断是“功能越多越好”于是选了商城、外卖、校园二手交易结果做到后期才发现支付接口需要资质、地图定位需要权限、消息通知需要WebSocket这些复杂点任何一个都可能把进度卡死。而天气查询的系统边界非常清晰核心需求就是“用户查天气、看预报、保存常用城市”。它不依赖复杂硬件不需要第三方支付的审核流程数据源也能通过网络接口稳定获得所以从工作量上更容易收口。更重要的是这种“看似简单”的题恰恰考察你做完整项目的工程能力你同样要设计数据库、写接口、处理前端交互、做异常兜底一个完整软件开发流程的每一步都不会缺席。换句话说它把技术栈里最难应付的“变量”全部剔掉只留下最基础、最核心、也最能体现学习成果的东西。1.2 SSM和Vue的搭配真的“过时”了吗目前的教学环境里SSM仍然是很多学校课程设计的默认技术栈Spring负责管理对象SpringMVC负责接收请求MyBatis负责操作数据库三者配合多年资料极多。Vue则用来构建页面页面通过JSON和后端通信。两者组合就是典型的前后端分离结构前端一个工程后端一个工程部署时前端静态文件可以丢进Nginx后端war包丢进Tomcat。技术方案优点缺点适合的场景传统JSP资料最多页面直出简单前后端耦合维护性差老项目改造教学示例SSM JSP后端分层清晰页面开发快接口复用差前端表现力受限单机版课设不强调前后端分离SSM Vue前后端分离交互体验好结构清晰前后端要联调部署多一步毕设首选答辩能讲出完整分层Spring Boot Vue配置简化启动快社区主流如果学校平时不教答辩容易被追问有Spring Boot基础的同学闭设答辩里老师通常最熟悉的还是SSM这套你讲得出“Controller调ServiceService调Mapper”这条链路他基本就不会深追。Spring Boot固然新但对基础一般的同学来说配置越简单反而越难解释底层原理。1.3 什么样的学生适合这个题目这个题不是“高手专用”反而适合三类人第一类是基础一般、只想完整走通一个项目流程的第二类是系统设计能力偏弱、需要题目自带清晰业务逻辑的第三类是担心答辩被追问底层、希望每个知识点都在自己能力范围内的。当然它也有短板没有算法亮点、没有高并发话题。所以论文里必须把“设计过程”写厚把“实现细节”写具体用工程完整度去弥补技术深度。这一点后面论文部分会详细展开。2. 系统架构与数据链路从Vue页面到第三方天气数据源2.1 一条查询请求到底经过了哪些环节先理清整体数据流用户在Vue页面输入城市名前端把请求发给自己的后端服务后端做参数校验查一下数据库里有没有这个城市然后带着自己配置的天气服务凭证去请求第三方天气数据服务商拿到JSON后把需要用到的字段解析出来再组合成统一的结构返回给页面同时后端会把这次查询记录写入历史表方便后续做“最近查询”功能。这条链路看起来长但每一段都是为了解决一个具体问题。前端只负责展示和交互不直接接触外部数据源后端负责业务处理和外部通信数据库负责用户、收藏、历史的持久化。划分清晰之后论文里的架构图能画答辩能讲写代码也不会东西一团浆糊。2.2 为什么天气数据必须由“后端代理”获取而不是前端直连有的同学图省事把天气服务商的接口地址直接写在Vue的代码里用浏览器去请求。这在毕设demo里能跑但答辩要问起来往往答不上来第一凭证会在前端源码里暴露这是安全隐患第二很多天气接口有访问频率限制页面一刷新就可能把免费额度刷爆第三跨域问题会让联调变得很痛苦。所以正确做法是后端包一层代理接口前端只调自己的后端地址由后端去和外部天气服务打交道。这样做还有一个额外好处你可以在Service层做缓存、做降级论文里能多写一整节“健壮性设计”。这块内容虽然简单却是区分“会调接口”和“会做系统”的关键分水岭。2.3 数据库表结构小项目也要有四张表天气查询看起来不涉及业务但我还是设计了四张核心表既满足功能又让ER图有东西可画用户表t_user用户id、用户名、密码、创建时间。城市表t_city城市id、城市名、省份、经度、纬度。收藏表t_favorite收藏id、用户id、城市id、创建时间、是否为默认城市。查询记录表t_history记录id、用户id、城市名、天气现象、温度、湿度、查询时间。CREATE TABLE t_user ( id INT NOT NULL AUTO_INCREMENT, username VARCHAR(50) NOT NULL, password VARCHAR(100) NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_city ( id INT NOT NULL AUTO_INCREMENT, city_name VARCHAR(50) NOT NULL, province VARCHAR(50) DEFAULT NULL, longitude DECIMAL(10, 6) DEFAULT NULL, latitude DECIMAL(10, 6) DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_favorite ( id INT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, city_id INT NOT NULL, is_default TINYINT(1) DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_history ( id INT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, city_name VARCHAR(50) NOT NULL, weather_text VARCHAR(50) DEFAULT NULL, temperature VARCHAR(10) DEFAULT NULL, humidity VARCHAR(10) DEFAULT NULL, query_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;为什么用四张表而不是一张大表因为每张表都有独立存在意义用户表是所有系统的基础城市表是为了统一城市名避免用户输入“北京”和“北京市”造成重复收藏表支撑常用城市列表历史表支撑首页的“最近查询”。答辩时被问“为什么要这张表”就有话可说。3. 后端SSM骨架搭建Controller、Service、Mapper三层怎么分3.1 后端工程目录与依赖清单后端是Maven工程包结构可以这样分controller、service、mapper、entity再加一个config包放跨域配置和自定义拦截器。依赖上spring-webmvc、mybatis、mybatis-spring、druid连接池、mysql-connector-java、httpclient、JSON解析库这些基本够用。这里特别提醒SSM工程里调用外部天气接口时很多人会漏掉HTTP客户端的依赖导致后端代理接口一直报“找不到类”。如果你觉得原生的HttpClient API太啰嗦可以再把请求封装到一个单独的WeatherApiClient类里所有外部调用都走这一个入口后面统一加缓存、加超时也比较方便。3.2 Controller的URL该怎么规划接口设计遵循一个约定/api/weather/now、/api/weather/daily、/api/weather/history、/api/city/search、/api/user/login、/api/user/register、/api/fav/add、/api/fav/list。用REST风格语义清楚前端联调时一眼能看出每个接口是干什么的。RestController RequestMapping(/api/weather) public class WeatherController { Resource private WeatherService weatherService; GetMapping(/now) public Result getNowWeather(RequestParam String city) { return Result.ok(weatherService.getNowWeather(city)); } GetMapping(/daily) public Result getDailyWeather(RequestParam String city) { return Result.ok(weatherService.getDailyWeather(city)); } }别在Controller里写业务它只负责参数接收和结果包装。所有查询逻辑放在Service层数据库访问放在Mapper层答辩被问到分层时才能讲清楚。Result是一个统一返回结构包含code、message、data三个字段前端所有请求都按这个格式解析。3.3 第三方天气接口对接的JSON解析Service层里写一个WeatherApiClient用HTTP客户端GET请求带上城市参数和凭证拿到JSON字符串后用JSON库解析。这里要特别注意不同天气服务商的字段名不一样有的叫condition有的叫text有的温度字段是字符串有的是数字。所以不要在Service里到处散落解析代码而是统一封装成自己的WeatherDetail实体类。天气接口返回的结构通常是这样的{ code: 200, updateTime: 2025-05-11T16:35:0008:00, now: { temp: 24, feelsLike: 25, text: 多云, windDir: 东南风, windScale: 2, humidity: 60 }, daily: [ { date: 2025-05-11, tempMax: 27, tempMin: 18, text: 多云 } ] }解析后只挑前端真正需要的字段返回别把外部接口的原始JSON一股脑丢给前端那样既不安全也会让页面字段乱掉。这一步对毕设来说就是“自定义DTO”的应用论文里可以专门写一小节说明为什么要做字段裁剪和结构统一。3.4 收藏和历史记录怎么用事务保证一致性有一个容易出错的点收藏操作需要验证用户是否存在、城市是否存在然后插入收藏表。如果验证通过后插入时服务出问题用户侧体验就是“点了收藏但没存住”所以Service方法上要加事务注解保证要么全成功、要么全回滚。但历史记录插入就不一样它发生在天气查询成功之后不应该因为插入历史失败导致天气数据返回失败所以这个操作不需要做成强事务用try-catch包住失败时写日志即可。两者区别在于什么时候必须保证一致性什么时候可以容忍局部失败。答辩时如果能说清这一点比单纯背“事务隔离级别”的概念要加分很多。4. Vue前端的页面落地与跨域联调细节4.1 Vue2、Vue3与UI库怎么选毕设环境里Vue2加Element UI的教程存量最大遇到问题几乎都能搜到适合求稳。如果学校要求较新用Vue3加Element Plus也行但要注意部分组件API有差异。整套页面复杂度不高无外乎布局、输入框、按钮、卡片、列表所以完全没必要引入重型组件库。前端工程目录建议按组件拆分Header、SearchBar、WeatherCard、ForecastList、HistoryList。每个组件只管一块内容代码量小调试方便论文里也好截图说明。4.2 首页天气展示与城市切换的实现逻辑核心页面做的事情顶部输入城市名点搜索后调用后端接口拿到WeatherDetail渲染到卡片上。城市切换有两种做法一种是在输入框里重新搜索另一种是点击收藏列表里的城市直接触发查询。两种方式都调用同一个fetchWeather方法。async fetchWeather(city) { this.loading true try { const { data } await this.$http.get(/api/weather/now, { params: { city } }) this.weather data.data } catch (e) { this.$message.error(查询失败请稍后重试) } finally { this.loading false } }注意这里通过后端代理调用前端代码里没有任何外部服务商地址和凭证和前面说的“后端代理”设计是呼应的。搜索按钮加一个空值校验城市为空时直接提示避免无效请求把后端日志塞满。4.3 七日预报与生活指数的页面组织七日预报用卡片列表平铺生活指数穿衣、洗车、紫外线占用一行图标加文字展示即可。这些数据在后端Service里已经统一成自己的结构前端只需要遍历渲染。页面不复杂但要注意空数据状态城市名输错、第三方服务商返回异常前端必须渲染“暂无数据”而不是白屏。建议在页面加载时默认查询一个常用城市比如首页进入就显示当前城市天气这样演示效果比空页面好很多。也可以让页面记住上次查询的城市用localStorage存起来用户刷新后自动加载上次的城市天气。4.4 跨域配置与Axios封装前端开发时最容易卡住的是跨域。我用Vue CLI自带的devServer代理在vue.config.js中配置module.exports { devServer: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } }这样前端请求/api/weather/now会由Node开发服务器自动转发到后端地址本地联调不需要在后端单独开CORS。但打包部署后如果前后端分属两个端口还要在后端全局配置跨域拦截器。很多同学本地能跑、部署后却不显示数据多半就是漏了这一步。Axios封装时统一处理后端返回的code字段比如code不是200就弹提示并抛错避免每个页面重复写一堆判断逻辑。拦截器里还可以统一追加token到请求头登录模块和收藏模块都会用到。5. 论文撰写顺序与答辩常见的“重系统、轻设计”问题5.1 论文的章节应该怎么排毕设论文一般七到八章顺序大致是摘要、绪论、关键技术、需求分析、系统设计、系统实现、系统测试、总结展望。天气项目的特点是每个章节都有实在内容可写不会出现“设计章全是代码粘贴”的情况。比如行列“关键技术”一章可以只讲SSM三层架构、Vue组件化、HTTP接口交互和JSON数据结构“系统设计”一章有架构图、ER图、每张表的字段说明“系统实现”一章按模块拆登录注册、搜索天气、收藏列表、历史记录各写一小节“系统测试”一章放功能测试用例表。整个论文的逻辑就是从需求到设计再到实现测试层层递进。5.2 代码和论文到底谁先写我建议代码先行但要做到“边开发边截图”。每完成一个功能模块立刻把界面截图、接口返回结果、测试日志保存好同时记录遇到的问题和解决方法。这些素材最后会变成论文第六章的界面图和测试数据。如果先写论文再补功能就会出现论文里的截图和当前系统界面不一致的情况。答辩时老师现场看一眼页面再翻一翻论文两张图对不上印象分会大打折扣。反过来如果代码先跑通论文只是把已经发生的内容记录下来整个过程会顺畅很多。5.3 图表规范与“只贴代码”的误区论文中不要贴Tomcat控制台的乱码截图也不要截一堆“程序运行成功”的证明图。真正有用的是三类图系统架构图、数据库ER图、核心模块界面截图。表格则主要是“功能测试用例表”比如输入城市名、预期结果、实际结果、是否通过。这张表越完整越能体现测试思维和工程习惯。所有图表要编号、加标题、在正文中要有文字引用比如“如图5-1所示”而不是孤零零放一张图在文档里。答辩老师翻到第六章时通常会先看图再看文字图如果是自己画的、能说清来龙去脉就是很大的加分项。5.4 答辩时最怕被问的五个问题问题方向建议回答思路第三方天气接口挂了你怎么办后端会做简单缓存接口异常时提示用户稍后再试而不是直接崩溃密码为什么不存明文表示在设计时考虑过安全问题用加盐哈希处理并说明选型原因查询历史表数据越来越多怎么办分页查询或只展示最近20条SQL里加上LIMIT必要时做定期清理前端请求报错怎么排查先看浏览器Network面板再看后端日志逐步定位是前端参数还是后端逻辑问题为什么不直接用Spring Boot结合学校课程安排强调SSM分层更明显、对底层原理理解更深入但表示自己也了解Spring Boot的便利性每个问题不需要长篇大论关键是能把自己的设计思路讲清楚。模板背熟没用因为老师会根据你的项目问细节只有真的动手写过、踩过坑才能答得自然。6. 从调试到打包交付前最容易翻车的几个小地方6.1 接口凭证千万别写死在页面里第三方的天气服务凭证要放在后端配置文件里并且区分开发环境和生产环境比如用两个配置文件或者占位符切换。这样即使代码交给别人也能避免密钥泄漏。天气服务商的免费额度通常有限调试时建议在Service层加一个简单缓存一分钟内同样城市不重复请求外部接口直接返回缓存数据。这个缓存用HashMap加过期时间就够用没必要为一个小场景上Redis徒增复杂度。6.2 数据库初始化脚本要能一键执行毕设验收时最尴尬的场景是老师说“现场跑一下”你却说“要先把数据库手动导一下”。正确做法是准备一个init.sql包含建库、建表、插入常用城市和测试用户。脚本必须自包含、可重复执行建表和删表之间用IF EXISTS兜底。现场只要执行一条命令就能把环境拉起来这种细节会让答辩印象分高一大截。6.3 前端打包后的部署路径问题Vue打包默认资源路径相对路径但放在Tomcat下如果部署在子级路径偶尔会碰到静态资源404。稳妥做法是把前端打包后的dist目录放到Tomcat的webapps/ROOT下后端war包部署到同一个Tomcat前端请求同一域名的/api等于规避了大部分跨域问题。如果后端在8080端口、前端在9090端口又不想配Nginx就一定要在后端加CORS配置。这两种部署方式我都试过后者在答辩现场会因为浏览器安全策略带来很多不确定性能选前者就尽量选前者。6.4 交付前按这个清单走一遍后端war包能独立启动不依赖IDE。前端dist页面能正常打开浏览器控制台无报错。init.sql可重复执行测试账号可登录。天气接口能正常返回城市名输入“北京”和“北京市”都能查到。论文里的截图与当前系统界面一致。答辩PPT控制在15分钟以内重点是架构图、ER图、核心界面和测试表。准备一份300字以内的项目介绍应对老师开场“你这个项目做了什么”的提问。我个人在操作中的体会是这套题目最大的价值不是“写完了”而是把它当成一次完整的工程演练。你会在联调时发现接口字段对不上在打包时发现路径不对在答辩前发现论文截图和当前页面不一样这些坑都是真实项目里每天都在发生的。项目本身可以简单但流程不能简化天气查询App这份毕设最大的加分项是让老师看到一个学生从头到尾完整做事、遇到问题能自己解决的过程。最后再分享一个习惯在项目根目录放一个README.md把启动步骤、测试账号、接口文档、常见报错都写清楚。这不光帮自己备答辩也是代码交付的基本素养。天气查询看起来是个小题目但只要把这条完整的链路走通你收获的远远不止一份毕设。
延伸阅读

更多相关文章

2026/10/20 9:52:24

Android USB串口打印热敏小票的底层通信与ESC/POS实战

1. 这不是“接个打印机”那么简单:Android USB串口打印的本质挑战很多人看到“Android USB串口打印结账单小票”这个标题,第一反应是:“不就是连个热敏打印机,发几行文本过去吗?网上一搜全是教程。”我最初也是这么想的…

2026/10/20 9:52:24

Paperzz工作流:从读文献到写综述的完整指南

每次答辩季,都有学弟学妹拿着本科文献综述来找我,第一句话永远是:老师只说要梳理文献,我读了二十多篇却不知道怎么写。这个问题我听了太多年。学术小白做文献综述写作,最容易踩的坑就是把时间全花在下载论文上&#xf…

2026/10/20 11:03:17

YOLO11结合HAFB-1实现五种羊品种自动识别与边缘部署

从去年底开始,我一直在做牧业场景下的视觉识别项目,其中最有意思也最折磨人的就是“把不同品种的羊自动分出来”。我们项目组代号为“基于YOLO11-HAFB-1的五种羊品种分类识别系统”,这个系统不是简单套一个目标检测模型完事,而是把…

2026/10/20 11:03:17

springboot宜宾旅游网站08225-计算机课程设计、毕业设计

前言 ✨ 博主介绍:一线全栈工程师,毕设实战引路人。技术栈覆盖Java、Python、C#、PHP、Node.js及UniApp跨端开发,擅长多语言项目落地与架构设计。持续分享毕设源码、开题报告、技术选型心得与职场踩坑经验。用工程化思维写代码,帮…

2026/10/20 11:03:17

长对话记忆压缩实战:三层架构解决大模型上下文窗口限制

1. 项目背景与痛点拆解1.1 为什么长对话场景必须解决记忆问题用过大模型产品的朋友应该都有同感:聊天窗口一旦拉长,模型就“开始失忆”。前十分钟还在讨论需求细节,二十分钟后你再提同一个事情,它要么含糊其辞,要么直接…

2026/10/20 11:03:17

PyQt+QML 实现个性化消息通知栏源码分享

PyQtQML 实现个性化消息通知栏源码分享一、效果展示二、源码分享1、工程结构2、库安装3、main.py4、main.qml三、实现原理1、整体架构2、数据模型设计3、消息类型与配色映射4、Canvas 绘制箭头丝带5、倒计时与自动移除机制6、交互逻辑7、小结一、效果展示 二、源码分享 1、工程…

2026/10/20 11:03:17

声纹识别Web身份认证实战:从MFCC特征提取到前后端落地

简介:基于声纹识别的Web身份认证系统,面向需要为企业或业务系统提供安全、便捷登录方案的技术人员,也适合信息安全、人工智能方向的学生作为课设参考。方案以人声生物特征代替传统口令,用户无需记忆复杂密码,且不涉及人…

2026/10/20 10:58:07

2026排课调课在教培系统后台怎么设置

排课是教培机构教务最头疼的事。老师时间冲突、教室被占、班级学员时间对不上,Excel拉来拉去还是撞课。2026年了,后台排课系统能按空闲智能排课、自动检测冲突,调课在课节里改、靠排课和上课提醒触达家长,这篇讲清楚怎么在后台把排…

2026/10/19 18:06:35

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/20 1:05:37

单片机C运行时从启动到多任务:中断安全与共享资源冲突

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:05:37

GCC编译四步详解:预处理、编译、汇编、链接实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:05:37

FIW线是什么?FEP注塑线与普通氟塑料线的区别及应用指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑