ARTICLE DETAIL

资讯详情

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

Java与Vue开发者如何构建AI全栈应用:旅游推荐助手实战

Java与Vue开发者如何构建AI全栈应用:旅游推荐助手实战 最近在技术社区里一个高频出现的词是“AI全栈”。很多有Java、Spring Boot、Vue经验的后端或前端开发者看着AI浪潮一波接一波心里都痒痒的我能不能也搞点AI但一打开教程不是复杂的数学公式就是海量的Python库和框架感觉要重头再来门槛太高。其实这里有个常见的误解从“前后端开发者”到“AI应用开发者”并不一定需要你成为算法专家。真正的转变是把AI能力当作一种新的、强大的“后端服务”或“数据处理组件”嵌入到你熟悉的工程体系里。你不需要从零推导一个模型但你需要知道如何调用、集成、部署并让它在你的应用里稳定工作。今天要聊的这个“AI旅游智能推荐助手”项目就是一个绝佳的切入点。它不是一个玩具Demo而是一个完整的、前后端分离的Web应用。它的核心价值在于它清晰地演示了如何在你熟悉的Java Spring Boot Vue3技术栈上安全、可控地“嫁接”AI能力完成一个真实的业务场景——旅游推荐。这比单纯学一个AI工具更有意义你是在用已有的工程能力去驾驭新的AI能力最终产出的是一个可交付、可迭代的完整产品。1. 为什么说这个项目是前后端开发者转型AI全栈的“理想跳板”很多AI入门项目要么是纯Python脚本要么是调用某个API的简单Demo。这对于习惯了工程化、模块化开发的Java或前端开发者来说感觉“使不上劲”学完了也不知道怎么用到自己的项目里。这个旅游推荐项目之所以合适是因为它构建了一个完整的“工程上下文”。你不是在孤立地学习AI调用而是在学习如何在一个标准的、你熟悉的Web应用架构中让AI能力成为业务逻辑的一部分。1.1 它复用了你已有的核心技能栈项目的技术选型非常“友好”后端Spring Boot。这意味着你已有的依赖管理Maven/Gradle、RESTful API设计、控制器Controller、服务层Service、数据访问层Repository/DAO的知识全部能用上。你处理用户认证、数据校验、业务逻辑、数据库操作的方式和以前完全一样。前端Vue 3 可能搭配的UI库如Element Plus。组件化开发、状态管理Pinia、路由Vue Router、API调用Axios这些前端工程实践是你已经掌握或正在学习的。数据库大概率是MySQL或PostgreSQL。你的SQL和ORM如MyBatis, JPA经验直接复用。AI部分在这个项目中通常是以一个“服务”的形式出现。比如一个RecommendationService它的内部可能封装了对某个AI模型API的调用或者对本地一个轻量级机器学习库的使用。你的主要工作不是训练模型而是如何设计这个服务的接口、如何处理它的输入输出、如何管理它的错误和超时、如何将它的结果与你的用户数据和业务规则结合。这些恰恰是软件工程师最擅长的。1.2 它清晰地定义了AI的“职责边界”在这个项目中AI的职责很明确基于用户输入如目的地、兴趣、预算、时间生成个性化的旅游推荐。 这避免了初学者常犯的“大而全”的错误。你不是要做一个能理解一切自然语言、规划一切行程的通用人工智能。你是在解决一个具体问题。这个边界让你可以聚焦输入输出用户输入什么格式的数据表单自然语言AI输出什么结构的数据JSON格式的景点列表带权重的标签设计降级方案如果AI服务不可用或超时你的应用能否返回一个基于规则的、缓存的推荐这是工程思维的关键。评估效果你可以设计简单的评估方式比如A/B测试看AI推荐和热门榜单推荐哪个更受用户点击。1.3 它演示了AI集成的关键工程问题这是本项目超越简单Demo的核心价值。你会实际面对并解决以下问题API集成与封装如何调用第三方的AI服务API如大语言模型API如何设计请求体、解析响应体如何将API的通用回复转换成你业务需要的结构化数据密钥与配置管理API密钥绝不能硬编码在代码里。你会学习如何使用Spring Boot的ConfigurationProperties或环境变量来安全地管理这些敏感信息。异步处理与用户体验AI推理可能需要几秒钟。你不能让用户界面一直卡住。你会实践如何使用Spring Boot的Async或前端的状态管理来实现“提交-后台处理-轮询或WebSocket通知结果”的流畅体验。错误处理与重试网络波动、API限额、模型过载都会导致失败。你的服务层需要有健壮的错误处理机制可能还包括指数退避的重试策略。成本与性能考量每次调用AI API都可能产生费用。你会开始思考这个推荐请求真的每次都需要调用AI吗能不能对热门目的地进行缓存如何设计才能平衡推荐质量和调用成本通过解决这些问题你完成的不仅仅是一个功能而是一个具备生产环境潜力的AI能力模块。这种经验是单纯看AI教程无法获得的。2. 项目实战拆解“AI旅游推荐助手”的核心架构让我们把这个项目拆开看看各个部分是如何协同工作的。理解了这个架构你就能举一反三把AI能力应用到其他业务场景中。2.1 系统架构总览一个典型的架构可能如下所示用户浏览器 (Vue3 App) | | HTTP (Axios) v Spring Boot 后端 (REST API) | | 业务逻辑处理 数据持久化 v [ 核心AI服务层 ] | | (可选路径) ------------------------------------- | | | v v v 本地轻量模型 第三方大模型API 规则引擎/缓存 (如ONNX运行时) (如OpenAI, 文心) (降级方案)这个架构的核心思想是解耦。前端负责展示和交互后端负责协调和业务AI服务负责智能推荐。AI服务本身也可以有多种实现并根据情况切换。2.2 后端Spring Boot的关键模块在后端项目中你可能会看到或创建以下关键包和类controller.RecommendationController提供如POST /api/recommend的端点接收前端传来的用户偏好数据。dto.RecommendationRequest请求数据对象包含destination目的地、interests兴趣列表、budget预算、days天数等字段。dto.RecommendationResponse响应数据对象包含status、message和一个ListAttraction的推荐列表。service.RecommendationService核心服务接口。这里定义了generateRecommendations(RecommendationRequest request)方法。service.impl.AiRecommendationServiceImpl上述接口的一个实现。它内部会组装Prompt将结构化的RecommendationRequest转换成一个给大语言模型的提示词Prompt。例如“请为一位计划去北京、喜欢历史文化、预算中等、游玩3天的游客推荐5个景点并简要说明理由。请以JSON格式返回包含name, description, reason字段。”调用AI客户端使用配置好的API密钥和客户端如OpenAI Java Client或一个自定义的HTTP客户端发送请求。解析与后处理收到AI返回的文本通常是JSON字符串后解析成Attraction对象列表。这里可能需要处理AI回复格式不标准的情况进行清洗和校验。融合业务数据将AI推荐的结果与数据库中的景点真实信息如开放时间、门票价格、评分进行关联和丰富。异常处理捕获网络超时、API限额、解析失败等异常并可能触发降级策略如调用RuleBasedRecommendationServiceImpl。service.impl.RuleBasedRecommendationServiceImpl降级服务的实现。当AI服务失败时根据简单的规则如目的地兴趣标签匹配数据库中的热门景点返回推荐。config.AiConfig配置类用于集中管理AI服务的URL、API密钥、超时时间等参数通常从application.yml中读取。2.3 前端Vue 3的关键交互前端需要提供一个友好的界面收集用户偏好并优雅地展示异步的推荐结果。偏好收集页面使用表单组件让用户选择或输入目的地、兴趣标签多选、预算区间、旅行天数等。状态管理Pinia可以定义一个useRecommendationStore用于管理推荐请求的状态loading,error,recommendations。这比在组件内用ref管理更清晰。异步请求与反馈// 在组件或Store中的方法 const fetchRecommendations async (preferences) { recommendationStore.setLoading(true); try { const response await axios.post(/api/recommend, preferences); recommendationStore.setRecommendations(response.data.data); } catch (error) { recommendationStore.setError(推荐生成失败请稍后重试或尝试简化条件。); // 可以在这里根据错误码给用户更具体的提示 } finally { recommendationStore.setLoading(false); } };加载与结果展示提交后显示一个加载指示器如旋转的图标或骨架屏。成功返回后使用卡片列表Card或列表List组件美观地展示景点名称、图片、描述、推荐理由。可以增加“换一批”、“基于此推荐优化”等交互按钮触发新的AI请求实现迭代式推荐。2.4 AI服务的两种实现路径与选择这是项目的技术核心点你需要根据实际情况选择。路径一调用第三方大模型API推荐初学者优点上手极快效果通常很好无需关心模型训练和部署。缺点有持续成本依赖外部网络和服务稳定性。关键技术点Prompt工程如何设计提示词让AI稳定地返回你需要的结构化数据。这是成败的关键。需要反复调试和优化。流式输出对于长文本生成可以考虑使用Server-Sent Events (SSE) 将AI的回复流式推送到前端提升用户体验。上下文管理如果推荐是对话式的你需要维护一个会话上下文并在每次请求时带上历史消息。路径二集成本地轻量级模型优点数据隐私性好无网络延迟和调用费用适合对延迟和成本敏感的场景。缺点技术栈更复杂需要处理模型部署、更新和性能问题。可能的技术选型ONNX Runtime一个高性能推理引擎可以运行多种框架PyTorch, TensorFlow等导出的模型。你可以用Python训练一个简单的推荐模型如基于内容或协同过滤导出为ONNX格式然后在Java中使用ONNX Runtime的Java API进行加载和推理。DJL (Deep Java Library)亚马逊开源的Java深度学习库可以直接加载和运行PyTorch、TensorFlow等模型。预训练模型微调对于旅游推荐可以找一个在相关文本上预训练过的模型如BERT用自己的景点描述数据进行微调用于计算用户兴趣与景点描述的相似度。工程挑战你需要将模型文件打包到项目中或放在特定路径管理模型版本并确保Java应用有足够的内存警惕java: outofmemoryerror: insufficient memory。建议对于第一个AI全栈项目强烈建议从路径一调用API开始。它能让你快速看到效果并集中精力解决工程集成问题。路径二可以作为后续的进阶探索当你需要更深度的定制和优化时再考虑。3. 从零到一手把手搭建你的第一个AI全栈功能模块假设我们现在采用“调用第三方大模型API”的方案来一步步实现这个推荐功能。请跟随这个流程它是一套可复用的方法论。3.1 环境与项目初始化创建Spring Boot项目使用 Spring Initializr 或IDE如IntelliJ IDEA创建项目。依赖选择Spring Web,Lombok简化DTOConfiguration Processor配置提示。创建Vue 3项目使用npm create vuelatest或 Vite 创建。按需添加Pinia,Axios,Element Plus等库。配置跨域CORS在Spring Boot中配置CORS允许前端本地开发服务器的请求。3.2 后端核心构建AI推荐服务步骤1定义数据模型DTO// RecommendationRequest.java Data // Lombok注解 public class RecommendationRequest { private String destination; private ListString interests; // e.g., [历史文化, 自然风光, 美食] private String budget; // 经济型, 舒适型, 豪华型 private Integer days; } // Attraction.java Data public class Attraction { private String name; private String description; private String reason; // AI推荐的理由 // 可以从数据库关联更多字段如 imageUrl, price, openingHours }步骤2配置AI客户端以OpenAI为例首先在application.yml中配置ai: openai: api-key: ${OPENAI_API_KEY:} # 优先从环境变量读取 model: gpt-3.5-turbo temperature: 0.7 max-tokens: 1000然后创建配置类和客户端Bean// AiConfig.java Configuration ConfigurationProperties(prefix ai.openai) Data public class AiConfig { private String apiKey; private String model; private double temperature; private int maxTokens; } // 在某个配置类中声明RestTemplate或使用OpenAI官方Java Client Bean public OpenAiService openAiService(AiConfig aiConfig) { return new OpenAiService(aiConfig.getApiKey(), Duration.ofSeconds(30)); }步骤3实现推荐服务// RecommendationService.java public interface RecommendationService { RecommendationResponse generateRecommendations(RecommendationRequest request); } // AiRecommendationServiceImpl.java Service Primary // 设置为主要实现 Slf4j public class AiRecommendationServiceImpl implements RecommendationService { Autowired private OpenAiService openAiService; Autowired private AiConfig aiConfig; Override public RecommendationResponse generateRecommendations(RecommendationRequest request) { // 1. 构建Prompt String prompt buildPrompt(request); log.info(Generated prompt: {}, prompt); // 2. 构建AI请求 ChatCompletionRequest chatRequest ChatCompletionRequest.builder() .model(aiConfig.getModel()) .temperature(aiConfig.getTemperature()) .maxTokens(aiConfig.getMaxTokens()) .messages(List.of( ChatMessage.builder() .role(ChatMessageRole.SYSTEM) .content(你是一个专业的旅游推荐助手。请根据用户偏好推荐景点并给出简短理由。必须返回纯JSON数组每个对象包含name, description, reason三个字段。) .build(), ChatMessage.builder() .role(ChatMessageRole.USER) .content(prompt) .build() )) .build(); // 3. 调用API并解析 try { ChatCompletionResult result openAiService.createChatCompletion(chatRequest); String aiResponse result.getChoices().get(0).getMessage().getContent(); log.info(AI raw response: {}, aiResponse); // 4. 解析JSON响应 (这里需要健壮的解析AI可能返回非标准JSON) ListAttraction attractions parseAiResponse(aiResponse); // 5. (可选) 融合数据库数据丰富信息 // attractions enrichWithDatabaseInfo(attractions); return RecommendationResponse.success(attractions); } catch (Exception e) { log.error(调用AI推荐服务失败, e); // 6. 降级策略返回规则推荐或友好错误 // return fallbackRecommendation(request); return RecommendationResponse.error(智能推荐服务暂时不可用请稍后重试。); } } private String buildPrompt(RecommendationRequest request) { return String.format( 目的地%s\n兴趣%s\n预算%s\n游玩天数%s天\n请推荐5个适合的景点并说明理由。, request.getDestination(), String.join(、, request.getInterests()), request.getBudget(), request.getDays() ); } private ListAttraction parseAiResponse(String jsonString) throws JsonProcessingException { // 使用Jackson或Gson解析 // 注意AI返回的JSON可能被Markdown代码块包裹需要预处理 jsonString jsonString.trim(); if (jsonString.startsWith(json)) { jsonString jsonString.substring(7); } if (jsonString.endsWith()) { jsonString jsonString.substring(0, jsonString.length() - 3); } ObjectMapper mapper new ObjectMapper(); return mapper.readValue(jsonString, new TypeReferenceListAttraction() {}); } }步骤4创建控制器// RecommendationController.java RestController RequestMapping(/api/recommend) public class RecommendationController { Autowired private RecommendationService recommendationService; PostMapping public RecommendationResponse getRecommendations(RequestBody Valid RecommendationRequest request) { return recommendationService.generateRecommendations(request); } }3.3 前端核心实现交互界面步骤1创建偏好表单组件使用Element Plus的Form、Select、Button等组件构建表单并通过Vue的ref或 Pinia Store 绑定数据。步骤2调用API并管理状态在Pinia Store中// stores/recommendation.js import { ref } from vue import { defineStore } from pinia import axios from axios export const useRecommendationStore defineStore(recommendation, () { const recommendations ref([]) const loading ref(false) const error ref(null) const fetchRecommendations async (preferences) { loading.value true error.value null try { const response await axios.post(http://localhost:8080/api/recommend, preferences) recommendations.value response.data.data } catch (err) { error.value err.response?.data?.message || 请求失败请检查网络或稍后重试。 console.error(推荐请求失败:, err) } finally { loading.value false } } return { recommendations, loading, error, fetchRecommendations } })步骤3在页面组件中使用template div el-form :modelform submit.preventhandleSubmit !-- 表单字段 -- el-form-item label目的地 el-input v-modelform.destination / /el-form-item !-- ... 其他字段 -- el-button typeprimary :loadingstore.loading native-typesubmit生成推荐/el-button /el-form div v-ifstore.error classerror-message {{ store.error }} /div div v-ifstore.loading classloading 正在为您智能规划行程... /div div v-else-ifstore.recommendations.length 0 classrecommendation-list el-card v-foritem in store.recommendations :keyitem.name template #header h3{{ item.name }}/h3 /template p{{ item.description }}/p pstrong推荐理由/strong{{ item.reason }}/p /el-card /div /div /template script setup import { useRecommendationStore } from /stores/recommendation import { reactive } from vue const store useRecommendationStore() const form reactive({ destination: , interests: [], budget: 舒适型, days: 3 }) const handleSubmit () { store.fetchRecommendations(form) } /script3.4 运行与调试启动Spring Boot后端。启动Vue前端开发服务器。打开浏览器访问前端地址填写表单并提交。观察后端控制台日志查看Prompt和AI原始响应。检查前端是否正确显示推荐结果。至此一个最基础的、可工作的AI全栈功能模块就完成了。它虽然简单但包含了从前端交互、后端API、AI服务集成到异常处理的核心链路。4. 超越Demo将AI功能工程化与生产就绪的思考完成基础功能只是第一步。要让这个“助手”真正可用、可靠你需要考虑更多工程化问题。这也是区分“玩具项目”和“有生产价值项目”的关键。4.1 稳定性保障降级、重试与熔断降级策略如前所述必须有一个RuleBasedRecommendationServiceImpl作为备用。当AI服务连续失败N次或响应时间超过阈值时自动或手动切换至降级服务。重试机制对于网络波动等暂时性错误可以配置重试。使用Spring Retry或手动实现带指数退避的重试逻辑。Retryable(value {OpenAiHttpException.class}, maxAttempts 3, backoff Backoff(delay 1000, multiplier 2)) public ChatCompletionResult callAiWithRetry(ChatCompletionRequest request) { return openAiService.createChatCompletion(request); }熔断与限流使用Resilience4j等库实现熔断器防止在AI服务不稳定时大量请求堆积拖垮整个应用。同时根据AI服务的QPS限制在后端对用户请求进行限流。4.2 性能与成本优化缓存对于热门目的地和常见兴趣组合的推荐结果可以缓存起来使用Redis或Caffeine。下次相同请求直接返回缓存结果大幅降低AI调用成本和响应延迟。缓存需要设置合理的过期时间。Prompt优化精心设计的Prompt可以提高AI回复的准确性和稳定性减少无效的token消耗从而降低成本。将系统指令System Message设计得尽可能清晰、具体。异步与流式对于耗时的推荐请求可以改为异步处理。提交请求后立即返回一个任务ID前端通过轮询或WebSocket获取进度和结果。对于长文本生成流式输出能极大提升用户体验。4.3 可观测性与监控日志记录详细记录每次AI调用的请求参数、响应时间、token消耗、是否成功。这对于排查问题、分析成本和优化Prompt至关重要。指标监控使用Micrometer将AI服务的调用次数、成功率、延迟等指标暴露给Prometheus并在Grafana中制作监控看板。链路追踪在分布式系统中使用Sleuth/Zipkin将一次用户请求从前端到后端再到AI服务的完整链路串联起来便于定位性能瓶颈。4.4 安全与合规API密钥管理绝对不要将密钥提交到代码仓库。使用环境变量、配置中心如Spring Cloud Config或云服务商提供的密钥管理服务如AWS Secrets Manager。用户输入净化对用户输入的目的地、兴趣等文本进行必要的检查和过滤防止Prompt注入攻击用户输入恶意指令影响AI行为。内容审核如果AI生成的推荐描述可能包含不受控的内容考虑接入内容安全审核API对输出进行二次过滤。隐私考虑如果涉及用户个人数据确保在Prompt中不泄露敏感信息并遵守相关的数据保护法规。4.5 迭代与评估A/B测试可以设计实验让一部分用户使用AI推荐另一部分用户使用规则推荐对比点击率、停留时长等业务指标量化AI带来的价值。反馈闭环在推荐结果旁边增加“有用/无用”的反馈按钮。收集到的反馈数据可以用于后续优化Prompt甚至作为数据来微调你自己的模型。版本化管理对Prompt、AI模型版本、降级规则等进行版本化管理。当做出更改时可以灰度发布观察效果。通过这个“AI旅游智能推荐助手”项目你实践的不是一个孤立的AI调用而是一套将AI能力产品化、工程化的完整方法论。你学会了如何在你熟悉的Java和Vue技术栈中为AI能力设计接口、处理异常、保障性能、控制成本。这才是从“前后端开发者”转向“AI全栈工程师”过程中最需要补上的那一块拼图。接下来你可以将这套模式复制到客服机器人、内容摘要、代码生成等无数场景中真正让AI为你所用。
返回列表