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

文章详情

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

Spring Boot+Vue健康健身追踪系统全栈开发实战

Spring Boot+Vue健康健身追踪系统全栈开发实战 做一套健康健身追踪系统我第一个想到的就是前后端分离后端用 Spring Boot前端用 Vue。这也是目前毕业设计和个人全栈项目里最典型的组合之一。它不只是做一个增删改查的 CRUD 项目而是要把用户体系、健康数据、运动计划、可视化报表、定时提醒这些真实业务场景串起来既考验后端的数据建模和接口设计能力也考验前端分组件的组织与交互体验。对准备做毕设、课设或者想系统练一遍全栈的人来说这个项目的复杂度非常合适——不大不小能讲清楚的东西还特别多。我把项目定名为“健康健身追踪系统”编号写的是 054。实际做下来花时间最多的不是写功能而是选型和解决各种环境问题。所以这篇博客我会把从需求拆解、技术选型、后端实现、前端落地到部署上线的完整过程都复盘一遍重点讲清楚每个环节为什么这样选、踩了哪些坑以及如何复现这套项目。1. 项目概述与需求拆解1.1 这个系统到底在解决什么问题先说痛点。绝大多数健身人群的状态是办了卡去了几次跑步靠 App 记体重靠备忘录写训练计划靠脑子记时间一长数据全丢积极性也没了。健康健身追踪系统的核心价值就是把个人健康数据集中管理起来让用户能看到自己的变化趋势而不是盯着某个孤立数字发呆。所以这个系统不是简单记录“今天跑步 5 公里”而是要解决三件事第一持续记录用户的体征数据和运动数据第二基于这些数据生成可视化图表让用户直观看到体重、体脂、运动时长的变化第三通过计划管理和定时提醒帮用户把运动习惯坚持下来。这个定位决定了系统不能做成一堆表格堆叠的后台管理系统而是要偏用户端的产品化设计。数据录入要简单展示要看图说话提醒要主动触达这样才能真正对用户产生价值。1.2 核心功能模块与使用场景我按照实际使用场景把整个系统拆成五个核心模块用户模块注册、登录、个人档案维护。登录用的是 JWT 无状态认证后面会详细说。健康档案模块维护身高、体重、体脂率、腰围、BMI 等指标每次体测完录入一条记录。运动记录模块支持跑步、骑行、力量训练、瑜伽等常见运动类型记录时长、距离、卡路里消耗。训练计划模块用户可以创建周期计划比如“21 天减脂计划”每天的任务可以勾选完成。数据看板模块用 ECharts 展示体重趋势、运动时长分布、卡路里消耗排行等图表。系统的核心用户场景很简单早上看体重趋势图晚上跑步回来录一条运动记录顺便查看今天的计划完成情况。后台管理员可以管理用户、发布健康资讯或训练计划模板。我在实际设计时没有加社交和好友排行因为那会明显拉大系统复杂度。核心链路跑通后再扩展会轻松很多这也是做全栈项目的一个原则先把主链路做深再做宽。1.3 为什么是 Spring Boot Vue这个组合之所以主流不是因为追热点而是它确实适合这个场景。Spring Boot 简化了 Spring 的繁琐配置内嵌 Tomcat可以快速启动一个独立的 REST API 服务自带 Starter 机制整合 MyBatis-Plus、Redis、定时任务都非常顺手。Vue 的响应式数据绑定、组件化开发和渐进式引入方式让前端代码结构清晰尤其是管理端和中台类页面开发效率很高。前后端分离还有个实际好处接口联调阶段前端用 Mock 数据开发后端用 Postman 或 Swagger 测接口两边互不阻塞。后期部署时前端构建成静态资源用 Nginx 托管后端打成 Jar 包天然适合 Docker 容器化部署。当然 Spring Boot Vue 也不是没有缺点比如它是典型的服务端渲染向客户端渲染迁移的产物首屏性能需要前端自己处理对于纯静态内容它不是最优解。但放在“健身追踪”这个有较多动态交互和个性化数据的场景里这套组合是踏实可行的。2. 技术选型与环境准备2.1 后端技术栈与 Spring Boot 版本选择后端推荐使用 Spring Boot 2.7.18。很多新手上来就下载最新版 Spring Boot 3.x结果遇到“springboot 版本太高”导致的坑JDK 版本要求 17javax 包全部改成了 jakarta 包老版本的 MyBatis-Plus、Swagger 文档依赖不兼容网上大量教程和源码还是基于 2.x 的遇到问题连参考都找不到。Spring Boot 2.7.x 是 2.x 系列的最后一个版本维护时间足够长JDK 8 和 JDK 11 都能跑生态兼容性也稳定。如果你不是为了学习 Spring Boot 3 的新特性做项目选 2.7.18 是最稳的选择。配套的后端组件是MyBatis-Plus 3.5.3简化 CRUD自带分页插件。MySQL 8.0主数据库用来存用户、健康记录和运动记录。Redis 6.x缓存用户 Token 和热点数据。Spring Security JWT登录认证与接口权限控制。Lombok减少样板代码。Hutool提供一些好用的工具方法。项目结构我用的是标准 Maven 单模块后面如果业务复杂可以拆成 Maven 多模块。单模块对毕设和课程设计足够目录分层用 controller、service、mapper、entity、config 五层职责清晰也方便写文档。2.2 前端技术栈与 Vue 环境搭建前端我用的 Vue 3 Vite Pinia Vue Router 4 Element Plus ECharts。Vite 启动速度比 Webpack 快很多热更新体验也好。Vue 环境的安装和配置是新手最容易卡住的第一步。建议统一用 Node.js 16 或 18 的 LTS 版本不要追最新版部分依赖对过高版本兼容性不好。装完 Node.js 后执行node -v npm -v接着设置 npm 镜像然后在想创建项目的位置执行npm config set registry https://registry.npmmirror.com npm create vitelatest health-tracker-front选择 Vue JavaScript 模板不需要配置 TypeScript降低上手门槛。然后进入项目目录安装依赖cd health-tracker-front npm install npm run dev开发工具我用的是 IDEA 配合 Vue 官方插件也可以用 VSCode 加 Volar 插件体验差不多。需要注意IDEA 打开 Vue 项目之后如果发现 import 路径报红多半是插件没启用 Node.js 和 Volar 支持检查一下设置里 JavaScript 语言版本。2.3 项目结构与数据库设计后端目录我按功能划分实际结构是这个样子的src/main/java/com/example/health/ ├── controller/ # 接口层只负责参数接收和响应返回 ├── service/ # 业务层处理核心逻辑 ├── mapper/ # 数据访问层继承 BaseMapper ├── entity/ # 数据库实体类 ├── config/ # 安全配置、跨域配置、Redis配置 ├── common/ # 统一返回结果、异常处理、工具类 └── HealthApplication.java前端 src 目录也做了分层src/ ├── api/ # axios 封装和接口定义 ├── views/ # 页面组件 ├── components/ # 可复用组件 ├── router/ # 路由配置 ├── store/ # Pinia 状态管理 ├── utils/ # 工具函数比如请求拦截器 └── assets/数据库设计是我最先动手的部分。核心表有四张用户表 user、健康记录表 health_record、运动记录表 exercise_record、训练计划表 exercise_plan。所有的统计报表基本都能由这四张表的数据派生出来。举个具体例子user 表设计的时候我加了 height 和 weight 字段作为初始档案但是后续身高体重变化仍然记录在 health_record 表里这样能保留历史数据体重趋势图就是从这张表里查出来的。设计上要注意能用设计解决的问题就不要用代码硬撑。3. 后端核心实现与数据访问3.1 基于 MyBatis-Plus 的数据访问层Spring Boot 的数据访问我用的是 MyBatis-Plus它对单体项目的 CRUD 非常友好。实体类上通过 TableName 指定表名继承 BaseMapper 就能获得常用的增删改查方法复杂查询用 LambdaQueryWrapper 构建条件基本不需要写 XML。举个例子查询用户最近 30 天的体重变化LambdaQueryWrapperHealthRecord wrapper new LambdaQueryWrapper(); wrapper.eq(HealthRecord::getUserId, userId) .orderByAsc(HealthRecord::getRecordDate) .ge(HealthRecord::getRecordDate, DateUtil.beginOfDay(LocalDate.now().minusDays(30))); ListHealthRecord records healthRecordMapper.selectList(wrapper);MyBatis-Plus 还有一个好用的点是字段自动填充。像 create_time、update_time 这类字段通过 TableField(fill FieldFill.INSERT) 和 MetaObjectHandler 自动处理这样业务代码里的重复赋值就少了。分页查询我直接用了 MyBatis-Plus 的分页插件配置一个 MybatisPlusInterceptor 就行。要注意分页插件和旧版本之间的兼容性如果 SQL 解析异常第一时间确认插件版本和 Spring Boot 版本是否匹配。3.2 JWT 登录认证与权限控制登录是每个系统都会有的模块但设计思路差别很大。我用的是 JWT 无状态方案流程是用户登录成功后后端生成一个带签名和过期时间的 Token 返回给前端前端后续请求每次在 Header 里带上 Authorization: Bearer xxx后端用拦截器校验 Token 并解析出用户 ID存到 ThreadLocal 里供后续业务方法直接获取。JWT 的好处是后端不需要在 Session 里保存登录状态适合前后端分离和微服务场景。但要注意一点JWT 本身是自包含的里面不要放敏感信息过期时间不要设太长我设为 24 小时同时可以把 Token 存进 Redis需要主动失效时直接删掉。有人会问多个 Spring Boot 项目之间怎么做到一次登录全部免登录这其实就是单点登录的需求简单做法是共享 Redis 存储的 Token应用之间通过统一认证服务校验 Token。做这个毕设项目不需要这么复杂但你要理解 JWT Redis 的认证链路面试经常问。我写了一个简单的 JwtInterceptor 拦截器排除 login 和 register 接口其余请求全部校验。实现起来大概是这样public class JwtInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String token request.getHeader(Authorization); if (StrUtil.isEmpty(token)) throw new BusinessException(未登录); Long userId JwtUtil.parseToken(token); UserContext.set(userId); return true; } }密码存储务必用 BCrypt 加密不要用 MD5。Spring Security 自带的 BCryptPasswordEncoder 可以直接注入使用同样密码在数据库里看起来完全不同。3.3 定时任务实现健康提醒与统计健康类应用最吸引人的功能之一是主动提醒。我用 Spring Boot 自带的 Scheduled 定时任务实现了两个场景每天早上 7 点向用户发送当日运动计划提醒每月 1 号凌晨统计上个月的健康数据生成月度报告。使用定时任务只需要两步启动类加 EnableScheduling在方法上加 Scheduled(cron 0 0 7 * * ?)。这里的 cron 表达式是六位或七位格式严格按照“秒 分 时 日 月 周”的顺序。我第一次写的时候把“0 0 7 * * ?”写错了位置导致晚上 7 点执行了排查半天。定时任务里最容易踩的坑有两个。一是默认单线程执行多个任务会互相阻塞解决方法是配置一个线程池把 TaskScheduler 替换掉二是集群部署时同一个任务会重复执行这个问题在毕设里一般不会遇到但如果以后做分布式项目需要引入分布式锁。3.4 自定义自动配置与第三方集成Spring Boot 的自动配置是其精髓。我用一个简单的自定义配置类处理跨域没有使用全局过滤器而是直接在 config 包下定义 WebMvcConfigurerConfiguration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE) .allowCredentials(true); } }生产环境不要 allowCredentials 和 allowedOriginPatterns(*) 同时开会有安全风险开发环境方便就行。Redis 的配置也属于这个范畴。默认的序列化器存中文会乱码我自定义了一个 RedisTemplateKey 用 StringRedisSerializerValue 用 GenericJackson2JsonRedisSerializer。所有自定义自动配置本质都是声明一个 Bean然后让相应组件在启动时自动装配理解这一点之后看各种 Starter 源码就不那么费劲了。关于第三方集成网上搜“springboot 整合 activemq”“springboot 整合 flink”这类关键词的人很多但在这套健康健身系统里我不建议引入消息队列或流计算框架。技术选型要为业务服务ActiveMQ 可以做异步通知但成本高于收益Flink 是实时计算场景才需要的现阶段就是过度设计。如果一定要给自己加分可以选一个轻量级的 Spring 事件监听机制把“用户创建成功发送欢迎消息”这类动作解耦。4. 前端核心实现与业务落地4.1 动态路由与页面权限控制前端路由我用了动态路由方案。用户登录后后端返回当前用户可访问的菜单列表和角色信息前端根据这些数据生成路由表用 router.addRoute 动态注册。这样可以做到不同角色登录后看到的页面不一样实现真正的页面权限控制。具体流程是登录成功后把 Token 存进 Pinia 和 localStorage同时拉取用户信息与菜单树。封装一个 generateRoutes 函数将后端返回的路由名称转换为 Vue Router 需要的 RouteRecordRaw。遍历菜单树判断组件路径后动态 import 对应页面。在全局前置守卫 beforeEach 里判断没有 Token 就去登录页有 Token 但菜单未加载就重新加载。这里有个关键细节动态路由注册后如果用户刷新浏览器Pinia 里的状态会丢失所以刷新时必须重新拉取菜单再 addRoute否则会出现刷新后白屏也就是常说的“刷新 404 问题”。我的解决方案是在 beforeEach 里加一个 if 判断如果当前路由表为空就重新走一遍动态路由流程然后调用 next({ ...to, replace: true })。Vue Router 的路由参数主要有两种传法query 和 params。query 是以 URL 问号形式传参比如 /plan?id12params 是动态路由路径比如 /plan/12。params 的方式更适合详情页跳转但要注意刷新后 params 丢失的问题所以关键参数我会用 query或者用 Pinia 缓存一份。4.2 组件复用、插槽与样式冲突处理前端代码写多了就会意识到组件化的重要性。我把 ECharts 的封装做成了一个通用图表组件传入 option 即可渲染。Element Plus 的表格组件也经常配合插槽使用比如在操作列里放按钮、在状态列放 Tag 标签都用插槽实现。Vue 插槽分为默认插槽、具名插槽和作用域插槽。最经典的场景是封装一个表格组件表格的列结构由父组件通过插槽传入子组件只负责数据和分页。这样一套表格逻辑可以在健身记录、健康档案、用户管理多个页面复用改起来也方便。我在封装的时候遇到过一个问题插槽传参是单向的作用域插槽拿到的变量要用解构重新赋值否则会改到父组件数据这是 Vue 的响应式陷阱。样式冲突是 Vue 项目很常见的问题。组件里如果忘了加 scoped每个组件里写的 class 就都会变成全局样式后面写的会覆盖前面的结果就是明明这段样式在首页好好的到了另一个页面就变形了。排查这种事特别浪费时间所以我的原则是组件内一律加 scoped需要修改子组件内部样式时用 :deep() 穿透全局样式只放在 assets/api.css 里统一管理。4.3 前后端联调与流媒体播放扩展联调阶段最大的问题是跨域。开发环境里我直接用 Vite 的 proxy 配置解决不需要后端开跨域// vite.config.js server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }这样前端请求 /api/user/login实际上会代理到 http://localhost:8080/api/user/login浏览器层面没有跨域问题。axios 封装也是关键一环。我封装了一个 request 实例请求拦截器自动把 Token 加到 Header响应拦截器统一处理业务码和 HTTP 状态码遇到 401 直接跳转登录页。这样后面每个接口写起来都非常简洁export function getHealthTrend(data) { return request({ url: /health/trend, method: get, params: data }) }我在做这个项目的时候还接了一个流媒体播放的扩展健身教学视频播放。网上搜“vue 播放 m3u8 免安装”的人不少这个需求用 hls.js 就能实现免插件播放原理是浏览器原生不支持 HTTP Live Streaming 的 m3u8 索引文件读取和分片加载hls.js 在 JavaScript 层实现了 Media Source Extensions 的封装。核心代码其实很简洁npm install hls.jsimport Hls from hls.js const video document.getElementById(video) if (Hls.isSupported()) { const hls new Hls() hls.loadSource(https://example.com/lesson.m3u8) hls.attachMedia(video) } else if (video.canPlayType(application/vnd.apple.mpegurl)) { video.src https://example.com/lesson.m3u8 }需要注意播放 m3u8 遇到最多的问题是跨域访问后端或 CDN 必须配置允许跨域另外服务端返回 m3u8 和 ts 分片时Content-Type 必须正确否则浏览器会拒绝解析。5. 部署上线与项目交付5.1 前端构建与后端打包开发完后的交付环节也值得好好讲。后端打包很简单在项目根目录执行mvn clean package -DskipTestsJar 包会生成到 target 目录本地测试可以执行java -jar target/health-tracker-0.0.1-SNAPSHOT.jar前端构建也顺手npm run build构建完成后会生成 dist 目录里面是纯静态文件交给 Nginx 托管就行。有人问“vue 项目源码怎么发给别人”我的建议不是直接发整个文件夹——node_modules 一定要删掉发给别人时让他们执行 npm install 重新安装依赖。完整的交付应该包括源码压缩包、数据库初始化脚本、环境说明文档和接口文档。很多人的项目到答辩阶段无法在对方电脑上跑起来就是因为没有写清楚依赖版本和启动顺序。5.2 宝塔面板 Docker 部署实操部署方式我最终用了宝塔面板配合 Docker。先说为什么不用传统的一键部署因为项目依赖 MySQL 和 Redis手动在服务器上装环境容易出错容器化可以把整个运行环境固定下来换一台服务器也能秒级复现。后端 Dockerfile 大概长这样FROM openjdk:8-jre WORKDIR /app COPY target/health-tracker-0.0.1-SNAPSHOT.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar, --spring.profiles.activeprod]构建镜像并启动容器docker build -t health-tracker . docker run -d --name health-server -p 8080:8080 \ -e MYSQL_HOSThost.docker.internal \ -e REDIS_HOSThost.docker.internal \ health-tracker这里 host.docker.internal 是 Docker 专为容器访问宿主机提供的地址如果你的数据库和 Redis 是直接装在宿主机上的用这个地址可以避免写死内网 IP。前端静态文件我直接用宝塔的 Nginx 服务托管配置一个 server 块root 指向 dist 目录location /api 反向代理到容器端口 8080。部署这一环节最大的坑是时区容器默认是 UTC 时间定时任务比北京时间晚 8 小时我在启动命令里加了 -e TZAsia/Shanghai。5.3 上线后的安全与性能注意点上线后第一件事是改数据库密码和 Redis 密码不要用默认 root 空密码。用户名密码要用 BCrypt 存储接口层需要加参数校验防止 SQL 注入和恶意请求。我引入了 spring-boot-starter-validation在实体类上直接用 NotBlank、Min 这类注解校验参数省了手写一堆 if 判断。性能方面最典型的优化是缓存热点数据。首页看板的统计用 Redis 缓存 10 分钟避免每次访问都查询多张表做聚合。另一个点是避免 N1 查询比如查询用户运动记录列表时如果需要关联用户信息不要写循环查数据库直接用 MyBatis-Plus 的 join 或者一次性查出来做内存映射。安全上还有个容易被忽视的点统一异常处理。我写了一个 RestControllerAdvice 全局异常处理器所有业务异常统一返回 JSON 格式消息同时把堆栈日志只打印到服务端不返回给客户端。前端拿到错误码后给用户展示对应文案而不是看到一个 500 白屏。6. 高频问题与排查技巧实录6.1 Spring Boot 相关的坑我先说一个最典型的Spring Boot 版本太高项目启动报 javax.servlet 相关的错误。这大概率是用了 Spring Boot 3.x但又引了基于 javax 的第三方依赖或者代码里 import 了 javax.servlet。解决方式有两个一是降低 Spring Boot 版本到 2.7.x二是把 javax 开头的依赖改成 jakarta 开头。对普通项目来说我建议直接选 2.7.x生态兼容性更好。还有一个容易踩的坑是数据库连接配置不对。很多人在 application.yml 里少写了时区参数导致数据库时间比正常时间差 8 小时。我一般这样配置spring: datasource: url: jdbc:mysql://localhost:3306/health?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456另外 MyBatis-Plus 和 PageHelper 同时存在会导致分页插件冲突两个分页插件都会尝试改写 SQL结果 SQL 被改得乱七八糟。如果用了 MyBatis-Plus就不要重复引入 PageHelper。6.2 Vue 相关的坑Vue 项目最常见的就是环境问题。npm install 时如果卡住大部分是网络问题更换淘宝镜像基本能解决。我用 Vite 创建项目之后执行 npm install如果出现 gyp 或者 node-sass 相关报错那基本上是 Node 版本不兼容卸载重装一个 LTS 版本最直接。还有一次我在创建 Vue 3 TypeScript 项目时启动直接报了这样一个错误failed to load tsconfig vue/tsconfig/tsconfig.web.json: tsconfig not found。原因是 tsconfig 相关依赖没有安装干净或者 Vite 版本升级后目录结构变化。解决方法是重新安装 vue/tsconfig或者直接新建项目时选择不包含类型检查的模板如果是纯 JavaScript 项目根本不会遇到这个问题。样式冲突这个坑前面提过再补充一个排查技巧页面里一个 class 被全局改乱时在浏览器开发者工具里看样式来源凡是来自 .css 文件的都可能有问题组件里加了 scoped 的样式来源会带>spring: jackson: date-format: yyyy-MM-dd HH:mm:ss部署阶段最常见的坑是 Nginx 反向代理后接口 404。检查一下代理配置转发时不要丢失路径前缀比如 location /api/ 对应 proxy_pass http://127.0.0.1:8080/前面的 /api 会被移除如果后端接口本身也带 /api就少拼了一段。我干脆用完整路径的方式写避免歧义。m3u8 播放不出来的问题在部署阶段也很典型。如果开发环境播放正常、部署后播放不了优先检查三件事目标地址是否允许跨域、服务器是否正确返回 .m3u8 文件并设置对应 MIME 类型、视频分片 .ts 是不是也能正常访问。实际项目里 90% 的情况是跨域没处理好可以给 Nginx 加上 add_header Access-Control-Allow-Origin *。我把这些高频问题整理成一份速查表方便后面直接对照问题现象可能原因解决方法Spring Boot 启动报 javax 包不存在Spring Boot 3.x 版本过高改用 2.7.x或替换 jakarta 依赖数据库时间相差 8 小时JDBC 连接缺少 serverTimezone 参数URL 添加 serverTimezoneAsia/Shanghai前端 npm install 卡住网络源不稳定设置 npm 淘宝镜像Vue 刷新后页面 404动态路由未重新加载beforeEach 中重新 addRoute接口跨域报错前后端域名不一致启用代理或后端 CORS 配置定时任务不触发cron 表达式或时区问题检查表达式、设置 Asia/Shanghai样式乱套失效组件未加 scoped组件内样式加 scoped 和 :deep7. 复盘与面试延伸7.1 这个项目给我带来的几点沉淀做完这套系统最大的体会是“全栈项目拼的不是功能数量而是数据流是否讲得清楚”。我刚开始把模块铺得很开又是社交功能又是消息推送后来发现核心链路跑不通全是在浪费精力。后来收敛到“用户上传健康数据—后端落库—前端图表展示—定时任务提醒”这条主循环上所有功能都围绕它展开项目立刻变得完整且有说服力。另外一个体会是环境问题占据了一半的调试时间。Spring Boot 版本、Node 版本、依赖兼容性、Docker 时区这些跟业务无关的问题最容易卡人但也是最能锻炼排查能力的。每次遇到一个报错我都会把解决方案记录到自己的笔记里后面越做越顺。这套项目做完我也从“代码能跑就行”过渡到了“知道为什么能跑”的阶段。做全栈项目还有一个容易被忽略的环节接口文档。我用的是 Knife4j 整合 OpenAPI 自动生成文档后端写完接口前端直接在线预览请求参数和响应结构联调效率提升非常明显。7.2 面试官可能会追着问的技术点这套项目如果写到简历上下面这些高频面试题你有必要提前准备Spring Boot 自动配置原理。核心是 SpringBootApplication 整合了 EnableAutoConfiguration会自动加载 META-INF 下的 AutoConfiguration.imports 文件根据条件注解 ConditionalOnClass 判断当前类路径是否存在对应类然后自动装配 Bean。讲清楚这个过程就够了。JWT 和 Session 的区别。Session 是服务端保存状态JWT 是客户端携带状态。JWT 适合无状态接口但不可控失效Session 可控性强但需要共享存储。要注意 JWT 不需要查数据库就能识别用户所以很适合多端共用和分布式场景。Vue 响应式原理。Vue 3 使用 Proxy 代替 Object.defineProperty好处是可以监听属性新增删除和数组索引变化而且默认是惰性劫持初始化性能更好。面试时可以顺带提一下依赖收集和派发更新的过程结合项目中体重数据从接口回来后页面自动更新的例子来讲。动态路由怎么实现。这个问题在项目里已经很深入了就按我前面说的内容组织答案登录后拉菜单、递归生成路由、addRoute 注册、刷新时重新加载。注意提到 Vue Router 4 的 addRoute 可以在路由实例上动态添加这个功能旧版本就有但新版对多级嵌套菜单更友好。我个人的建议是做完项目后把每个模块的“为什么要这样做”记录下来。面试时不可能手写全部代码但你能把逻辑讲透就已经能超过绝大多数只贴代码的简历了。这套健康健身追踪系统无论从技术覆盖面还是业务完整性来说都是非常适合作为学习和项目经验积累的一个全栈案例。
返回列表