news 2026/8/31 19:10:11

AI全栈实战:Spring Boot+Vue3构建智能旅游推荐助手

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI全栈实战:Spring Boot+Vue3构建智能旅游推荐助手

AI全栈这个说法,最近在 Java 和前端圈子里热度很高。但很多人把它理解成“会调用一个大模型接口就算 AI 全栈”,这是把问题想简单了。真正的 AI 全栈,至少要打通“前端交互、后端服务、模型调用、业务规则、部署运维”这一整条链路。想验证自己是否具备这个能力,最直接的方式就是亲手做一个完整项目。我在梳理 AI 旅游智能推荐助手这个项目时,发现它特别适合用来练这一套能力:后端用 Spring Boot,前端用 Vue3,中间接入大模型推荐能力,最后把项目部署成一个可以访问的系统。下面按实际落地顺序拆一遍。

1. AI 全栈到底在练什么:不是“多学一个框架”,而是打通一条链路

1.1 AI 全栈工程师和普通前后端开发的区别

很多招聘信息里会出现“AI 全栈工程师”“大模型全栈工程师”这类 title。不同公司叫法不一样,但核心工作通常不是训练模型,而是把模型能力接进业务系统。

普通前后端开发关心的是接口、CRUD、权限、页面交互。AI 全栈开发还要多关心三件事:

  • 大模型接口怎么调用,提示词怎么设计。
  • 模型返回结果怎么校验、降级、缓存。
  • 模型能力怎么和现有业务规则结合,而不是让模型直接接管一切。

放到 AI 旅游智能推荐助手这个项目里,就是你要能解释清楚:用户填了城市、天数、预算和偏好后,系统是怎么从景点库里选出候选景点,怎么生成推荐理由,怎么安排行程,又怎么在接口异常时兜底返回。

1.2 旅游推荐助手为什么适合作为转型项目

这个项目不是随便抓来的 demo,它覆盖了 Java 后端、Vue3 前端、AI 接口调用和部署四块内容。

从后端角度看,有用户登录、景点管理、推荐记录、收藏订单这类标准 CRUD。从 AI 角度看,有偏好解析、候选召回、打分排序、提示词生成、行程规划。从前端角度看,有登录页、推荐表单、结果时间线、个人中心。从部署角度看,有后端打包、前端构建、Nginx 或 Docker 配置。

一句话总结:这是一个足够小、但链条完整的项目。比起一堆零散笔记,它能让你在面试时有一条完整的讲述线。

1.3 关于“百万年薪”先泼一盆冷水

项目标题写“学完直接挑战百万年薪”,这是吸引点击的说法。真正找工作的时候,面试官不会只看你有没有做过这个项目,更会看你有没有把项目讲清楚,能不能处理里面的异常和边界。

我的建议是:把这个项目当成练手和面试话题,而不是一张保底 offer。它最能帮你的地方,是让你在“Java 八股文”之外有一个可以讨论的实战样本。

2. 落地之前,先把技术栈和环境确认清楚

2.1 建议的技术栈组合

先列一组稳定且常见的组合,不要一上来就追求最新版本。最新版不一定不好,但资料少、坑多,尤其对转型者不友好。

模块选型说明
后端Java + Spring Boot用 Spring MVC 暴露 REST 接口
数据库MySQL保存用户、景点、推荐记录
缓存Redis缓存热门景点和重复推荐结果
ORMMyBatis-Plus 或 Spring Data JPA二选一即可,重点是别把 SQL 写在 Controller 里
前端Vue3 + Vite组合式 API,适合实践 defineProps、defineEmits
UI 组件Element Plus 或 Naive UI加快表单和结果页开发
HTTP 客户端Axios前后端交互的标准方案
接口文档springdoc-openapi也就是 Swagger 风格的接口网页
部署Docker + Nginx前后端分离后最常用的部署方式

如果不想引入太重的前端组件库,也可以用原生 CSS 加组合式 API。重点是先跑通,再优化。

2.2 本地开发环境和最低配置

这个项目的核心不是训练模型,所以对 GPU 没有硬性要求。大模型部分可以走远程 API,本机只负责业务逻辑和调用。

本地建议准备这些环境:

  • JDK 17 或 JDK 21。新版 Spring Boot 对 JDK 版本有要求,装太老会直接编译失败。
  • Maven 3.8 以上,用来管理后端依赖和打包。
  • Node.js 18 以上,用来启动 Vue3 开发服务器。
  • MySQL 8.x,Redis 6.x 或 7.x。
  • 一个可用的 IDE,IDEA 或 VS Code 都行。

如果你的机器内存只有 8G,先不要同时开 IDEA、MySQL、Redis、Vue dev server 和大模型相关工具。建议按顺序启动,关掉不用的软件。项目本身不重,但开发环境的资源占用很容易让人误判成项目问题。

2.3 第一次启动前的目录和端口规划

前后端分离项目最常见的坑,是两边各跑各的,最后前后端无法交互。

我建议在项目根目录下分两个子目录:

ai-travel-assistant/ ├── backend/ // Spring Boot 工程 ├── frontend/ // Vue3 工程 └── docs/ // 接口文档、部署文档、测试用例

端口规划也要提前定好。后端用 8080,前端开发服务器用 5173,Nginx 部署后对外用 80。前端访问后端接口时,如果本地端口不同,就要处理跨域。

注意:先不要急着写大量业务代码,先把 Spring Boot 空工程和 Vue3 空工程都启动起来,确认端口正常,再开始加业务。

3. 后端:Spring Boot 把“推荐助手”拆成可测试的接口

3.1 先做基础数据和用户模块

推荐助手要跑起来,首先要有一个可用的景点库。不需要一开始就录入全国数据,我建议先放一个城市的基础数据,比如杭州的 20 个景点,字段包括:景点名称、城市、标签、评分、门票价格、建议游玩时间、地理位置、图片 URL。

这些数据可以直接用 SQL 脚本初始化,也可以在后台管理页面里录入。从项目完成度来看,做一个简单的后台接口会比纯 SQL 更有说服力。

用户模块可以做得克制一点:注册、登录、获取当前用户信息、修改偏好。不要为了炫技加一堆不落地的功能。登录方式用 JWT 或 Session 都可以,但你要能解释清楚 token 存在哪里、什么时候过期、怎么刷新。

3.2 推荐接口的输入和输出

推荐接口是这个项目的核心,我建议设计成这个样子:

POST /api/recommend

请求体:

{ "city": "杭州", "days": 3, "budget": 2500, "tags": ["历史", "美食"], "pace": "适中", "companion": "朋友" }

响应体:

{ "spots": [ { "name": "西湖", "reason": "适合朋友一起散步,周边餐饮选择多", "duration": "4小时", "cost": 0 } ], "route": [ { "day": 1, "spots": ["西湖", "河坊街", "南宋御街"] } ], "reason": "整体路线以老城区为主,兼顾历史街区和本地美食。", "budgetEstimate": 2300, "tips": ["提前预约西湖游船", "河坊街晚上人较多"] }

接口设计的关键不是一次返回很多字段,而是让前端拿到后能直接渲染。比如“每日行程”固定为数组,前端就可以用 timeline 组件循环展示。

3.3 推荐逻辑:规则打分加大模型生成

这里要区分清楚:大模型负责什么,业务规则负责什么。

最稳妥的做法是先用规则引擎做候选推荐。比如用户选“历史”和“美食”,系统就对景点列表做打分:

  • 标签匹配加 20 分。
  • 评分在 4.5 以上加 10 分。
  • 单日门票价格超过预算除以天数的扣分。
  • 建议游玩时间过长或过短扣分。
  • 景点之间距离太远扣分。

按分数排序后,取前 5 到 8 个景点作为候选。这些候选数据再交给大模型,让它生成推荐理由、每日行程和注意事项。

这样做有三个好处:

第一,不依赖大模型也不会完全跑偏。第二,候选结果可控,模型不会凭空编造不存在的景点。第三,接口哪怕是超时或模型解析失败,规则层还能兜底返回结构化结果。

大模型调用部分,可以用一个简单的提示词模板:

String prompt = """ 你是一位熟悉国内旅游的规划助手。 用户偏好:%s 候选景点:%s 请生成: 1. 推荐理由。 2. 每日行程,最多 %d 天。 3. 预算估计。 4. 注意事项。 要求以 JSON 格式输出,不要输出多余内容。 """.formatted(userPreferences, candidateSpots, days);

注意,大模型并不是每次都会严格输出 JSON。所以后端一定要做结果解析校验,解析失败时降级到规则推荐,而不是直接报错。

3.4 接口安全:API Key 不能出现在前端

调用大模型最关键的一点,是 API Key 绝对不能放在 Vue3 代码里。前端代码打包后是静态文件,任何一个用户都能在开发者工具里看到请求内容,Key 一旦泄露就会被盗用。

正确做法是把模型调用放在后端:

  • 后端配置环境变量保存 API Key。
  • 前端只调用后端自己的/api/recommend
  • 后端收到请求后,再去调用大模型接口。
  • 前端永远感知不到模型地址和 Key。

这里可以再补一层:用户提交的内容不要直接拼进提示词,先做长度限制和内容过滤。否则很可能会出现超长输入、注入提示词、输出不符合预期的问题。

3.5 缓存、异步和日志:批量任务前必须想清楚

推荐接口不会像普通 CRUD 那么快,因为它涉及候选计算和模型调用。如果用户在短时间内重复提交相同请求,每次都去调大模型,不仅慢,还容易把模型调用的预算打爆。

我一般会这样做:

  1. 把用户的请求参数转成固定字符串,作为 Redis 缓存的 key。
  2. 缓存时间设置成 30 分钟或 1 小时。
  3. 如果用户请求相同,直接返回缓存。
  4. 对于批量离线推荐任务,使用异步线程池或消息队列处理,避免请求阻塞。

日志也要比普通项目多打一层。每次推荐请求要记录:用户 ID、城市、天数、预算、候选景点数量、模型返回耗时、是否走了降级逻辑。这些日志在排查问题上非常有用。

spring: datasource: url: jdbc:mysql://localhost:3306/ai_travel?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: your_password data: redis: host: localhost port: 6379 ai: api-key: ${AI_API_KEY} api-url: ${AI_API_URL} model: ${AI_MODEL:default-model} timeout-seconds: 30

4. 前端:Vue3 不只做页面,还要把状态、交互和异常处理做完整

4.1 页面模块和路由设计

Vue3 前端不需要做得很复杂,但要清晰。建议至少包含这几个页面:

  • 首页:展示推荐入口和热门城市。
  • 登录注册页:用户名密码登录。
  • 推荐表单页:城市、天数、预算、标签选择。
  • 推荐结果页:展示推荐景点、每日路线、预算和时间线。
  • 个人中心:查看收藏和最近推荐记录。

路由可以使用 Vue Router。页面状态建议用 Pinia 保存用户信息和最近一次推荐结果,避免页面跳转后数据丢失。

组件层面再做拆分,比如:

  • RecommendForm:负责收集用户偏好。
  • SpotCard:展示单个景点。
  • RouteTimeline:展示每日行程。
  • BudgetSummary:展示预算评估。

拆分组件不是为了好看,而是为了让你能讲清楚父子组件之间的数据流。Vue3 面试题里常问的 defineProps、defineEmits,在这个项目里都会用到。

4.2 用 Axios 对接后端,注意 loading 和错误状态

很多人写前端接口时只写了成功路径,忘记 loading 和错误状态。这样在演示时一旦模型接口超时,页面就一直转圈,体验很差。

推荐写法是封装一个统一 request:

// src/api/request.js import axios from 'axios' const request = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || '/api', timeout: 30000 }) request.interceptors.request.use((config) => { const token = localStorage.getItem('token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config }) request.interceptors.response.use( (response) => response.data, (error) => { if (error.response && error.response.status === 401) { window.location.href = '/login' } return Promise.reject(error) } ) export default request

然后在推荐页里这样调用:

<script setup> import { ref } from 'vue' import { recommend } from '@/api/recommend' const loading = ref(false) const errorMessage = ref('') const form = ref({ city: '杭州', days: 3, budget: 2000, tags: ['历史', '美食'] }) async function handleSubmit() { if (!form.value.city) { errorMessage.value = '请先选择城市' return } loading.value = true errorMessage.value = '' try { result.value = await recommend(form.value) } catch (e) { errorMessage.value = '推荐服务暂时不可用,请稍后重试' } finally { loading.value = false } } </script>

这里最关键的不是代码量,而是流程完整:校验输入、开启 loading、捕获错误、关闭 loading。很多前端新手漏掉 finally,导致出错后按钮一直禁用。

4.3 推荐结果展示和参数调整

推荐结果页不要只展示一个 JSON 字符串,要把它转成用户能看懂的组件。

比如每日路线用时间线组件展示:

  • 第 1 天:西湖、河坊街、南宋御街。
  • 第 2 天:灵隐寺、龙井村。
  • 第 3 天:西溪湿地、返程。

每个景点卡片里显示推荐理由、建议游玩时间、门票价格。预算部分用进度条展示,让用户一眼看出是否超预算。

同时可以在结果页增加“重新生成”按钮。不同用户会输入不同偏好,生成结果差异会很明显,这本身也是 AI 项目适合展示的地方。

4.4 前后端联调和跨域配置

本地开发时前端跑在 5173,后端跑在 8080,这是不同端口,所以必须处理跨域。

后端可以配置全局 CORS:

@Configuration public class CorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("http://localhost:5173") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("*") .allowCredentials(true); } }; } }

生产环境不建议太依赖跨域配置,更好的办法是用 Nginx 做反向代理。前端请求/api时,Nginx 转发到后端 8080,这样前端对外只访问同一个域名,就不会有跨域问题。

注意:跨域报错时,先确认是浏览器拦截还是后端没响应。打开开发者工具 Network 面板,如果能看到请求已经发出但看不到返回,基本就是后端或代理配置问题。

5. 部署和验收:从“本地能跑”到“像样交付”

5.1 构建后端和前端产物

本地跑通不代表项目完成。面试时如果只能演示npm run devjava -jar,会显得项目还停留在开发阶段。建议至少完成一次正式构建。

后端打包:

cd backend mvn clean package -DskipTests java -jar target/ai-travel-assistant.jar

前端构建:

cd frontend npm install npm run build

构建后frontend/dist就是静态文件目录。把 dist 目录放到 Nginx 的 html 目录,再把 API 反向代理到后端,就是一个可访问的完整系统。

5.2 使用 Docker Compose 部署前后端

如果考虑到简历上体现 Docker 能力,可以把部署也做一下。一个简化的 docker-compose 示例:

version: "3.8" services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: ai_travel ports: - "3306:3306" redis: image: redis:7 ports: - "6379:6379" backend: build: ./backend ports: - "8080:8080" environment: SPRING_PROFILES_ACTIVE: prod AI_API_KEY: ${AI_API_KEY} AI_API_URL: ${AI_API_URL} depends_on: - mysql - redis frontend: build: ./frontend ports: - "80:80" depends_on: - backend

注意,Docker Compose 文件里不要直接写死 AI_API_KEY,建议用环境变量替换。部署文档里要写清楚外部需要准备哪些变量,否则换一台机器跑不起来。

5.3 验收清单:拿什么标准判断项目合格

不要只看“能打开页面”就算完成。我建议按下面这个清单逐项验收:

  • 用户能否注册、登录,刷新页面后登录状态是否保留。
  • 推荐表单缺少必填项时是否有明确提示。
  • 输入“杭州 3 天 2500 预算”能否稳定返回 3 到 5 个景点。
  • 每日行程是否按天数拆分,有没有把景点排到日期外面。
  • 大模型接口故意关掉时,系统是否还能返回规则推荐结果。
  • 连续提交 10 次相同请求,Redis 缓存是否生效,模型调用次数是否减少。
  • 前端部署到 Nginx 后,刷新页面是否 404。
  • 容器重启后,数据库数据和 Redis 缓存是否恢复或重建。

6. 转型和面试:项目亮点怎么说,踩坑怎么避免

6.1 项目讲法:从“功能列表”改成“问题链路”

面试时不要一上来就背功能列表。比较自然的讲法是:

  1. 先说项目背景:用户在选择旅行目的地和路线时,信息分散,所以做一个智能推荐助手。
  2. 再说系统边界:后端处理用户、景点、推荐记录,前端负责交互,AI 负责生成个性化理由和行程。
  3. 然后讲技术难点:模型输出不稳定、候选结果不可控、接口超时、缓存策略。
  4. 最后讲你的处理:规则打分保证候选可控,提示词加 JSON 解析,模型失败时降级,Redis 缓存热数据。

这个过程比单纯说“我会 Spring Boot 和 Vue3”更有说服力。

6.2 面试高频问题

根据 Spring Boot、Vue3、AI 全栈这三个方向,下面几个问题很容易被问到:

  • Spring Boot 自动配置原理是什么。
  • 前后端分离后,如何管理接口版本、错误码和登录鉴权。
  • Vue3 的响应式原理和 Vue2 有什么区别。
  • 组件通信方式有哪些,为什么不用全局变量。
  • 大模型返回结果怎么保证格式稳定。
  • 推荐系统里的冷启动怎么处理。
  • Redis 缓存穿透、缓存击穿、缓存雪崩分别怎么解决。

这些问题不需要背标准答案,结合项目回答最能体现真实水平。

6.3 常见启动和运行问题排查

下面是我在这个类型项目里经常遇到的坑,按排查顺序列出来。

现象优先排查点
Spring Boot 启动失败数据库账号密码、MySQL 是否启动、Redis 是否启动、端口是否被占用
Maven 编译报错JDK 版本、Lombok 版本、Spring Boot 版本是否兼容
Java 报 OutOfMemoryError构建或运行 JVM 堆是否太小,尝试调大-Xmx
前端 npm install 报错Node 版本、npm 镜像源、package.json 依赖冲突
接口 404请求路径是否带/api,Controller 映射是否匹配
跨域报错后端 CORS、Nginx 反向代理、前端 baseURL
推荐结果长时间不返回大模型接口超时、日志是否卡在远程请求、候选 SQL 是否慢
模型返回内容无法解析提示词约束不够、返回内容被截断、解析逻辑太严格

“Spring Boot 版本太高”这个问题也值得单独说。很多人在搭建项目时直接选了最新版,结果插件、依赖或教程里的写法不兼容。如果不是特别清楚新版特性,建议先用稳定版把项目跑通,再考虑升级。

6.4 我的建议

把这个项目做完,不等于你能拿到百万年薪 offer,但它确实能让你在转型 AI 全栈的路上有东西可讲。关键不在标题,而在你能否独立完成一条链路:Spring Boot 提供接口,Vue3 渲染页面,AI 生成个性化推荐,Docker 部署上线。

我建议你把节奏放稳一点。先跑通单条推荐请求,再处理批量任务;先接受默认配置,再优化模型输出和缓存;先完成基础页面,再考虑组件拆分和权限控制。很多问题看起来是功能不支持,实际是依赖版本、路径权限或输入格式没有处理好。

如果只是学习,默认配置够用。如果要把它写进简历,请务必补上接口文档、部署文档、测试样例和问题排查记录。到那时候,这个 AI 旅游智能推荐助手才真正成为你的项目,而不只是别人教程里的复刻品。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 19:05:59

工业巡检机器人软件系统:从五层架构到落地路径的深度拆解

最近在关注工业巡检机器人这个方向&#xff0c;发现一个有意思的现象&#xff1a;硬件堆料越来越猛&#xff0c;激光雷达、四足底盘、防爆外壳&#xff0c;看得人眼花缭乱&#xff1b;但真正决定一套巡检系统能不能从“演示视频”变成“车间里天天跑的工具”&#xff0c;几乎全…

作者头像 李华
网站建设 2026/8/31 19:05:03

64QAM软解调MATLAB仿真链路搭建与误码率分析

简介&#xff1a;本资源是一套面向通信工程专业本科生与初阶科研人员的64QAM软解调通信链路MATLAB仿真教学包&#xff0c;聚焦高阶调制下的误码率性能分析与实现细节&#xff0c;解决理论学习后缺乏可运行、可调试、可复现仿真实例的实践痛点。压缩包共5个文件&#xff08;2个核…

作者头像 李华
网站建设 2026/8/31 19:03:25

监控视角下教室人头密集检测:YOLOv8训练调优与部署实践

简介&#xff1a;本资源是面向计算机视觉初学者与教育智能化研究者的教室人头密集场景目标检测数据集&#xff0c;聚焦监控视角下小尺度、高密度头部目标的识别难题&#xff0c;适用于YOLO系列模型训练、算法优化及课堂行为分析等实际应用。数据包共2000个文件&#xff0c;含19…

作者头像 李华
网站建设 2026/8/31 19:03:12

Vibe coding到生产上线,你还差哪些工程化能力?

最近在技术社区里&#xff0c;“Vibe coding”这个概念几乎刷屏了。不少开发者用它快速搭出原型、做Demo&#xff0c;甚至把内部小工具直接跑起来。但很多人拿着 AI 生成的代码准备上线时&#xff0c;却卡住了&#xff1a;没有环境配置、缺少错误处理、数据库连接裸奔、接口没有…

作者头像 李华
网站建设 2026/8/31 19:00:20

SpringBoot实战:智慧养老系统架构设计与核心业务实现

简介&#xff1a;本资源是一个基于SpringBoot开发的智慧养老中心管理系统完整项目源码包&#xff0c;面向Java后端开发者、养老信息化系统学习者及高校相关专业师生&#xff0c;旨在解决老龄化背景下养老机构数字化管理难题。系统覆盖老人档案、健康监测、日常活动、服务记录、…

作者头像 李华
网站建设 2026/8/31 18:59:11

DSP28335全桥LLC数字软启动:原理、策略与工程实现详解

简介&#xff1a;本资源是一套面向电力电子工程师与嵌入式开发者、专为TMS320F28335 DSP平台设计的全桥LLC谐振变换器数字控制软启动程序&#xff0c;解决高频开关电源启动过程中的电流冲击、电压过冲及器件应力过大等关键问题&#xff0c;适用于电动车充电模块、通信电源、工业…

作者头像 李华