多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

SpringBoot+小程序+Vue前后端分离视频分享小程序开发全解

SpringBoot+小程序+Vue前后端分离视频分享小程序开发全解 “springboot基于微信小程序的搞笑视频分享浏览小程序”这套标题在毕设和课设圈子里见得太多了。它其实点了一条很典型的前后端分离技术链路SpringBoot 做服务端接口小程序做 C 端浏览再配一个 Vue 管理后台来维护内容。很多人拿到这种项目代码能跑起来是一回事真正搞清楚每个环节为什么这么设计、部署上线会踩哪些坑又是另一回事。这篇文章就以这个视频小程序为例子从项目拆解、表结构设计、接口实现、视频存储、小程序联调、Vue 后台、部署调试到问题排查完整走一遍把我做类似项目时积累的经验都写出来。1. 项目整体设计与技术选型思路1.1 这个项目到底在解决什么问题从用户视角看这就是一个搞笑视频的浏览工具进入小程序看到瀑布流式的短视频列表点开即播可以点赞、评论、收藏也可以按分类去刷。管理员的活则在后台完成也就是上传视频、审核内容、下架违规视频、查看用户数据。这类项目的核心价值在于验证一套“内容型小程序”的标准开发流程。搞笑视频只是一个内容形态换成美食教程、宠物日常、健身动作库架构完全不用变。所以做这个项目时我建议你不要只盯着“搞笑视频”这四个字而是把它当成一个通用的内容分发小程序来做这样以后找工作写简历时描述空间会大很多。1.2 为什么是 SpringBoot 微信小程序 Vue 这套组合我经常被问到为什么后端不用 Node.js、不用 PHP小程序不用 uniapp其实没有绝对的对错只有场景适配。SpringBoot 是 Java 生态里上手成本最低的 Web 框架内置 Tomcat起步依赖把配置都简化了而且国内公司尤其是中小型系统Java 后端依旧是主流。面试时聊分布式、微服务也都是从 SpringBoot 延伸出去的。微信小程序是 C 端形态里“所见即所得”的选择不需要上架 App Store开发工具现成用户扫码即用。视频浏览这类场景微信的 video 组件天然支持不用自己造播放器轮子。Vue 管理后台是目前前后端分离项目中最常见的后台方案Element UI 一套组件库就能把表格、表单、弹窗全部搞定拿来管视频数据非常顺手。这套组合的本质就是SpringBoot 只对外提供 JSON 接口小程序和 Vue 后台各自消费这些接口。三个项目互不干扰开发效率高职责边界也清楚。1.3 “前后端分离”在这次项目里的具体形态这里要展开说清楚。标题里的“前后端分离”不是指 SpringBoot 把页面丢给 Vue而是说整个系统被拆成了三个独立工程API 服务端SpringBoot端口一般设成 8080负责登录、视频列表、点赞评论等所有业务逻辑。小程序端微信开发者工具里运行的原生小程序WXML、WXSS、JS通过 wx.request 请求后端接口。管理后台端Vue Element UI端口 8081开发环境用代理跳转管理员登录后维护视频和用户。三者之间通过 HTTP JSON 通信。小程序和后台都不直接访问数据库数据库只对 SpringBoot 开放。我第一次做这类项目时最大认知转变就在这写后端的人不关心数据最终怎么展示只保证接口的输入输出约定稳定。前端也不关心数据存哪个表只关心接口返回什么字段。对接的核心就是接口文档。提示前后端分离项目里最大的坑往往不是代码而是接口约定变了之后两边没同步。项目一开始就维护一份简单的接口文档哪怕只是 Markdown 表格都能省下大量联调时间。2. 数据库设计与核心接口建模2.1 核心表结构的设计逻辑视频分享小程序我把数据库拆成六张核心表用户表、视频表、分类表、评论表、点赞表、收藏表。再加一张浏览记录表也不复杂但小型项目可以先省掉等以后做大点再补。用户表userCREATE TABLE user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, openid VARCHAR(64) UNIQUE NOT NULL COMMENT 微信openid唯一, nickname VARCHAR(64) DEFAULT 微信用户, avatar VARCHAR(255) DEFAULT , phone VARCHAR(20) DEFAULT , status TINYINT DEFAULT 1 COMMENT 1正常 0禁用, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里有两个关键点。第一openid 必须加唯一索引这是用户身份的锚点同一个微信用户反复登录时先查 openid 再决定注册还是直接返回用户信息。第二所有文本字段的排序规则我用的是 utf8mb4因为用户昵称里可能出现 emoji 表情MySQL 老版本 utf8 是存不了的。视频表videoCREATE TABLE video ( id BIGINT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(128) NOT NULL COMMENT 视频标题, cover_url VARCHAR(255) DEFAULT COMMENT 封面图地址, video_url VARCHAR(255) NOT NULL COMMENT 视频播放地址, category_id BIGINT DEFAULT NULL COMMENT 分类id, user_id BIGINT DEFAULT NULL COMMENT 上传者id可能为空, duration INT DEFAULT 0 COMMENT 时长秒, play_count INT DEFAULT 0 COMMENT 播放数, like_count INT DEFAULT 0 COMMENT 点赞数, status TINYINT DEFAULT 0 COMMENT 0待审核 1已发布 2已下架, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;status 字段值得单独拿出来讲。内容型平台对内容审核是有强需求的如果不加状态控制用户随手就能刷到未审核的视频后台审核机制就形同虚设。我的习惯是把状态数字枚举清楚0 待审核、1 已发布、2 已下架。列表接口默认只查 status1后台则可以根据状态筛选。分类表很简单id、名称、排序号。分类建议控制在六个以内否则瀑布流页面会出现“分类栏比视频内容还长”的尴尬情况。点赞和收藏表的核心其实是联合唯一索引CREATE TABLE video_like ( id BIGINT PRIMARY KEY AUTO_INCREMENT, video_id BIGINT NOT NULL, user_id BIGINT NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_video_user (video_id, user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这个联合唯一索引是防重复点赞的底线。不管前端按钮点了多少次数据库层面就能把重复数据卡掉。实际开发中我要么在 Service 层先查一次要么直接 try-catch 这个唯一索引的 DuplicateKeyException后一种在高并发下更可靠。2.2 视频列表接口分页与排序怎么定视频列表页是最核心的接口它同时要解决分页、排序、分类筛选三个问题。我推荐的做法是统一用 POST body 传参而不是 GET 带一堆 query 串因为参数多起来之后GET 的请求行长度和可视化调试都不太友好。请求参数设计{ page: 1, size: 10, categoryId: 1, orderBy: newest }orderBy 支持两个值newest 按发布时间倒序hot 按 play_count 倒序。SQL 层用 MyBatis-Plus 的 LambdaQueryWrapper 来拼条件LambdaQueryWrapperVideo wrapper new LambdaQueryWrapper(); wrapper.eq(Video::getStatus, 1) .eq(categoryId ! null, Video::getCategoryId, categoryId) .orderByDesc(hot.equals(orderBy), Video::getPlayCount) .orderByDesc(newest.equals(orderBy), Video::getCreateTime);这里的 eq 方法第二个参数是布尔值条件condition 为 true 才拼接该条件对筛选这种可选项非常合适。分页用 MyBatis-Plus 内置的分页插件配置一个 MybatisPlusInterceptorBean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; }然后 Service 层直接PageVideo page videoMapper.selectPage(new Page(page, size), wrapper);返回值封装成统一的 Result 结构。我习惯把所有接口的返回值规范成{ code: 200, message: success, data: { records: [], total: 100, page: 1, size: 10 } }小程序端拿到 data.records 渲染列表数据量大了之后底层自动变成 limit 0,10不用手动拼 SQL。注意分页 page 参数从 1 开始还是从 0 开始前后端一定要约定好。我踩过一次坑前端习惯了从 0 传后端 MyBatis 默认从 1 开始结果第三页开始永远丢一条数据。项目里统一从 1 开始前端首屏页码就是 1直觉上也顺。2.3 微信登录与 token 机制小程序登录流程和传统网页登录不同它没有账号密码核心是 code 换 openidopenid 就是用户的唯一身份。流程小程序端调用wx.login()拿到临时 code。小程序把 code 发给后端/api/auth/login。后端拿着 code 去微信接口服务换 openid需要 appid 和 secret。后端查 user 表openid 存在则直接登录不存在则自动注册。后端生成一个 token我习惯用 UUID 或者 JWT返回给小程序。小程序后续请求在 header 里带上 token后端通过拦截器解析出用户身份。登录接口核心逻辑PostMapping(/auth/login) public Result login(RequestBody LoginRequest req) { String code req.getCode(); // 调微信接口用code换取openid String openid wechatService.codeToOpenid(code); User user userMapper.selectOne(new LambdaQueryWrapperUser() .eq(User::getOpenid, openid)); if (user null) { user new User(); user.setOpenid(openid); userMapper.insert(user); } String token UUID.randomUUID().toString().replace(-, ); // token存redis或者内存map实际项目用redis tokenStore.put(token, user.getId()); return Result.success(new LoginVO(token, user)); }这里有个很实际的问题code 只能用一次而且 5 分钟内有效。后端和微信交互时如果网络抖动导致超时重新发起时 code 已经作废这是高频报错点排查时要先确认是不是 code 过期导致的。token 存储我提一下两种方案。课设级别可以用 ConcurrentHashMap 存前端项目重启 token 就失效用户得重新登录可以接受。正式项目一定要上 Redis缓存 key 是 tokenvalue 是 userId设置过期时间比如 7 天。判断登录就是在拦截器里检查 Redis 里有没有这个 key。2.4 点赞、评论、播放量计数的细节点赞接口看似简单就是 update 一个数字但有两个细节值得注意。第一点赞状态要双向判断。视频详情页初次渲染时需要根据当前用户是否点过赞来显示“已点赞”还是“未点赞”的 UI 状态。我每次查列表时会额外查一张 like 表把当前用户点赞过的 videoId 集合查出来放到一个 Set 里然后给返回的每个视频打个 isLike 字段。第二播放量计数和点赞计数的“最终一致性”问题。播放量如果是每次播放请求都去 update video 表数据库压力会随着用户量增大而上升。小型项目直接 update 没问题但如果未来用户量大了正确的做法是先把播放量更新到 Redis每隔几分钟做一次批量落库。这个属于扩展性设计这篇文章里点到为止等你真的遇到性能瓶颈再优化也不迟。评论区设计也有一点要提醒。评论表不需要存用户名和头像只存 user_id查询时再用 join 或者二次查询把用户昵称头像查到并拼装返回。这样用户改昵称时评论历史自动跟着变不用回改评论表。3. 视频存储与播放链路3.1 视频文件存在哪里本地磁盘 vs 对象存储视频文件的存储是这类项目最容易忽略、上线后最容易翻车的环节。我先说结论如果只是课设演示把视频存放在服务器本地指定目录就够了如果要上真实运营千万别省用云厂商的对象存储。本地存储实现很简单。SpringBoot 配置一个虚拟路径映射把/upload/**映射到磁盘目录例如/data/videos/。上传接口用 MultipartFile 接收文件然后按日期建子目录存储避免单个目录文件过多。# application.properties upload.video.path/data/videos/ upload.video.url-prefix/upload/对应的 WebMvcConfig 里加一个 addResourceHandlersOverride public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadVideoPath); }这样服务器上/data/videos/abc.mp4就能通过http://域名/upload/abc.mp4访问。对象存储的好处是显而易见的带宽不受服务器限制视频加载更快不用自己备份文件CDN 加速随手接入。缺点是配置多一点但也就是引入 SDK、配 AccessKey 和 Bucket、上传时拿到返回的 URL 三个步骤。3.2 小程序 video 组件对播放地址的硬性要求这是本篇文章里我认为最值得写的一段经验。你在微信开发者工具里随便填一个http://localhost:8080/video/xxx.mp4的播放地址模拟器能播但真机测试时绝对播不了。原因有两个第一微信小程序对资源地址有域名白名单限制。开发者工具里勾选“不校验合法域名”只能在开发阶段生效上线后的正式版只允许访问在小程序后台配置过的 request/downloadFile 合法域名且必须是 HTTPS。第二video 组件加载视频时需要的并非普通的 HTTP 地址规则严格一些原则上应该使用 HTTPS。真机也不会帮你混过这个校验。所以你在本地测试时必须走内网穿透工具比如 ngrok、cpolar把本地 SpringBoot 服务的 8080 端口暴露成一个临时 HTTPS 域名再把该域名配置到小程序后台的合法域名列表。这里有个容易踩的细节合法的 request 域名后缀不能带端口号必须是https://xxx.com这种形式端口靠穿透工具帮你绑定在 443 上。3.3 审核要用的视频与封面处理技巧我特别建议视频上传时同步生成一张封面图在上传接口里截取视频某一帧存成图片前端列表页使用封面图点击后才加载真实视频。这样流量消耗小小程序页面加载速度也快得多。没有专业转码工具的情况下可以要求后台管理视频时手动填一个封面 URL或者干脆用视频第一帧作为默认封面。具体实现上Java 可以用 ffmpeg 命令做抽帧处理ffmpeg -i input.mp4 -ss 00:00:01 -vframes 1 -q:v 2 cover.jpg项目里用 ProcessBuilder 执行这条命令就行。课程设计阶段如果嫌麻烦列表页也可以直接用 video 组件的 poster 属性指定封面或者干脆不传让它显示黑屏。提示上传视频时不要直接拿原始文件名作为存储名一个是中文文件名在 URL 里会编码混乱另一个是重名会互相覆盖。文件名统一用 UUID后缀则要真实保留小程序播放器对 mp4 格式兼容性最好上传时最好限制只允许 mp4。4. 小程序端与 Vue 后台的实现要点4.1 小程序请求封装统一入口与错误拦截小程序页面结构虽然轻但网络请求如果每个页面各自写在 onLoad 里后期维护会非常痛苦。我的习惯是所有请求走同一个 request 工具函数集中处理三件事拼接 baseUrl、携带 token、统一报错提示。工具函数核心代码const request (url, method, data) { return new Promise((resolve, reject) { wx.request({ url: BASE_URL url, method: method, data: data, header: { Content-Type: application/json, token: wx.getStorageSync(token) }, success: (res) { if (res.data.code 200) { resolve(res.data.data); } else if (res.data.code 401) { wx.removeStorageSync(token); wx.navigateTo({ url: /pages/login/login }); reject(res.data); } else { wx.showToast({ title: res.data.message || 请求失败, icon: none }); reject(res.data); } }, fail: (err) { wx.showToast({ title: 网络异常, icon: none }); reject(err); } }); }); };这样封装之后页面里的业务代码就非常清爽const list await request(/video/list, POST, { page: 1, size: 10 });注意这里用了 async/await但小程序的基础库版本要调到 2.10.0 以上。如果担心兼容性改用success回调写法也行只是没有 Promise 优雅。4.2 瀑布流列表、下拉刷新与触底加载视频列表页是用户第一眼看到的界面交互体验决定了用户会不会继续用下去。我做过三版迭代最后稳定的方案是用onPullDownRefresh做下拉刷新重新请求 page1 的数据用onReachBottom做触底加载每次 page1 继续请求页面维护一个isLoading状态防止触底事件连续触发时重复请求返回完所有数据后用一个hasMore布尔值控制列表不再追加。触底加载代码onReachBottom() { if (this.data.isLoading || !this.data.hasMore) return; this.setData({ isLoading: true, page: this.data.page 1 }); this.loadVideos(); }每次请求完成后注意判断如果records.length size说明没有更多数据了hasMore 置为 false并在页面底部显示“已经到底啦”。瀑布流两列布局的实现是 WXML 里写两个 view 容器根据索引奇偶决定进入左列还是右列。视频列表的封面图高度是不一致的所以两列的高度天然不同不能用一个行容器去套。4.3 Vue 管理后台登录鉴权与视频管理页管理后台用的是 Vue 2 Element UI Axios整体难度其实比小程序还低因为页面逻辑都是标准 CRUDElement UI 的表格组件帮了大忙。后台管理员不能用小程序的 openid 体系我用的是一张独立的 admin 表登录时走账号密码成功后用 JWT 生成 token 存到 localStorage。然后 Axios 请求拦截器统一加上 Authorization 头axios.interceptors.request.use(config { const token localStorage.getItem(adminToken); if (token) { config.headers.Authorization Bearer ${token}; } return config; });响应拦截器里遇到 401 就跳回登录页防止管理员 session 过期后页面白屏。视频管理页主要功能大致有这些视频列表支持按状态筛选、视频上传/编辑、视频下架/审核通过、数据统计卡片今日新增视频数、总用户数、总播放量。页面点“上传”之后选择本地 mp4 文件post 到后端的/admin/video/upload接口返回视频 URL 后填表提交。开发环境跨域问题我会在 Vue 项目根目录建 vue.config.jsmodule.exports { devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } };这样 Vue 页面里请求/api/video/list会被代理到 SpringBoot避免了开发环境下 CORS 的跨域报错。但要注意代理只存在于 devServer打包上线之后就由 Nginx 承担这个角色了。5. 部署、联调与调试经验5.1 本地开发环境怎么调通“前后端分离”本地开发会遇到三个端口三个程序的问题。我的一般调试流程启动 MySQL命令行起服务或者用本地可视化工具。启动 SpringBootIDE 里直接跑 main 方法控制台看到“Tomcat started on port(s): 8080”。启动 Vue devServernpm run serve控制台看到 8081。微信开发者工具打开小程序小程序里 BASE_URL 指向本地穿透地址或http://localhost:8080记得开“不校验合法域名”。正常情况下真实手机预览时小程序调http://localhost:8080是不通的因为 localhost 在手机里指向的是手机自己。所以真机调试必须做一个内网穿透把本机的 8080 映射成一个域名。这是我必须强调的一点真机调试不开穿透请求必挂。内网穿透工具启动后小程序端 BASE_URL 换成穿透生成的 https 域名开发者工具后台或工具里勾选不校验合法域名就能在真机上看到接口数据。5.2 服务器部署jar 包 Nginx 反向代理项目验收或者正式上线时不能再用脚本后台启动的临时方式。我推荐的部署结构是一台 Linux 服务器MySQL、Nginx、Java 环境都装好SpringBoot 打成 jar 包前端 Vue 打包成静态文件交给 Nginx。步骤拆出来就是本地或服务器上执行 Maven 打包mvn clean package -DskipTests把 target 目录下生成的xxx.jar传到服务器用以下命令启动nohup java -jar xxx.jar --spring.profiles.activeprod app.log 21 Vue 项目执行构建npm run build生成 dist 目录里面是静态文件。Nginx 配置里同时做两件事把前端 dist 目录作为站点根目录把/api前缀的请求反向代理到 8080 端口的 Java 服务。server { listen 443 ssl; server_name yourdomain.com; ssl_certificate /path/cert.pem; ssl_certificate_key /path/key.pem; root /var/www/dist; index index.html; location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /upload/ { alias /data/videos/; } }这里有一个历史上很多人翻车的点Nginx 的 proxy_pass 后如果带了路径比如proxy_pass http://127.0.0.1:8080/api/则会对请求 URI 做替换如果不带路径只是http://127.0.0.1:8080则请求原样转发。我建议后端接口本身统一带/api前缀这样 Nginx 只做地址转发逻辑最简单。5.3 小程序后台配置合法域名与发布项目部署上线后登录微信公众平台在“开发管理 - 开发设置”里找到“服务器域名”分别配置request 合法域名填https://yourdomain.comdownloadFile 合法域名填https://yourdomain.com视频播放走的是 video 组件它本质上是 downloadFile 网络请求所以 downloadFile 域名非常关键漏配的话视频一个都播不了。这里有个容易迷惑点前端请求的接口地址是https://yourdomain.com/api/xxx域名是 yourdomain.com配置域名时只需要写域名本身不带路径不写端口。如果你的视频文件放在了腾讯云存储或阿里云比如https://video-125xxxx.cos.ap-shanghai.myqcloud.com/xxx.mp4则 downloadFile 合法域名还需要额外添加这个 COS 域名一个域名配不进去就会黑屏。发布前建议先在开发者工具里勾选“不校验合法域名”跑通一遍再取消勾选、切换成正式配置做最后一次验证。这一步能筛掉绝大多数环境配置问题。6. 高频问题排查实录6.1 小程序请求 404、401、500 怎么快速定位404 大概率是路径没对上。排查方式是打开微信开发者工具的 Network 面板看实际请求的 URL 是不是和后端 Controller 的 RequestMapping 完全一致。我遇到最多的是拼了/api前缀后 Controller 里又写了一遍/api导致路径重复。401 一般是 token 校验失败。小程序端请求头有没有把 token 放进去、后端拦截器解析 header 的名称是否统一比如前端叫 token后端拦截器取 token这两处最容易不一致。500 一般是后端业务代码抛异常只能看 SpringBoot 控制台日志从堆栈第一行找问题。这里我建议在全局加一个 RestControllerAdvice 统一异常处理器把业务异常和系统异常都转成规范的 Result JSON 返回前端看到至少是一个可读的 message而不是一堆英文堆栈。6.2 视频不播放从加载地址到域名校验逐一检查视频黑屏或者一直转圈我先不怀疑代码逻辑顺序从外到内排查浏览器直接访问视频 URL看能不能播放。如果能说明文件本身没问题问题出在小程序环境。真机播放不行但模拟器可以几乎可以断定是域名白名单问题。提示 “video 组件加载失败”检查 video_url 是不是还是 http 而不是 https。手机网络下访问会突然断流检查视频文件是不是太大太大而服务器带宽又不够连接被掐了。我曾经有个项目因为视频文件普遍四五十 MB部署在一台 1M 带宽的服务器上播放时卡的怀疑人生。后来统一压缩分辨率到 720p、切片成 ts 或者压缩码率问题才解决。6.3 跨域报错开发与生产环境的分界点前后端分离开发时最常看到的报错就是浏览器控制台提示Access-Control-Allow-Origin。这是因为浏览器限制了浏览器端发起的跨域请求而小程序是客户端发请求不会触发这个限制。所以我们实际上只需要在开发阶段处理跨域问题。处理方式很简单SpringBoot 写一个 CORS 配置类允许特定来源跨域即可。Configuration public class CorsConfig { Bean public CorsFilter corsFilter() { CorsConfiguration config new CorsConfiguration(); config.addAllowedOriginPattern(*); config.addAllowedHeader(*); config.addAllowedMethod(*); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(/**, config); return new CorsFilter(source); } }有同学会问生产环境还要不要开跨域答案是如果生产环境的请求都走 Nginx 同域代理前端资源和接口在同一个域名下浏览器就不会触发跨域CORS 配置加了也无害。但要注意把 allowCredentials 设为 true 时allowedOriginPattern 使用*在某些浏览器会失效需要写具体来源这个属于细节坑留个印象即可。7. 项目文档与后续扩展方向7.1 一套能拿去答辩的文档应该包含什么这份题目里带了“文档”我就把文档怎么写得像模像样分享出来。项目文档至少要包含四块内容项目概述与技术选型用一两段话说明项目目标然后解释为什么选择 SpringBoot、小程序、Vue 这套技术栈。需求分析与功能拆解从用户和管理员两个角色拆功能模块每个模块一句话配一个操作流程。数据库设计与接口说明给出六张表的设计说明、字段注释再加一张接口清单表标注请求方式、参数、返回值。界面截图与部署步骤小程序端和后台主要页面各截几张图写清打包、部署到服务器的步骤。一个额外的加分享在文档里画一两张简单的时序图不用画太复杂比如登录流程、视频上传流程会直观很多。注意项目文档里如果引用了微信官方文档、Vue 官方教程尽量写自己的理解而不是大段复制答辩评委看的是你是否真的动手做了。7.2 从“能跑”到“能讲”底层逻辑要吃得透这种单项目的演示系统考察的往往不是代码多复杂而是你对整个链路有没有完整认知。面试官如果深挖大概率会问三连小程序登录流程怎么实现的视频文件是怎么存储的前后端分离怎么解决跨域这三个问题我这里都展开过了能用自己的话讲出来比面试前背十道面试题有用得多。7.3 一些扩展想法如果做完这个项目之后还想继续打磨可以考虑的扩展点不少视频搜索用 MySQL 全文索引或 Elasticsearch、用户关注与私信、播放历史与断点续播、广告位和打赏入口、运营数据大屏。技术上都不难叠加每次叠加都会让简历里的描述多一层空间。我在实际做这类项目时还有一个习惯先把最简单的闭环跑通上传一个视频 - 在小程序里看到它 - 给它点个赞再去追求花哨功能。因为内容型产品的核心链路通了其他的功能都只是往这个管道上接分支而已。最后再分享一个实操细节调试视频上传时后端打印日志时不用打印整个文件流只打印文件名和大小就行否则控制台会被二进制垃圾刷到毫无可读性。这种小习惯不会影响功能但能让你在出了问题时花最少时间找到原因。
返回列表