发布时间:2026/9/2 19:51:13
基于Spring Boot+Thymeleaf+AI的智能天气出行系统设计与实现 毕业设计选型时很多同学会陷入两个极端要么做一个“增删改查”的管理系统答辩时被老师一句话问住要么把选题吹得很大结果开发两周发现根本做不完最后只能临时砍功能。今天要拆解的这套“基于 Spring Boot Thymeleaf AI 的智能天气出行服务系统”正好踩在了一个比较稳的平衡点上技术栈主流、功能贴近真实场景、有 AI 大模型做亮点、而且工作量可控。它不是那种只做 CRUD 的“空壳系统”也不是动辄分布式微服务的“毕设重灾区”而是用一套经典 JavaWeb 技术栈把一个真实需求做深做透。这篇文章会从选题判断、功能拆解、核心原理、环境搭建、代码实现、运行验证、排错思路到答辩加分点完整讲清楚这套系统应该怎么做、以及做的时候最容易踩哪些坑。如果你正在准备计算机毕业设计或者想用 Spring Boot 练手一个完整项目这篇文章值得先收藏。1. 这份毕设到底在做什么为什么值得选很多同学看到“智能天气出行服务系统”这个名字脑子里会冒出一堆疑问这不就是一个查天气的网站吗加上 AI 大模型就智能了这里要先把概念掰清楚。传统天气网站的核心逻辑是用户输入城市系统调用天气接口返回温度、风力、空气质量。这个流程本质上是单向查询系统只是天气数据的“搬运工”。而这一套系统的设计逻辑是把天气数据变成出行决策的输入。它至少往前走了三步天气数据接入层获取实时天气、未来预报、空气质量、生活指数出行场景映射层把天气数据映射到出行场景比如下雨天提醒带伞、高温天建议减少户外活动、空气质量差时推荐室内目的地AI 对话与推荐层用户可以直接用自然语言提问比如“明天适合去爬山吗”系统会结合天气数据和出行常识生成一条可读性强的出行建议。通过这三层的组合系统从“天气展示工具”变成了“出行决策助手”。从毕设角度来说这个选题有三重价值第一技术栈主流且覆盖面广。Spring Boot 是 Java 后端的事实标准Thymeleaf 是服务端渲染的代表方案MySQL 是关系型数据库的必选项再叠加 AI 大模型接口调用几乎把大学四年 Java 方向的核心课程都串起来了。第二AI 大模型属于当前热点。在答辩现场“如何接入大模型”“大模型返回的结果怎么处理”“AI 在什么环节起作用”这些问题天然比“查询语句怎么写”更能展示你的工程能力和对新技术的理解。第三工作量适中可拆分。即使 AI 部分遇到困难系统仍然可以靠天气接口 基础出行推荐独立运转AI 是增强而不是全部。这种“核心功能完整、亮点功能独立”的架构对毕设来说非常安全。选题判断一句话这是一个典型的“工具价值明确 技术热点加持 实现风险可控”的毕业设计选题。2. 系统功能模块与技术架构拆解2.1 用户侧功能模块从使用者视角系统分成四个主要功能块用户管理模块注册、登录、个人信息维护。毕设系统建议使用 Spring Security 或简单的拦截器实现权限控制不需要做复杂的 OAuth2 第三方登录把时间留给核心功能。天气查询模块按城市查询实时天气按日期查看多日预报展示温度、湿度、风力、风向、天气现象、空气质量等基础维度。出行建议模块根据当前天气和预报数据生成适合出行的时段和建议。比如“早晨有雨建议推迟到 10 点后出行”“紫外线较强外出请注意防晒”。这个模块可以基于规则实现比如 if 温度大于 35 度则提示防暑这样即使不接入大模型系统也能正常工作。AI 智能问答模块用户输入自然语言问题系统调用大模型接口把问题、天气上下文和系统提示词组装后发送给 AI再把返回结果解析后展示给用户。2.2 管理员侧功能模块管理员功能是毕设评分中的“完整度”加分项通常包含用户列表与状态管理启用、禁用日志管理用户操作日志、AI 调用日志数据统计每日访问量、天气查询次数、AI 问答次数。日志模块容易被忽视但对毕设答辩很加分。它展示了你的系统有“可观测”意识而不是一堆接口的堆积。2.3 系统总体架构浏览器页面Thymeleaf 模板渲染 ↓ Spring Boot 控制层Controller ↓ 业务服务层Service ↓ ↓ ↓ 天气数据服务 出行建议服务 AI 对话服务 ↓ ↓ ↓ 天气 API 规则引擎 大模型 API ↓ ↓ ↓ MySQL 数据库 Redis 缓存可选这个架构的关键设计是把天气数据访问、出行建议、AI 对话拆成三个独立服务。这样各模块之间不互相拖累测试的时候也可以单独验证。2.4 技术栈选型明细技术组件作用说明Spring Boot后端主框架版本以实际项目为准Thymeleaf服务端模板引擎直接渲染 HTML 页面MySQL关系型数据库存储用户、日志、收藏等数据MyBatis / Spring Data JPA数据访问层根据熟悉程度二选一天气 API天气数据来源选择稳定、文档清晰的公共服务接口大模型 APIAI 回复能力接入国内主流大模型服务商提供的接口Maven依赖管理Java 项目的标配Bootstrap / Layui前端样式框架不需要手写复杂 CSS3. 核心概念Spring Boot 与 Thymeleaf 是怎么配合的不少同学对“前后端分离”和“服务端渲染”两个概念分不清楚这里先把基础原理讲透。Spring Boot 是一个帮助你快速构建 Java Web 应用的框架。它解决的痛点是传统 JavaWeb 项目需要写大量 XML 配置、为每一个组件手动装配依赖。Spring Boot 通过“约定大于配置”和“自动装配”机制把 90% 的样板配置消除了。你只需要在 pom.xml 中引入依赖在 application.yml 中写少量配置就能启动一个可运行的 Web 服务。Thymeleaf 是一种服务端模板引擎。它的工作方式是浏览器请求一个 URL后端 Controller 处理请求把需要展示的数据放进 Model 对象然后由 Thymeleaf 把数据“填充”到 HTML 模板中最终生成完整的 HTML 页面返回给浏览器。整个过程发生在服务器端浏览器拿到的就是最终页面。用一句话区分前后端分离后端只返回 JSON 数据前端用 Vue/React 渲染页面服务端渲染Thymeleaf后端直接生成 HTML浏览器拿来就显示。对于毕业设计来说Thymeleaf 最大的优势是开发链路短。你不用单独启动一个前端工程也没有跨域问题写完一个 Controller 加一个 HTML 模板就是一个完整功能。如果你是一个人完成整个系统这种开发效率非常重要。放在这个天气出行系统里流程是这样的用户访问 /weather?city北京 → WeatherController 接收请求 → WeatherService 调用天气API拿到数据 → 把数据放入 Model → 返回 weather.html → Thymeleaf 渲染出包含天气信息的完整页面 → 浏览器展示这个流程就是“服务端渲染”的典型范式。4. 为什么这个系统要引入 AI 大模型AI 大模型在毕设里很容易变成“花瓶”接一个接口问一句答一句看起来很高端实际上和系统本身的业务没有关系。一个真正合理的 AI 接入方式是把 AI 放在**“天气数据解读”和“出行决策辅助”**的位置上。举个具体例子用户提问“周末想去公园走走建议安排在哪一天”如果系统只做天气展示用户需要自己去看周六周日的天气数据然后自己判断。现在后端把未来三天的天气预报、空气质量、风力等数据放到提示词里交给大模型要求模型结合这些数据给出建议。模型返回的结果可能是“周六下午有小雨建议安排在周日出行周日多云气温 24°C东南风 3 级空气质量良好适合户外散步建议上午 9 点到 11 点之间前往。”看这就是 AI 的价值——它完成的不是天气查询而是把结构化天气数据转化为决策建议并且连贯地输出给用户。AI 接入的技术实现本质上是这样一个链路用户输入问题系统获取该城市的实时/预报天气数据组装系统提示词System Prompt 用户问题 天气数据调用大模型 API传入消息列表接收模型返回的文本解析结果展示到页面。这里最关键的是第 3 步的提示词设计。同样的模型提示词写得好不好输出质量差别很大。后面第 6 节会给出完整代码。5. 环境准备与项目初始化5.1 开发环境清单项目建议工具/版本JDK1.8 或 11版本以项目实际要求为准IDEIntelliJ IDEA 社区版或旗舰版Maven3.6MySQL5.7 或 8.0数据库客户端Navicat 或 MySQL WorkbenchAPI 测试工具Postman 或浏览器直接访问天气数据接口选择一个文档完整、注册即可使用的天气服务如果你机器上还没装这些工具建议先按 J 从 JDK → Maven → MySQL → IDEA 的顺序装好。5.2 创建 Spring Boot 项目推荐使用 Spring Initializr 创建项目。https://start.spring.io/需要勾选的依赖Spring WebThymeleafSpring Data JPA或 MyBatis二选一MySQL DriverLombok可选简化实体类代码如果你是离线环境也可以手动创建一个 Maven 工程然后在 pom.xml 中引入依赖。5.3 核心依赖配置下面是一个基础的 pom.xml 关键依赖片段实际使用时请根据你选用的 Spring Boot 版本微调!-- 文件路径pom.xml -- parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent dependencies !-- Web 支持 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Thymeleaf 模板引擎 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-thymeleaf/artifactId /dependency !-- MySQL 驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- Spring Data JPA如果选择 MyBatis替换为对应依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency !-- 常用工具库 -- dependency groupIdorg.apache.commons/groupId artifactIdcommons-lang3/artifactId /dependency /dependencies5.4 配置文件 application.yml# 文件路径src/main/resources/application.yml server: port: 8080 spring: application: name: weather-travel-service datasource: url: jdbc:mysql://localhost:3306/weather_travel?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: your_password_here driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update show-sql: true thymeleaf: cache: false # 自定义配置天气服务 weather: api: base-url: https://your-weather-api.example.com key: your_weather_api_key # 自定义配置AI 大模型服务 ai: api: base-url: https://your-llm-api.example.com key: your_llm_api_key model: your-model-name注意weather.api.key和ai.api.key属于敏感配置。实际项目中不要把真实密钥提交到代码仓库后续第 8 节会专门讲配置安全。6. 核心功能完整代码示例下面按照“天气查询 → 出行建议 → AI 对话”的顺序给出可以直接借鉴的核心代码。每个代码块都标注了文件路径方便对照你的项目目录。6.1 天气查询功能首先定义一个接收天气 API 返回结果的结构类。为了简洁这里只展示核心字段实际字段根据所选天气 API 的文档调整。// 文件路径src/main/java/com/example/weather/dto/WeatherResponse.java package com.example.weather.dto; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; Data JsonIgnoreProperties(ignoreUnknown true) public class WeatherResponse { private String city; private String weather; private String temperature; private String humidity; private String windDirection; private String windPower; private String airQuality; private String tips; }接下来编写天气服务类负责调用外部天气 API并把返回值清洗成业务对象。// 文件路径src/main/java/com/example/weather/service/WeatherService.java package com.example.weather.service; import com.example.weather.dto.WeatherResponse; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; Service public class WeatherService { Value(${weather.api.base-url}) private String baseUrl; Value(${weather.api.key}) private String apiKey; private final RestTemplate restTemplate; public WeatherService(RestTemplate restTemplate) { this.restTemplate restTemplate; } public WeatherResponse getWeatherByCity(String city) { String url baseUrl ?city city key apiKey; // 不同天气服务商的返回结构不同这里按通用写法演示 // 实际项目中需要根据返回 JSON 结构调整解析方式 return restTemplate.getForObject(url, WeatherResponse.class); } }6.2 控制器层代码Thymeleaf 项目的 Controller 和前后端分离项目的 Controller 有一个显著区别它的方法返回值是模板名称而不是 JSON。// 文件路径src/main/java/com/example/weather/controller/WeatherController.java package com.example.weather.controller; import com.example.weather.dto.WeatherResponse; import com.example.weather.service.WeatherService; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; Controller public class WeatherController { private final WeatherService weatherService; public WeatherController(WeatherService weatherService) { this.weatherService weatherService; } GetMapping(/weather) public String weatherPage(RequestParam(value city, required false, defaultValue 北京) String city, Model model) { WeatherResponse weather weatherService.getWeatherByCity(city); model.addAttribute(city, city); model.addAttribute(weather, weather); return weather; } }这里的return weather对应的是src/main/resources/templates/weather.html。Spring Boot 自动配置会找到这个模板文件并渲染。6.3 Thymeleaf 页面模板下面是天气展示页面的核心片段。Thymeleaf 的语法特点是使用th:text等属性代替原生取值。!-- 文件路径src/main/resources/templates/weather.html -- !DOCTYPE html html langzh-CN xmlns:thhttp://www.thymeleaf.org head meta charsetUTF-8 title天气查询 - 智能天气出行服务系统/title link relstylesheet hrefhttps://cdn.jsdelivr.net/npm/bootstrap5.3.0/dist/css/bootstrap.min.css /head body div classcontainer mt-4 h2 classmb-3实时天气查询/h2 form classrow g-3 mb-4 th:action{/weather} methodget div classcol-auto input typetext classform-control namecity th:value${city} placeholder输入城市名称 /div div classcol-auto button typesubmit classbtn btn-primary查询/button /div /form div classcard th:if${weather ! null} div classcard-body h4 classcard-title 城市span th:text${city}北京/span /h4 p classcard-text 天气现象span th:text${weather.weather}晴/spanbr/ 当前温度span th:text${weather.temperature}25/span °Cbr/ 湿度span th:text${weather.humidity}40/span%br/ 风向span th:text${weather.windDirection}东南风/spanbr/ 风力span th:text${weather.windPower}3级/spanbr/ 空气质量span th:text${weather.airQuality}良/spanbr/ /p p classtext-muted mt-2 th:text${weather.tips}出行建议内容/p /div /div /div /body /html这里还要注意首页入口通常我们会写一个默认映射到天气查询页面// 文件路径src/main/java/com/example/weather/controller/IndexController.java package com.example.weather.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; Controller public class IndexController { GetMapping(/) public String index() { return redirect:/weather; } }6.4 出行建议模块规则引擎方式规则方式不依赖外部服务系统运行更稳定。建议先实现规则版再叠加 AI 对话。// 文件路径src/main/java/com/example/weather/service/TravelAdviceService.java package com.example.weather.service; import com.example.weather.dto.WeatherResponse; import org.springframework.stereotype.Service; Service public class TravelAdviceService { public String generateAdvice(WeatherResponse weather) { StringBuilder advice new StringBuilder(); String condition weather.getWeather(); if (condition.contains(雨)) { advice.append(今日有降水出行请携带雨具路面湿滑注意安全。); } else if (condition.contains(雪)) { advice.append(今日有降雪气温较低注意保暖和防滑。); } else if (condition.contains(晴)) { advice.append(天气晴朗适合出行但请注意防晒补水。); } else { advice.append(天气状况总体平稳适合出行。); } String airQuality weather.getAirQuality(); if (airQuality.contains(污) || airQuality.contains(差)) { advice.append(空气质量较差建议减少户外停留时间敏感人群佩戴口罩。); } return advice.toString(); } }然后在 WeatherController 中加入建议的组装// 在 WeatherController 中新增注入 // private final TravelAdviceService travelAdviceService; // model.addAttribute(advice, travelAdviceService.generateAdvice(weather));6.5 AI 智能问答模块这是整个系统最有“亮点”的部分。实现思路是构造请求消息列表把天气数据作为上下文塞进提示词然后调用大模型接口。// 文件路径src/main/java/com/example/weather/service/AiTravelService.java package com.example.weather.service; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; Service public class AiTravelService { Value(${ai.api.base-url}) private String baseUrl; Value(${ai.api.key}) private String apiKey; Value(${ai.api.model}) private String model; private final RestTemplate restTemplate; public AiTravelService(RestTemplate restTemplate) { this.restTemplate restTemplate; } public String askTravelQuestion(String userQuestion, String weatherContext) { String url baseUrl /chat/completions; HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBearerAuth(apiKey); // 构造 Prompt系统提示词 天气上下文 用户问题 String systemPrompt 你是一个智能出行助手。请结合用户所在城市的实时天气数据 给出具体的出行建议。回答要简洁、可操作不要编造天气数据。 如果问题与出行无关请礼貌拒绝回答。; ListMapString, String messages new ArrayList(); messages.add(message(system, systemPrompt)); messages.add(message(user, 当前城市天气数据如下 weatherContext \n用户的问题是 userQuestion)); MapString, Object requestBody new HashMap(); requestBody.put(model, model); requestBody.put(messages, messages); requestBody.put(temperature, 0.7); HttpEntityMapString, Object request new HttpEntity(requestBody, headers); MapString, Object response restTemplate.postForObject(url, request, Map.class); return parseResponse(response); } private MapString, String message(String role, String content) { MapString, String message new HashMap(); message.put(role, role); message.put(content, content); return message; } private String parseResponse(MapString, Object response) { // 大模型接口返回结构一般为: // { choices: [ { message: { role: ..., content: ... } } ] } // 这里的解析方式视所选大模型服务商的文档为准代码中做防御性判断 if (response ! null response.get(choices) instanceof List? choices !choices.isEmpty()) { Map?, ? firstChoice (Map?, ?) choices.get(0); Map?, ? message (Map?, ?) firstChoice.get(message); return (String) message.get(content); } return 抱歉AI 服务暂时不可用请稍后再试。; } }再写一个 AI 对话的 Controller// 文件路径src/main/java/com/example/weather/controller/AiController.java package com.example.weather.controller; import com.example.weather.dto.WeatherResponse; import com.example.weather.service.AiTravelService; import com.example.weather.service.WeatherService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; Controller public class AiController { private final AiTravelService aiTravelService; private final WeatherService weatherService; public AiController(AiTravelService aiTravelService, WeatherService weatherService) { this.aiTravelService aiTravelService; this.weatherService weatherService; } GetMapping(/ai) public String aiPage() { return ai_chat; } PostMapping(/ai/ask) ResponseBody public MapString, String ask(RequestParam String city, RequestParam String question) { WeatherResponse weather weatherService.getWeatherByCity(city); String weatherContext String.format(城市%s天气%s温度%s℃湿度%s%%风力%s空气质量%s, weather.getCity(), weather.getWeather(), weather.getTemperature(), weather.getHumidity(), weather.getWindPower(), weather.getAirQuality()); String answer aiTravelService.askTravelQuestion(question, weatherContext); MapString, String result new HashMap(); result.put(answer, answer); return result; } }这里的思路是用户提问时后端先拉取实时天气再连同问题一起发给大模型。AI 给出的建议是基于真实天气数据的不是一个“查不到数据就编答案”的玩具接口。这一点在论文和答辩中都能讲出深度。7. 运行验证与效果演示7.1 启动项目在 IDEA 中直接运行启动类或者在项目根目录执行mvn spring-boot:run看到类似输出说明启动成功Tomcat started on port(s): 8080 (http) with context path Started WeatherTravelApplication in 3.2 seconds7.2 验证核心流程验证一天气查询浏览器访问http://localhost:8080/weather?city上海预期看到上海的温度、湿度、风力和空气质量信息。如果页面空白或报错优先检查天气 API 的返回结构和数据库连接配置。验证二AI 对话浏览器访问http://localhost:8080/ai输入城市和问题例如“上海明天适合去外滩散步吗”点击发送页面通过 AJAX 请求/ai/ask接口返回大模型的文本建议。如果 AI 接口报错先检查 API Key 是否有效、网络能否访问该服务、消息体格式是否与服务商文档一致。验证三注册登录系统应包含最基础的注册登录流程。注册后密码建议使用 BCrypt 加密存储不要明文保存密码。7.3 接口返回示例/ai/ask接口在 Postman 中测试时的预期 JSON 返回{ answer: 根据明天的天气预报上海多云气温 20~26°C东南风 3 级空气质量良好。建议安排在上午 10 点到下午 3 点之间前往外滩此时光线充足适合散步和拍照。傍晚可能会有微风降温建议带一件薄外套。 }注意不同大模型返回的内容表述会不同这是正常的不需要强求一致。8. 常见问题与排查思路毕设开发过程中有几个高频问题值得提前记录。下面的表格可以贴到你自己的问题记录文档里也可以在论文“系统测试”章节引用。问题现象可能原因排查方式解决方案项目启动失败提示端口被占用8080 端口已被其他程序占用查看启动日志中的端口错误执行 netstat -anofindstr 8080天气数据查询不到天气 API 的 Key 无效或超出调用次数先用 Postman 直接请求天气 API查看返回检查 API Key 和套餐剩余次数更换稳定的天气服务商页面中文显示乱码数据库连接未指定 UTF-8检查 JDBC URL 和表字符集在 JDBC URL 中加入characterEncodingutf8建表时指定DEFAULT CHARSETutf8mb4Thymeleaf 页面修改后不生效模板缓存未关闭检查是否配置了spring.thymeleaf.cachefalse在开发环境关闭模板缓存改完按 CtrlF9 重新编译AI 接口返回 401 或 403API Key 错误、请求头格式不对检查请求头和文档对比确认 Bearer Token 格式确认模型名称存在AI 接口返回超时大模型响应慢或网络不稳定查看日志中的超时信息用 Postman 测试接口耗时将 HTTP 请求超时时间调大在代码中设置 RestTemplate 连接超时数据库连接失败MySQL 服务未启动或账号密码错误用命令行连接 MySQL 测试启动 MySQL 服务确认用户名密码正确项目打包后无法运行Maven 打包时跳过测试或依赖缺失查看构建日志检查 target 目录执行mvn clean package -DskipTests后重新运行 jar 包AI 返回内容包含编造的天气信息提示词没有明确限制模型检查 System Prompt 是否包含“不要编造数据”强化提示词告知模型只能基于提供的天气数据回答还有一个非常常见的坑单独拿出来说一下RestTemplate 的实例化。在 Spring Boot 项目中如果你直接在 Service 类里写new RestTemplate()每调用一次就创建一个新实例会造成不必要的资源开销。更推荐的方式是在配置类中声明一个 Bean// 文件路径src/main/java/com/example/weather/config/RestTemplateConfig.java package com.example.weather.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; Configuration public class RestTemplateConfig { Bean public RestTemplate restTemplate() { RestTemplate restTemplate new RestTemplate(); // 设置合理的超时时间避免 AI 接口长时间占用线程 return restTemplate; } }如果后续流量增大还可以用RestTemplate配合线程池或者切换到 WebClient 异步方案但毕设层面使用 RestTemplate 已经足够。9. 数据库设计与安全建议9.1 核心表结构毕设系统不需要设计太复杂的表但一定要“全”。以下四张表建议必须有user 表用户 ID、用户名、密码BCrypt 加密、昵称、手机号、创建时间、状态。city_favorite 表用户常用城市收藏用于展示“我的关注城市”列表。weather_query_log 表天气查询日志记录用户 ID、城市、查询时间。ai_chat_log 表AI 问答日志记录用户 ID、问题、回答、耗时、创建时间。日志表的价值体现在论文的数据分析部分你可以写“系统采集了用户在天气和出行场景下的查询数据为后续优化出行推荐提供了数据基础”。9.2 安全与合规建议密码必须加密存储使用BCryptPasswordEncoder不要用 MD5管理员的接口要单独校验权限数据库账号使用最小权限账号不要在生产环境使用 rootAPI Key 不要写在代码里用Value读取配置在答辩演示时不要展示真实的 API KeyAI 接口调用要加频率限制避免被刷量用户输入的问题要在前端做长度校验避免一次性提交超长文本。这些点不仅能提升系统质量在答辩时也能体现工程素养。10. 答辩加分点与常见追问毕业设计写到“能运行”只是及格线真正拉开差距的是你对系统的理解和表达。答辩时推荐按下面三个层次介绍 AI 部分第一层说结果系统实现了基于自然语言的出行问答用户提问后能获得结合天气数据的建议。第二层说实现后端通过 AI 服务的 API 实现对话能力调用前会把实时天气数据组装进 Prompt模型是基于天气上下文生成建议的。第三层说设计之所以用 Service 层封装 AI 调用是为了方便后续替换不同的大模型服务商System Prompt 的设计约束了模型只能基于提供的数据回答避免幻觉。老师可能会追问的问题提前准备问题一为什么选择 Thymeleaf 而不是前后端分离回答思路毕设系统以服务端渲染为主开发链路短、部署简单不需要单独维护前端工程。AI 问答这种交互性较强的功能通过 AJAX 局部刷新实现兼顾了交互体验。如果后续需要扩展成多端系统可以再重构为前后端分离架构。问题二AI 返回结果如果包含错误信息怎么办回答思路在大模型调用结果解析时做了防御性判断接口不可用时返回统一提示。同时通过 System Prompt 约束模型输出尽可能避免无效内容和编造数据。问题三如何保证天气数据的准确性和实时性回答思路天气数据来源于第三方天气服务商的实况接口每次查询实时拉取。对于高频访问的热门城市还可以引入 Redis 缓存减少对第三方接口的依赖。11. 最佳实践如何把毕设做出“工程感”很多同学的毕设代码能跑但一看就是“学生项目”。问题出在哪里缺少工程感。什么是工程感就是别人打开你的代码库能感觉到你是按软件工程的方式去组织代码的而不是把堆功能。第一包结构清晰。按照controller/service/repository/dto/config分层不要把所有类都放在一个包下面。这是最基础也最容易做到的一点。第二统一返回结构。虽然 Thymeleaf 场景下页面直接通过 Model 渲染但 AI 问答这类用到 AJAX 的接口建议统一封装返回结构。不要这次返回 Map下次返回 String。第三日志要完整。在 AI 调用、天气查询这类操作中打日志日志里要记录入参、出参和耗时。logger.info(用户 {} 查询城市 {} 天气信息耗时 {} ms, userId, city, costTime);第四异常处理要统一。编写全局异常处理器ControllerAdvice把业务异常、系统异常分开处理。页面场景下跳转到错误页接口场景下返回错误 JSON。第五开发环境和生产环境配置分离。用application-dev.yml和application-prod.yml区分环境用spring.profiles.active切换。这不仅是好习惯论文的系统设计部分也能多写两页。12. 总结与后续扩展方向从开发实现层面看这套“Spring Boot Thymeleaf AI”的智能天气出行服务系统把后端开发、模板渲染、第三方接口集成、AI 应用四大能力整合在了一个完整项目里。它不是一个只能跑通的 Demo而是一个结构完整、可以扩展、适合写进论文的项目。如果你准备动手做建议按下面的顺序推进第一步先把基础工程跑起来实现天气查询单页功能 第二步加上用户注册登录和基础的用户管理 第三步完成基于规则的出行建议模块 第四步接入 AI 大模型完成智能问答 第五步补充日志、异常处理、全局配置等工程化内容 第六步整理测试数据录制功能演示视频准备答辩 PPT。如果做完这些还想继续深入可以考虑三个方向方向一把规则出行建议升级成个性化推荐根据用户历史查询记录和偏好动态调整推荐策略这是可以在论文里写成算法优化的方向。方向二引入消息队列把高频天气查询做成异步任务降低第三方接口压力这个概念在毕设论文里很加分。方向三重构为前后端分离架构后端提供 API 服务前端用 Vue 3 重新实现页面。不过这个改动量较大适合时间充足、希望挑战自己的同学。记住一个核心判断毕设不是功能越多越好而是每做一个功能都要讲清楚它解决了什么问题、用了什么技术、有什么坑。这套天气出行系统最大的优势就是你每一个模块都能讲出这句话。预祝顺利。

相关新闻

2026/9/2 19:51:13

MATLAB下LS-SVM工具箱实战:原理、参数调优与应用

简介:Matlab LS-SVMlab1.5 工具箱是一套面向科研与工程实践的最小二乘支持向量机算法实现,适合需要处理非线性分类与回归、希望快速搭建SVM模型的机器学习研究人员和工程师。压缩包内共81个文件,以64个m源文件为主,覆盖模型训练、…

2026/9/2 19:46:13

闺蜜机智享版评测:移动智慧屏如何成为全屋智能中枢

最近在折腾家里的智能设备时,我入手了一台被朋友反复种草的“哇哦闺蜜机智享版”。原本以为它只是一台普通的大屏平板,结果用了几天之后,发现它已经成了我每天离不开的“生活搭子”——追剧、健身、看菜谱、语音控制智能家居,全都…

2026/9/2 19:46:13

WebSphere MQ V6.0实战:老版本消息中间件的安装运维与迁移

简介:这是一份针对企业级消息中间件 WebSphere MQ V6.0(IBM MQ 6.0)Windows 平台的安装与学习资源,适合系统集成工程师、中间件运维人员以及正在学习 MQ 消息队列的开发者。资源共 2000 个文件,压缩包约 257.95MB&…

2026/9/2 20:06:14

SecureCRT与SecureFX:Windows下SSH终端与文件传输实战指南

简介:一份面向IT专业人员的安全终端访问与文件传输集成工具包,整合SecureCRT与SecureFX核心功能,专为需要在Windows平台与各类远程服务器之间开展维护、配置与部署工作的用户设计。64位版本充分释放内存性能,支持SSH、Telnet以及S…

2026/9/2 20:06:14

Windows下编译WebRTC静态库并集成到Qt桌面应用的实战指南

简介:面向Windows x64桌面开发者的WebRTC m105版静态库资源,特别适合需要在C项目中快速接入实时音视频功能的工程师。该压缩包共包含2000个文件,主要类型为头文件,涵盖标准库、系统库及WebRTC自身接口声明,并附带少量协…

2026/9/2 20:06:14

隐形水印如何抗裁剪与打码?解析开源工具的鲁棒性设计

上个月,一个做插画的朋友发来一张截图:她刚发布的原创作品,被人截掉了右下角的署名,又在画面中间打了一道马赛克,变成某个短视频账号的背景图。她问我,有没有什么办法能让图片在传播之后还能证明“这是她的…

2026/9/2 20:06:14

Windows下编译WebRTC静态库完整指南:从环境配置到链接避坑

简介:面向 Windows x64 桌面环境的 WebRTC 105 版静态库,为需要在本地 C 工程中集成实时音视频通信能力的开发者提供预编译链接单元,省去从源码自行构建 WebRTC 的繁琐流程。压缩包为 7z 格式,约 68.75MB,共 2000 个文…

2026/9/2 20:06:14

jsoncpp库文件.zip从解压到集成全攻略:避坑指南与实战排查

简介:面向Windows平台C开发者的Jsoncpp集成资料包,专注于解决C项目里JSON数据的解析、生成与序列化难题,适用于桌面程序、网络通信、配置文件读写等常见场景。Jsoncpp本身具备轻量、易于集成的特点,能让开发者摆脱手工拼接和解析J…

2026/9/2 20:01:14

Windows下OpenCV+MinGW+Qt完整编译配置指南

简介:一套已编译好的 OpenCV 3.2.0 资源包,面向需要在 Windows 10 64 位下使用 MinGW 编译器搭配 Qt 5.9.6 进行图像处理与界面开发的技术人员。解决 OpenCV 官方预编译库不兼容 MinGW、手动编译配置繁琐的问题,省去 CMake 配置与编译耗时&am…

2026/9/1 16:02:17

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/9/2 9:00:32

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/9/2 8:41:06

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/9/2 0:03:41

单片机毕业设计-基于单片机与蓝牙通讯的输液状态监测终端设计与开发 基于 STM32 或 51 单片机的液位‑滴速‑温度多参数输液监护装置设计(024005)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/9/2 0:03:41

DeepSeek字幕翻译实战:从API调用到批量SRT转中文的完整方案

这次我们来看一个很实用的 DeepSeek 落地场景:用 DeepSeek 把英文视频字幕自动翻译成中文。具体案例是《恶魔君》1989 年第 28 集的英转中字幕任务,标题写得很直白,但背后其实是一整套可以复用的技术流程:字幕解析、模型调用、批量…

2026/9/2 0:03:41

用Python搭建搞笑语音助手:从语音识别到语音合成全教程

当你家里摆着一台天猫精灵,却总希望语音助手偶尔“不正经”一点,不用官方腔回答问题,而是张口就接几句搞笑段子,会是什么体验?我最近动手验证了一下这个想法——没有去改装任何市面上现有的智能音箱,而是直…

2026/9/2 1:15:22

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/2 1:15:22

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/2 1:15:20

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…