资讯动态

AI大模型+Spring Boot+Vue非遗数字化管理系统全栈实战

发布时间:2026/10/3 9:10:50 来源:尧图企业网站定制
这套非遗数字化管理系统我前后做了大概一个半月真正动手敲代码的时间其实只有三周剩下的时间全花在需求梳理和文档整理上。这也印证了我一直以来的观点——基于AI大模型应用 Spring Boot Vue这种全栈项目真正的难点从来不是某一个技术点而是怎么把AI能力、Java后端、前端页面和一套实际业务揉在一起。如果您正打算做一个含金量高一点的毕业设计、课程设计或者个人作品这篇记录可以省下不少摸索时间项目拆解、技术选型、核心代码、部署细节和设计说明书写作要点都会覆盖到。项目的整体组合是Spring Boot 3 提供后端服务Vue 3 Element Plus 搭建管理端页面AI大模型应用通过统一封装接口对外暴露主要承担非遗智能问答、知识科普生成和讲解词翻译三类任务。系统并不是把非遗项目登记进数据库就完事而是把数字化采集、知识检索、内容生成串成一条完整链路。文章里凡是涉及代码的地方我会给出能直接复制的实现涉及设计说明书的地方也会把章节结构和写作思路写出来。1. 项目拆解非遗数字化管理系统到底在管什么1.1 业务全景与模块边界非遗数字化管理系统字面上是管理非遗但数字化才是真正的重心。早期做这类系统很多人容易把它做成一个简单的增删改查后台——非遗项目表、传承人表、新闻表、用户表再加几个页面就收工。这样不是说不行但数字化三个字没有体现AI更是无从谈起。我最后落地的模块是这样拆的非遗资源库管理非遗项目国家级、省级、市级分类申报批次申报地区传承方式、传承人档案、非遗视频/图片/音频/文献资料。这是整个系统的数据底座后面所有AI能力都依赖这个库。数字化采集与加工视频转码切片、图片压缩、OCR识别、音频转文字把线下散落的资料变成线上结构化数据。这一步决定了资料能不能被AI有效使用。AI知识服务面向公众和管理人员提供非遗智能问答、知识科普自动生成、多语言讲解。这一层是大模型应用的核心承载也是系统的亮点。业务管理活动申报、展览安排、文创商品管理、用户权限管理、数据统计。这部分是传统管理系统的部分技术难度不大但工作量不小。模块边界一定要在开发前画清楚否则AI服务很容易和业务模块缠在一起。我采用的原则是AI服务单独成一个模块只依赖资源库的数据接口不直接操作业务表。这样即便大模型接口出了故障基础增删改查功能还能正常跑不会出现AI挂了整个后台都用不了的尴尬局面。实际开发中我还加了一层开关通过配置项控制AI功能是否启用演示和答辩时可以随时切换这个细节对现场演示很有用。1.2 AI大模型应用的真实落点很多人一听说基于AI大模型第一反应是让系统能对话。对话只是表象真正要解决的是知识检索和内容生成两个问题。非遗资料散落在PDF、Word、网页和口述录音里用户想查一个冷门非遗项目传统模糊匹配效果很差。我用的方案是检索增强生成RAG先把文档切分、向量化存入知识库用户提问时先检索相关片段再让大模型基于这些片段生成回答。比如游客问蜀绣和湘绣到底有什么区别传统系统用SQL的LIKE去匹配可能只命中蜀绣两个字然后把几百字的介绍整页丢出来RAG方案会先检索到两个绣种的工艺、针法、产地资料再让大模型组织成一段200字左右的对比回答。这一步才是AI大模型应用在系统里真正的价值不是让AI回答泛泛的问题而是让它基于你自己的知识库干活。内容生成方面我做了三个实用功能根据传承人档案自动生成简介、根据非遗项目信息生成讲解词、根据展览主题生成前言。这类任务不需要特别强的推理但要模板规范、事实准确用提示词约束就能做到不错的水平。翻译功能则是把中文非遗介绍交给模型翻译成英文和日文供外宾参观场景使用效率比传统人工翻译高很多。整体设计上我把AI能力封装成三个接口问答接口、内容生成接口、翻译接口前端所有带AI字样的功能都走这三个接口后台只负责配置模型参数和知识库文档。这套设计的最大好处是AI模块可以独立替换以后换模型服务商业务代码基本不用动。2. 技术选型与开发环境为什么是 Spring Boot 3 Vue 32.1 后端选型与IDEA社区版的实操方式后端选型时不少人在Spring Boot和Python FastAPI之间纠结。如果纯做AI应用FastAPI确实香Python的大模型生态太成熟了。但非遗管理系统本质上是一个业务系统有用户、权限、文件、工作流需要大量CRUD和事务管理。Spring Boot在这块的成熟度太高了MyBatis-Plus做持久层、Spring Security做权限、Spring Data Redis做缓存一条龙下来几乎不用造轮子。我的做法是业务系统用JavaAI能力通过HTTP调用模型平台既没有引入Python技术栈的运维成本又拿到了大模型能力。版本上我选了Spring Boot 3.2.x搭配Java 17。这里有个容易踩坑的点Spring Boot 3把javax包迁移成了jakarta包很多老教程、老依赖会直接报错网上一搜全是Spring Boot 2.x的配置照抄会翻车。如果用Spring Boot 3Spring Security也必须是6.x版本配置方式和2.x差别很大后面权限章节我会单独讲。如果你用的是IDEA社区版免费版里面没有Spring Boot项目向导。我的解决办法是打开 start.spring.io 网站选Maven、Java 17、Spring Boot 3.2.x勾上Web、Validation、MySQL Driver、Redis等依赖生成项目压缩包后解压再用IDEA打开。社区版完全能写Spring Boot只是没有图形化创建按钮启动就走Application类的main方法跑起来没有任何区别。记得在IDEA的插件市场装Lombok插件否则实体类的Data注解不生效编译会报找不到getter和setter。2.2 前端栈与基础设施Vite 5、Element Plus 与Node环境前端选了Vue 3.4 Vite 5 Element Plus Pinia Vue Router。这套组合是当前社区最稳的方案资料多、招聘需求也大和Spring Boot属于毕业设计黄金套餐后续写设计说明书也顺手。为什么不选Vue 2项目是全新的没理由用老技术。为什么不选React个人全栈项目Vue在国内的社区资料更丰富Vue Router和Element Plus对管理端场景支持很成熟。环境配置上Node.js必须用18以上版本Vite 5对Node版本有要求。装依赖前先把npm源切到国内镜像别问我为什么强调这一点直接跑一次npm install就知道什么叫怀疑人生。脚手架用npm create vitelatest创建选择Vue和JavaScript——个人项目用JavaScript能更快交付团队项目建议上TypeScript。Element Plus有两种用法小型项目直接全局引入app.use(ElementPlus)三行代码搞定大项目用unplugin-auto-import和unplugin-vue-components做按需导入打包体积更小。我建议个人项目先用全局引入先把功能做完性能优化放到后面再考虑。3. 核心代码讲解AI大模型接入与非遗知识库问答3.1 统一大模型客户端OkHttp流式解析SSEAI模块的核心是一个兼容主流模型服务商接口的客户端。现在大多数模型平台都提供兼容OpenAI协议的接口请求和响应格式统一所以我做了个独立的AiChatClient把HTTP调用、流式解析、错误处理都封装在里面。用OkHttp而不是RestTemplate是因为RestTemplate在Spring Boot 3里已经进入维护期WebClient是响应式的对流式SSE虽然也能支持但OkHttp用起来更直观连接超时和逐行读取都好控制。依赖就两个OkHttp和fastjson2。Component public class AiChatClient { private static final Logger log LoggerFactory.getLogger(AiChatClient.class); private final OkHttpClient httpClient new OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .build(); Value(${ai.base-url}) private String baseUrl; Value(${ai.api-key}) private String apiKey; Value(${ai.model}) private String model; public void streamChat(String systemPrompt, String userMessage, ConsumerString tokenConsumer) { JSONObject payload new JSONObject(); payload.put(model, model); payload.put(stream, true); payload.put(temperature, 0.3); JSONArray messages new JSONArray(); JSONObject system new JSONObject(); system.put(role, system); system.put(content, systemPrompt); messages.add(system); JSONObject user new JSONObject(); user.put(role, user); user.put(content, userMessage); messages.add(user); payload.put(messages, messages); Request request new Request.Builder() .url(baseUrl /chat/completions) .header(Authorization, Bearer apiKey) .post(RequestBody.create(payload.toJSONString(), MediaType.parse(application/json; charsetutf-8))) .build(); try (Response response httpClient.newCall(request).execute()) { if (!response.isSuccessful()) { throw new RuntimeException(AI接口调用失败HTTP状态码 response.code()); } ResponseBody body response.body(); if (body null) { return; } BufferedReader reader new BufferedReader( new InputStreamReader(body.byteStream(), StandardCharsets.UTF_8)); String line; while ((line reader.readLine()) ! null) { if (line.startsWith(data:)) { String data line.substring(5).trim(); if ([DONE].equals(data)) { break; } JSONObject json JSONObject.parseObject(data); JSONArray choices json.getJSONArray(choices); if (choices null || choices.isEmpty()) { continue; } JSONObject delta choices.getJSONObject(0).getJSONObject(delta); String token delta.getString(content); if (token ! null !token.isEmpty()) { tokenConsumer.accept(token); } } } } catch (IOException e) { log.error(AI流式调用失败, e); throw new RuntimeException(e); } } }这段代码有几个关键点。第一stream参数必须设置为true否则接口会等全部生成完才返回用户端体验很差。第二readTimeout给到60秒长文本生成很容易超过30秒。第三SSE的每一行都是以data:开头的收到[DONE]表示生成结束这两个约定是所有兼容OpenAI协议的模型平台都遵循的。我已经把超时时间、模型名称、接口地址都放到了application.yml里切换模型服务商时不用改代码只改配置就行。3.2 RAG知识库向量切分、检索与提示词拼接RAG部分设计成两个模块文档处理模块负责把非遗资料切分、向量化并存储检索模块负责计算相似度、召回最相关的片段。文档切分是很容易被忽视但极其重要的环节我的策略是优先按文档原有的章节标题切每个片段控制在300到500字相邻片段重叠50字这样能防止段落上下文在切分处被截断。切完之后调用模型平台的Embedding接口把每段文字转成向量。这里有个工程上的取舍为什么不直接上向量数据库因为文档量在几千条以内时把向量存到MySQL的一个单独表查询时全表扫一遍算余弦相似度耗时也就几毫秒到几十毫秒完全够用。引入Milvus或Elasticsearch反而增加了部署和维护成本。等以后文档量到百万级再迁移也不迟这种渐进式架构对个人项目非常友好。检索实现如下Service public class KnowledgeBaseService { Resource private KnowledgeChunkMapper chunkMapper; public ListKnowledgeChunk searchTopK(float[] queryVector, int topK) { ListKnowledgeChunk all chunkMapper.selectList(null); ListKnowledgeChunk ranked new ArrayList(); for (KnowledgeChunk chunk : all) { double score cosineSimilarity(queryVector, chunk.getVector()); chunk.setScore(score); ranked.add(chunk); } ranked.sort((a, b) - Double.compare(b.getScore(), a.getScore())); return ranked.stream().limit(topK).collect(Collectors.toList()); } private double cosineSimilarity(float[] a, float[] b) { double dot 0, normA 0, normB 0; for (int i 0; i a.length; i) { dot a[i] * b[i]; normA a[i] * a[i]; normB b[i] * b[i]; } return dot / (Math.sqrt(normA) * Math.sqrt(normB) 1e-8); } }检索到TopK片段之后把它们拼进系统提示词再调用大模型。提示词的设计比大多数人想象的重要我实际用的版本是这样的你是一名非物质文化遗产领域的专业讲解员。 请只根据下面提供的资料片段回答用户问题。 资料中没有的内容要明确回复资料中暂未找到相关信息不要编造。 【资料1】... 【资料2】...这段提示词里不要编造四个字非常关键。大模型训练数据里可能包含非遗相关的信息但很可能和你系统里的资料不一致。如果不明确限定只根据资料回答模型就会自由发挥把错误信息当作事实说出来。我在实际测试中发现加了RAG和这条限定之后回答的准确性从大约六成提升到九成以上效果非常明显。3.3 Vue端流式接收fetch ReadableStream前端接收流式响应时要注意axios底层是基于XHR的虽然能拿到响应内容但流式事件的处理很不直观。我用的是fetch ReadableStream既能处理GET请求也能轻松应对POST和自定义Header。大模型返回的内容是标准SSE格式每行以data:开头逐帧解析并追加到页面即可。async function streamChat(question) { const response await fetch(/api/ai/chat?question encodeURIComponent(question), { headers: { Accept: text/event-stream } }) const reader response.body.getReader() const decoder new TextDecoder(utf-8) let buffer while (true) { const { value, done } await reader.read() if (done) break buffer decoder.decode(value, { stream: true }) const lines buffer.split(\n) buffer lines.pop() for (const line of lines) { if (line.startsWith(data:)) { const data line.slice(5).trim() if (data [DONE]) continue answerText.value data answerHtml.value marked.parse(answerText.value) } } } }buffer的处理是这段代码的隐藏重点。网络传输过程中一个SSE事件可能被拆成多个数据帧到达如果每次都直接把data:行拿来解析会遇到内容被截断的情况。我先把所有收到的数据追加到buffer里再按换行符切分最后把最后一行留回buffer继续拼接这样能保证每个事件被完整处理。渲染方面大模型返回的是Markdown格式我用marked库转成HTML展示同时用DOMPurify做了一次清洗防止模型输出内容里夹带不安全的HTML标签。风格上还做了一个打字机效果配合流式刷新用户能直观看到文字逐字出现互动感强很多。4. 数字化资源管理视频、文件与监控的工程化方案4.1 非遗视频的HLS切片与Vue播放器非遗资源里视频是重头戏老艺人技艺展示、非遗项目实地拍摄、传承人口述访谈动辄几百MB甚至几GB。管理端上传后如果直接让前端播放mp4文件大文件会在拖动进度条时卡顿而且各浏览器兼容性参差不齐。我的方案是统一用FFmpeg把视频转码成HLS格式生成m3u8索引文件和ts切片前端用hls.js播放。FFmpeg转码命令看起来很简单参数却有不少讲究ffmpeg -i input.mp4 -c:v libx264 -c:a aac -hls_time 10 \ -hls_list_size 0 -hls_segment_filename output_%03d.ts output.m3u8-hls_time 10表示每10秒切一个切片文件-hls_list_size 0表示保留所有切片不循环覆盖。如果要做多码率适配可以再加-filter_complex做视频缩放分别生成720p和1080p两个版本的m3u8再用主m3u8文件引用子m3u8。不过个人项目里我建议先生成单码率跑通整个链路后再优化否则FFmpeg的参数调试会占掉大量时间。前端播放器组件用hls.js兼容性处理是重点。Safari浏览器原生支持HLS直接设置video元素的src就能播放Chrome和Firefox不行必须引入hls.js来转码播放。组件里先判断videoElement.canPlayType(application/vnd.apple.mpegurl)能播放就直接用原生否则走hls.js分支。播放器我用的video.js hls.js的组合UI控件、字幕、清晰度切换都现成比自己封装省事。4.2 文件存储与MinIO配置与异步化视频、图片这类大文件直接用Java接收MultipartFile保存到本地磁盘是最简单的方案开发环境足够用。但文件量一多分散在磁盘各处备份和迁移会很痛苦。我采用的方式是开发环境用本地磁盘通过Nginx或Spring Boot的静态资源映射暴露访问路径生产环境切换到MinIO对象存储两者对外接口统一后端服务感知不到差异。MinIO的配置不复杂依赖和连接Client封装好之后上传就是一个方法的事Configuration public class MinioConfig { Value(${minio.endpoint}) private String endpoint; Value(${minio.access-key}) private String accessKey; Value(${minio.secret-key}) private String secretKey; Bean public MinioClient minioClient() { return MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } }上传接口里要特别注意文件名的处理。直接用用户上传的原始文件名有两个风险一是可能包含路径和恶意字符二是多个用户可能上传同名文件造成覆盖。我的做法是使用UUID.randomUUID()生成新的对象名再拼接原始文件名的后缀既能避免冲突又能保留扩展名供浏览器识别类型。上传大视频时接口很可能超时所以要异步化上传成功后立即返回已上传正在处理的状态后台线程池执行转码、截取封面、更新数据库等耗时操作前端通过轮询或WebSocket获取进度。如果不想引入消息队列用Spring的CompletableFuture.runAsync加状态字段就能撑住个人项目的并发量。4.3 Spring Boot Admin监控与WebSocket进度推送系统上线后有几个指标必须盯内存占用、接口响应时间、异步任务积压数量。Spring Boot Actuator已经提供了基础的监控端点但页面上一个个查JSON太难受了我直接引入Spring Boot Admin。方式很取巧新建一个独立的管理端模块启动类上加EnableAdminServer注解这个模块跑在一个独立端口上业务模块引入spring-boot-admin-starter-client在yml里配置spring.boot.admin.client.url指向管理端地址业务服务的信息就会自动上报上去。管理端界面能看到服务列表、实时内存曲线、HTTP接口调用统计还能动态调整日志级别排查生产问题非常有用。这里有个很多人容易犯的错Spring Boot集成WebSocket时到处找yml配置项。实际上原生WebSocketServerEndpoint方式不需要在application.yml里写任何专用配置只需要注册一个ServerEndpointExporter的Bean再写一个ServerEndpoint注解的配置类就行。Spring的STOMP方案也是在配置类里addEndpoint注册路径yml里默认没有全局开关。网上一堆教程往yml里塞自定义的websocket配置那些基本都是瞎写。我实际做视频转码进度推送时用WebSocket把任务状态推给管理端页面整个WebSocket模块的配置加起来不到20行代码。5. 前后端联调、权限部署与关键配置5.1 开发环境联调Vite proxy与CORS取舍开发阶段前后端分离前端跑在5173端口后端跑在8080端口必然面临跨域问题。解决跨域有两条路一条是后端配置CORS另一条是前端配置Vite代理。我强烈推荐Vite代理因为开发环境下代理方案不需要后端做任何额外配置浏览器请求的是5173端口Vite在本地把请求转发到8080浏览器根本感知不到跨域的存在。// vite.config.js server: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }如果选择后端CORS方案需要注意allowCredentials(true)和allowedOrigins不能使用通配符*必须明确写出允许的域名否则带Cookie的请求会失败。个人项目建议直接引入spring-boot-starter-validation做参数校验Controller的Valid注解加DTO校验字段比手写一堆if判断清爽太多。接口返回结构我统一封装成ResultT包含code、message、data三个字段前端axios拦截器统一处理错误码这样接口写多了之后维护成本并不会线性增长。5.2 权限路由Vue动态路由与Spring Security配合管理端有超级管理员、内容编辑员、审核员三种角色各自的菜单和操作权限不同。前端的做法是动态路由登录成功后后端返回当前用户的角色和菜单权限前端根据这个列表动态生成路由调用router.addRoute注册到路由实例。const dynamicRoutes generateRoutes(menus) dynamicRoutes.forEach(route router.addRoute(route))这里有个细节未登录用户第一次进入页面时默认只能访问登录页其他路由都不存在。一旦登录成功动态添加的路由才会生效。为了防止刷新页面后路由丢失我在Vuex/Pinia里持久化了菜单信息刷新时重新从后端拉取。路由守卫里还做了另一层判断访问的后端接口如果没有权限后端会返回403前端弹出无权限提示。前端的动态路由更多是为了交互体验真正的安全防线必须放在后端不能只靠隐藏按钮。后端权限用的是Spring Security 6 JWT。Spring Boot 3下要开启方法级权限用的是EnableMethodSecurity注解不再是Spring Boot 2时代的EnableGlobalMethodSecurity这一点很多人会踩坑。接口上用PreAuthorize(hasRole(ADMIN))控制访问权限比如删除非遗项目这个操作只有管理员能调编辑员只能编辑内容不能删除。5.3 生产部署Vue打包进Spring Boot的两种方式部署方案我踩过不少坑最后稳定下来的是两根路线。路线一是前后端分离部署前端打包后放到Nginx静态目录后端独立跑在8080通过Nginx反向代理把/api路径转发到后端。路线二是单包部署执行npm run build后把dist目录复制到Spring Boot的src/main/resources/static打成一个jar包端口和静态资源全由Spring Boot管理。对毕设和个人项目来说路线二更省事一个jar包直接java -jar就完事演示环境部署非常快。但路线二有个经典坑Vue Router用history模式时前端路由是虚拟路径比如/admin/items刷新页面时Spring Boot会去静态目录找admin/items这个文件找不到就返回404。解决方法是加一个Spa转发Controller把所有不带扩展名的路径都转发到index.htmlController public class SpaForwardController { GetMapping(value {/, /{path:[^\\.]*}, /{path:[^\\.]*}/{rest:[^\\.]*}}) public String forward() { return forward:/index.html; } }注意这里必须用forward而不是redirectredirect会让浏览器地址栏变成index.html视觉上很怪forward是服务器内部转发URL不变。正则里的[^\.]*是为了排除带点号的静态资源比如/assets/app.js这种请求会走正常静态资源映射不会被拦截。6. 设计说明书编写从代码到文档的转化要点6.1 设计说明书的标准结构与每章写作重点项目能跑起来只是第一步文档写不好答辩和验收会非常吃亏。非遗数字化管理系统这种业务系统 AI应用的组合说明书结构一般按八章来写绪论、相关技术介绍、需求分析、总体设计、详细设计、系统实现、系统测试、总结与展望。绪论部分最容易被忽略的是研究现状。非遗数字化是全球性的议题欧盟有文化遗产数字化项目中国各地方也在推进非遗数据库建设这些内容写进国内外研究现状可以瞬间提升论文的文献支撑感。需求分析章节除了功能需求还要写非功能需求比如系统响应时间、并发用户数、数据安全等级。总的架构建议画一张大图前端Vue展示层、后端Spring Boot服务层、数据存储层再加一个独立的AI服务模块放旁边说明清楚数据流方向。这张图在毕业设计答辩里往往是评委第一个盯的地方。6.2 数据库设计与图表工具数据库设计要跟着功能走我把核心表整理成了一张表文档里直接照着这个结构写表名说明关键字段sys_user用户表id, username, password, real_name, role_idsys_role角色表id, role_code, role_namenon_heritage_item非遗项目表id, name, level, batch, category, region, status, contentinheritor传承人表id, name, item_id, level, phone, photo, storyvideo_asset视频资源表id, item_id, title, original_name, oss_url, hls_url, cover_url, statusknowledge_chunk知识库切片表id, source_id, content, vector_json, embedding_model表之间的关系不用画得太复杂E-R图里把主外键关系画清楚就行。工具方面draw.io画架构图和E-R图完全够用ProcessOn在线协作也不错数据库表结构用数据库客户端导出SQL然后在文档里贴核心建表语句就够不需要把所有表结构都贴进去。要注意一点文档中的表字段必须和实际数据库一致很多人写完代码再凭记忆写文档字段名对不上答辩时被问数据库设计就傻眼。6.3 含AI模块的设计说明书怎么写既然标题里写了基于AI大模型应用说明书里AI相关的内容就不能只是简单提一句。我建议专门用一个章节写AI模块设计至少包含五块内容模型选型对比、Prompt设计、RAG流程、知识库构建、评测结果。模型选型对比可以列一个表格对比不同模型在非遗问答场景下的优劣势、调用成本、部署方式。Prompt设计要把实际使用的系统提示词贴出来并说明为什么这么写。RAG流程画一个从左到右的流程图文档导入、文本清洗、切片、向量化、存储查询时问题编码、向量检索、拼接上下文、模型生成。知识库构建部分写清楚切片大小、重叠策略、向量存储方案。最关键的是评测结果我实际做了30个非遗相关问题的测试集分别测试直接问大模型和RAG 大模型两种模式把回答准确率对比数据做成了表格放在说明书里。这个评测数据在答辩现场的效果非常好评委看到量化结果后基本不会再纠结AI功能是不是摆设。7. 常见问题与避坑记录7.1 开发期的五个高频坑围绕这套系统开发时遇到的实际问题我整理成了一份问题速查表按解决成本从低到高排列问题现象原因与解决办法IDEA社区版没有Spring Boot向导新建项目找不到Spring Initializr选项去start.spring.io生成项目包再导入或用Maven手动创建pom.xmlSpring Boot 3项目编译报javax不存在引入的某个依赖还在用javax包把依赖升级到兼容jakarta的版本代码里javax.*全部改成jakarta.*npm install卡住不动依赖下载极慢或报网络错误先执行npm config set registry https://registry.npmmirror.com再重新安装前端打包后放Spring Boot刷新404刷新深层路由白屏加SPA转发Controller把无扩展名路径forward到index.htmlSpring Security 6的注解不生效加了PreAuthorize但没拦截确认启动类上用了EnableMethodSecurity而不是老注解这些问题看起来简单但每一个都花了我不少时间搜索。印象最深的是javax和jakarta的问题系统里引入了一个老版本的工具包编译时疯狂报错一开始以为是自己代码写错了后来才发现是依赖兼容性。所以用Spring Boot 3做项目依赖版本一定要尽量用最新的别迷信老教程里的版本号。7.2 运行期的四个排查思路系统跑起来之后会有一类更难查的问题接接口没反应、页面一直转圈、视频播不出来这类问题的排查思路我总结了四个方向现象排查方向关键检查点SSE接口一直不出内容后端的响应是否被缓冲Controller返回类型是否为text/event-streamSseEmitter是否正常send并flushfile输入大视频上传超时Spring和Nginx两层限制spring.servlet.multipart.max-file-size和max-request-sizeNginx的client_max_body_sizem3u8视频播放白屏跨域和MIME类型MinIO或Nginx是否正确配置Access-Control-Allow-OriginContent-Type是否为application/vnd.apple.mpegurlAI回答的内容明显编造知识库检索是否真的命中查看检索日志看召回片段是否相关如果没召回检查Embedding向量模型是否一致最后一条是我最想强调的。AI回答内容编造十次里有八次不是模型问题而是知识库没检索到相关内容模型只能自由发挥。上线前我把非遗知识库里的文本做了一轮清洗把PDF转换带来的乱码、页眉页脚都处理掉检索命中率才显著提升。数据质量是AI系统的生命线这个理念在非遗数字化系统里体现得淋漓尽致。7.3 个人对这类项目的一点体会整个项目做完我最深的体会是这类系统的技术框架其实不复杂真正决定成败的是数据能不能喂好。Spring Boot写CRUD、Vue写页面网上教程一抓一大把但能说清楚非遗资料如何清洗、切分、向量化如何设计提示词才能让模型给出可靠回答的内容非常稀缺。如果你也准备做类似的项目我建议先花三天时间把业务数据梳理清楚哪怕先找一个具体的非遗项目做试点把它的全流程资料走通再扩展成整个系统。这样开发节奏会稳很多。还有一个小建议视频转码和文件存储这类基础设施不要一开始就追求高大全的视频平台方案。先实现本地上传FFmpeg转码浏览器播放跑通链路之后再考虑对象存储、CDN、多码率这些优化循序渐进比一步到位可靠。这个系统后续如果要扩展可以增加小程序端后端接口和知识库完全可以复用工作量主要集中在登录适配和视频播放器选型上。代码里多留一点扩展的余地后面会感谢自己。最后分享一个调SSE时的小技巧后端开发时直接打开浏览器访问接口地址如果能看到一行行data:内容滚动输出说明流式链路是通的如果等到最后才一次性输出就该检查是不是哪里做了缓冲。这个简单的判断方法帮我快速定位过不少问题比反复看前端截图高效得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑