当前位置: 首页 > news >正文

Spring Boot + Vue 前后端联调踩坑记录

最近在搞那个 AI 内容创作平台 的前后端联调,踩了一堆坑,从 SSE 时序到参数类型,再到响应数据结构,一个接一个。

本文记录一下,大概有4个比较典型的。

SSE 连接时序竞争:Emitter 不存在

SSE Emitter 不存在, taskId=aef5eec7307b4532815a239c45cad95b GET http://localhost:5173/api/article/progress/xxx 500 (Internal Server Error)

后端用@Async跑 AI 生成文章的异步任务,但频繁报 “SSE Emitter 不存在” 错误。

原因分析

这是一个典型的时序竞争问题。

流程如下:

1. POST /article/create → 返回 taskId,同时 @Async 启动异步任务 2. 异步线程立即开始执行 AI 生成,尝试通过 sseEmitterManager.send() 推送消息 3. 前端拿到 taskId 后才建立 SSE 连接 GET /article/progress/{taskId}

如果步骤 2 比步骤 3 先发生,emitterMap中还没有该taskId对应的 Emitter,就会报错。

解决方案

在启动异步任务之前,先把 SSE Emitter 预创建好,放进 emitterMap 里,确保异步任务启动时,Emitter 已经存在了。

ArticleController.java调整一下顺序:

@PostMapping("/create")publicBaseResponse<String>createArticle(...){StringtaskId=articleService.createArticleTask(request.getTopic(),loginUser);// 关键:先预创建 SSE Emitter,放进 map 里sseEmitterManager.createEmitter(taskId);// 之后再启动异步任务,此时 Emitter 已经存在,可以安全发送articleAsyncService.executeArticleGeneration(taskId,request.getTopic());returnResultUtils.success(taskId);}

然后在SseEmitterManager.javacreateEmitter方法加个幂等判断,防止重复创建:

publicSseEmittercreateEmitter(StringtaskId){// 如果已经存在,直接返回已有的(支持预创建场景)SseEmitterexistingEmitter=emitterMap.get(taskId);if(existingEmitter!=null){returnexistingEmitter;}// ... 原来的创建新 Emitter 的逻辑}

修复后时序变为:

1. 创建任务 + 预创建 Emitter(放入 emitterMap) 2. 启动异步任务(此时 Emitter 已存在,可以安全发送) 3. 前端建立 SSE 连接(返回已预创建的 Emitter)

文章详情页参数传递类型错误

BusinessException: 文章不存在 at ArticleController.getArticle(ArticleController.java:106)

文章是创建成功了,但是,点击“查看文章”,前端页面却显示“文章不存在”。

原因分析

前端 API 函数getArticle期望接收一个对象{ taskId: string },但是,我在页面里直接传了个字符串:

// articleController.ts — 函数签名明确要对象exportasyncfunctiongetArticle(params:API.getArticleParams){const{taskId:param0,...queryParams}=paramsreturnrequest(`/article/${param0}`,{...})}// ArticleDetailPage.vue — 我直接传了字符串constres=awaitgetArticle(taskId)// 传入字符串

对字符串做解构后param0undefined,最终请求变成了/article/undefined

解决方案

老老实实传对象就行:

constres=awaitgetArticle({taskId})// 传 { taskId: xxx }

我的文章列表显示 “No data”

文章生成完成了,数据库里也有数据,但查看【我的文章】列表页却显示 “No data”。

原因分析

Axios 的完整响应结构是这样的:

res = AxiosResponse 对象 res.data = { code: 200, data: { records: [...], totalRow: 10 }, message: "ok" }

也就是说,实际的业务数据在res.data.data里,但我在前端直接取了res.data.records

// 错误写法 — res.data 是 { code, data, message },根本没有 records 属性dataSource.value=res.data.records||[]pagination.value.total=res.data.totalRow||0

当然是空的。

解决方案

老老实实多写一层.data

dataSource.value=res.data.data.records||[]pagination.value.total=res.data.data.totalRow||0

删除文章请求体格式错误

MismatchedInputException: Cannot construct instance of `DeleteRequest` (no int/Int-argument constructor/factory method to deserialize from Number value (5))

点击删除文章,后端直接报 Jackson 反序列化错误。

原因

后端接口用的是@RequestBody DeleteRequest,期望接收一个 JSON 对象,但我在前端直接传了个数字:

// 错误写法 — 请求体是数字 5awaitdeleteArticleApi(record.id)

Jackson 收到数字5,当然没法反序列化成DeleteRequest对象。

解决方案

老老实实传对象就行:

// 正确写法 — 请求体是 { "id": 5 }awaitdeleteArticleApi({id:record.id})
http://www.jsqmd.com/news/582640/

相关文章:

  • FIFA 23 Live Editor终极指南:10分钟掌握实时游戏修改技巧
  • 手把手教程:快速设置远程开机,看完就会
  • 每日 200 篇免费额度!PaperXie 查重:把论文安全感焊死在毕业季
  • 2026年五星酒店床垫推荐:五家优选品牌深度解析 - 科技焦点
  • Windows环境下安装TVM编译器
  • 5大核心优势:为多场景用户打造的屏幕翻译解决方案
  • 【头歌】操作系统 课堂练习2.3:系统调用
  • OpenMS实战指南:如何用开源工具解决质谱数据分析三大难题
  • 春游出发前买酒外卖来得及吗?歪马送酒大额券解锁春日微醺新方式 - 资讯焦点
  • 论文查重还在花冤枉钱?Paperxie 免费查重,本科生的毕业省钱神器
  • SQL优化让查询提升10倍——从数据库工程到执行计划深度解析
  • 2026海外网红营销内容合作与策划最佳实践
  • 数据分析之事实表(Fact Table)
  • 代码随想录算法训练营第一天 | Leetcode 704.二分查找 | Leetcode 27.移除元素 | Leetcode 977.有序数组的平方 (c#和c++双语)
  • 履约门槛再次大修!TikTok美区全面强制官方物流后,卖家该怎样守住前台账号的安全底线?
  • 露营烧烤喝什么精酿比较潮?歪马送酒大额券帮你省出潮饮预算 - 资讯焦点
  • AI辅助开发:让快马AI理解并生成ccswitch工具的核心逻辑与UI管理代码
  • AgentCPM-Report高效部署教程:GPU显存优化+流式输出配置详解
  • async/await:异步编程的“读心术”|从原理到避坑,一篇吃透!
  • 追剧想喝点酒外卖哪里买方便?歪马送酒大额券解锁便捷微醺 - 资讯焦点
  • 解决FTPS连接问题:从握手失败到成功连接的实战
  • 《Docker 部署 Elasticsearch + Kibana:搭建自己的日志搜索平台》
  • 117. 如何在Rancher监控中测试 AlertManager
  • GitHub 学生认证须知
  • 学会OpenClaw后,我的摸鱼时间又变长了
  • 如何通过LAV Filters解决媒体播放难题?开源解码工具完整优化指南
  • STM32H723ZGT6 与 STM32F103RCT6 硬核对比,从参数到实战的全维度精准解析
  • 2026最新户外文旅灯光设计厂家推荐!权威榜单发布,品质服务双优 - 十大品牌榜
  • LFM2.5-1.2B-Thinking-GGUF版本管理与协作:GitHub工作流中的AI助手
  • 苏州日料哪家优惠力度大?火地铁板烧口令解锁隐藏福利,性价比碾压同档门店 - 资讯焦点