首页 / 资讯中心 / 文章详情

基于SpringBoot+Vue的多媒体信息共享平台设计实例解析

基于SpringBoot+Vue的多媒体信息共享平台设计实例解析 ★ FEATURED ARTICLE
1. 项目概述这套“武理多媒体信息共享平台”到底做了什么毕业设计年年都有做“XX管理系统”“XX平台”的但真正能让人眼前一亮、答辩不翻车的往往是那种把技术栈选扎实、把业务逻辑讲清楚的项目。这套基于 SpringBoot Vue MySQL 的多媒体信息共享平台走的正是这条务实路线——它本质上是一个面向高校场景的资源分享与展示系统用户可以在上面上传视频、图片、文档等多媒体资源浏览和检索他人分享的内容管理员则负责资源审核、用户管理等后台操作。核心价值在于用一个完整的前后端分离项目把学生时代最常被问到的那几个技术问题——权限控制怎么做、文件上传怎么存、跨域怎么解决——全部用一套可运行、可演示的方案回答清楚。我推荐有 Java Web 基础、想拿一个“能跑、能讲、能改”的毕设项目的同学认真看一遍这套东西。它不只是给你一堆源码而是把从数据库设计到部署上线的整条链路都打通了论文、部署文档齐全属于典型的“拿来就能用、改改就能答辩”的完整交付物。下面我结合自己做类似项目的实际经验把它的设计思路、核心实现、部署避坑一条条拆开讲希望能帮你省掉几周的无头苍蝇式摸索。2. 核心方案选型与技术剖析系统采用前后端分离架构前端 Vue 后端 Spring Boot 数据库 MySQL这个组合在毕业设计场景里几乎是“标准答案”但标准答案也有标准答案的讲究。选型不是越新越好而是要权衡你自己的基础、环境、资料丰富度和答辩展示需求。2.1 为什么是 Spring Boot 而不是 SSM很多同学的课程设计用的是 SSMSpring SpringMVC MyBatis到了毕业设计就纠结要不要换。我的建议是直接换 Spring Boot理由很实在配置简化SSM 里那堆 XML 配置数据源、事务、扫描包、视图解析器在 Spring Boot 里全部自动化一个application.yml搞定大部分事。毕设时间就那么多省下配置时间去做业务不香吗内嵌容器Spring Boot 自带 Tomcat打包成 jar 直接跑不用单独装 Tomcat、配置 server.xml。部署文档里少写一大段环境配置说明答辩演示也方便。生态成熟Spring Boot 整合 MyBatis-Plus、Spring Security、Redis 都有现成 starter查资料容易遇到问题搜得到。版本选择考虑到大部分同学本机环境是 JDK 8推荐 Spring Boot 2.7.x 系列比如 2.7.18不要一上来就追 Spring Boot 3.x。Spring Boot 3 要求 JDK 17如果你电脑上装了多个 JDK 或者学校机房环境是 JDK 8版本冲突会让你在环境配置上浪费大量时间。这一点下面详细说。2.2 前端架构Vue 2 Element UI 还是 Vue 3 Element Plus前端框架选择直接影响开发体验和后期维护这里给两个方案对比对比维度Vue 2 Element UIVue 3 Element Plus上手难度低教程多中需理解 Composition API组件生态成熟稳定持续更新资料丰富度极高几乎任何问题都能搜到较多新项目为主推荐指数★★★★★★★★★对于毕业设计我的建议是如果你 Vue 基础薄弱选 Vue 2 Element UI稳如果你想在答辩时多一个亮点“我们使用了最新主流框架”选 Vue 3 Element Plus前提是你愿意花时间学 Composition API。我自己的项目用的是 Vue 2 Element UI原因很简单资料多、坑少、我熟。技术选型不是越新越好而是越稳越好。毕设的核心目标是顺利通过答辩不是展示你用了多少新技术。2.3 数据库设计4 张核心表撑起整个系统MySQL 数据库设计是毕设的重头戏表结构设计得好不好直接影响后期编码效率。我设计的数据库名为media_share核心表结构如下简化版完整建表 SQL 请看项目内doc/sql目录用户表userCREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 用户ID, username VARCHAR(50) UNIQUE NOT NULL COMMENT 用户名, password VARCHAR(100) NOT NULL COMMENT 密码, avatar VARCHAR(255) DEFAULT NULL COMMENT 头像地址, role TINYINT DEFAULT 0 COMMENT 角色 0-普通用户 1-管理员, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, status TINYINT DEFAULT 1 COMMENT 状态 1-正常 0-禁用 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;资源表resourceCREATE TABLE resource ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 资源ID, title VARCHAR(200) NOT NULL COMMENT 资源标题, type VARCHAR(20) NOT NULL COMMENT 资源类型video/image/doc, url VARCHAR(500) DEFAULT NULL COMMENT 资源存储地址, cover VARCHAR(255) DEFAULT NULL COMMENT 封面图, description TEXT COMMENT 资源描述, uploader_id INT NOT NULL COMMENT 上传者ID, category_id INT DEFAULT NULL COMMENT 分类ID, download_count INT DEFAULT 0 COMMENT 下载次数, view_count INT DEFAULT 0 COMMENT 浏览次数, status TINYINT DEFAULT 1 COMMENT 状态1-审核通过 0-待审核 2-下架, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 上传时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;分类表category和评论表comment相对简单分类表存资源分类视频/图片/文档等评论表存用户对资源的评论内容、评论时间、评论人 ID。具体字段这里不展开项目 SQL 文件里都有。设计要点外键不建物理关联建逻辑关联。比如resource.uploader_id关联user.id我只在代码层面做校验没有在数据库层面加外键约束。这样后期如果要删数据、加批量操作不会被外键绊住。状态字段用 TINYINT 而非 VARCHAR。开发时你会频繁做状态筛选用数字类型效率更高且不容易出现大小写问题。大字段用 TEXT。description用TEXT类型避免 VARCHAR(255) 存不下长描述导致插入失败。统一使用 utf8mb4。不要用 utf8mysql utf8 在存储 emoji 时会报错utf8mb4 才是真正的“全量字符集”。3. 后端核心实现权限、登录与文件上传后端是整个系统的“大脑”我按模块拆分讲重点说权限控制、登录认证、文件上传三个模块因为这三个地方是毕设里最容易出问题、也最容易被老师追问的。3.1 JWT 登录认证状态管理不再依赖 Session传统的 Session 登录在前后端分离架构下不好使——前端是独立部署的Session 存在后端服务器上小程序、App、网页端各自维护 Session 太麻烦。这里我用 JWTJSON Web Token做登录认证一句话概括服务器不存状态客户端自己保管凭证。流程是这样的用户提交用户名密码到/api/auth/login后端校验通过后生成一个 JWT Token 返回给前端前端把 Token 存在 localStorage 或 Cookie 里后续每次请求在请求头加Authorization: Bearer token后端写一个拦截器Interceptor统一校验 Token非法请求直接返回 401JWT 的核心代码如下简化版// JwtUtil.java 核心方法 public String generateToken(String username, Long userId) { return Jwts.builder() .setSubject(username) .claim(userId, userId) .setExpiration(new Date(System.currentTimeMillis() 1000 * 60 * 60 * 24)) // 24小时过期 .signWith(SignatureAlgorithm.HS256, secretKey) .compact(); } // 解析Token public Claims parseToken(String token) { return Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(token) .getBody(); }这里有一个特别容易踩的坑JWT 的 secretKey 必须在配置文件中管理不能写死在代码里。我之前为了省事直接在类里写了一个固定字符串后来想换 key 得重新编译代码非常被动。正确做法是放在application.yml里读取用Value(${jwt.secret})注入。另外JWT 过期时间建议设置 24 小时配合前端的“记住我”功能做成 7 天。如果时间太短用户频繁重新登录体验很差如果太长安全性下降。24 小时是折中方案。3.2 基于拦截器的权限控制管理员和普通用户分开权限控制如果每个接口都写一遍判断逻辑代码会非常冗余而且容易漏。我的做法是用 Spring Boot 拦截器统一处理// AuthInterceptor.java Component public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行登录、注册等公开接口 if (request.getRequestURI().startsWith(/api/auth)) { return true; } String token request.getHeader(Authorization); if (token ! null token.startsWith(Bearer )) { String realToken token.substring(7); try { Claims claims jwtUtil.parseToken(realToken); request.setAttribute(userId, claims.get(userId)); return true; } catch (Exception e) { response.setStatus(401); return false; } } response.setStatus(401); return false; } }拦截器写完后需要在配置类里注册并且设置拦截路径。这里我犯过一个低级错误拦截器注册顺序和路径匹配规则搞混导致静态资源也被拦截。后来在配置类里明确排除了/assets/**、/static/**等静态资源路径才解决。对于管理员接口我额外加了一个注解RequireAdmin在拦截器里解析 token 里的 role 字段如果是 0 就返回 403。这样写的好处是普通接口只验证是否登录管理接口额外验证角色权限新增接口时只需加注解不用改拦截器3.3 文件上传本地存储方案详解多媒体资源系统最核心的功能就是文件上传。这里的文件包括图片、视频、文档我采用的方案是本地磁盘存储上传的文件保存在服务器的/upload目录数据库里只存文件的相对路径。关键代码如下// FileController.java PostMapping(/api/upload) public Result uploadFile(RequestParam(file) MultipartFile file, RequestParam(type) String type) { if (file.isEmpty()) { return Result.error(文件不能为空); } // 原文件名处理防止非法字符 String originalFilename file.getOriginalFilename(); String ext originalFilename.substring(originalFilename.lastIndexOf(.)); // 生成新文件名时间戳 随机数避免重名 String newFileName System.currentTimeMillis() _ UUID.randomUUID().toString().substring(0, 8) ext; // 按日期分目录存储如 /upload/2025/06/ String datePath new SimpleDateFormat(yyyy/MM).format(new Date()); File dir new File(uploadPath / datePath); if (!dir.exists()) { dir.mkdirs(); } File dest new File(dir, newFileName); file.transferTo(dest); // 返回可访问路径 String url /api/files/ datePath / newFileName; return Result.success(url); }这段代码虽然简单但有几个细节值得注意文件名必须重命名直接用用户上传的文件名存磁盘一是可能重名二是可能包含特殊字符如中文路径在某些环境会乱码三是路径穿越攻击风险。用时间戳 随机数 扩展名的重命名方案三防齐了。按日期分目录如果所有文件都堆在同一个目录文件数量到几万个时目录性能明显下降而且手动查找文件极其痛苦。按yyyy/MM分目录既方便管理又方便按月份清理。前端展示跨域问题前端访问/api/files/**时如果前端和后端不在同一个域名下会跨域。这一点在 Vue 开发环境通过 proxy 代理解决生产环境用 Nginx 反向代理解决下面部署章节会说。还有一个经验上传接口要限制文件大小和类型。Spring Boot 默认上传文件大小上限是 1MB这显然不够用你需要在application.yml里调整spring: servlet: multipart: max-file-size: 100MB max-request-size: 200MB这里也别无脑开大100MB 够用了。如果有同学硬要上传几个 GB 的大视频建议走对象存储比如阿里云 OSS、七牛云本地存储扛不住。本地存储适合做毕设演示、中小规模系统这是它的定位用起来心里有数就行。4. 前端核心实现页面路由、组件通信与接口对接前端我用 Vue 2 Element UI 开发整体结构清晰模块划分合理。这一章讲三个关键点路由配置、组件通信、接口封装。4.1 路由配置页面跳转与权限控制Vue Router 是前端页面的“导航系统”我设计的路由表如下简化版// router/index.js const routes [ { path: /login, name: Login, component: () import(/views/Login.vue), meta: { title: 登录, public: true } }, { path: /, component: () import(/layout/Layout.vue), children: [ { path: , name: Home, component: () import(/views/Home.vue) }, { path: resources, name: ResourceList, component: () import(/views/ResourceList.vue) }, { path: upload, name: Upload, component: () import(/views/Upload.vue) } ] } ]路由配置里有一个容易被忽略的点页面标题meta.title一定要配。毕业设计答辩时老师会切换页面看效果如果浏览器标签页一直显示同一个 title观感很差而且显得不专业。我通过全局路由守卫动态设置 document.titlerouter.beforeEach((to, from, next) { document.title to.meta.title ? ${to.meta.title} - 武理多媒体分享平台 : 武理多媒体分享平台 // 未登录跳转登录页 const token localStorage.getItem(token) if (!to.meta.public !token) { next(/login) return } next() })这个守卫函数同时承担了两个职责设置页面标题 登录拦截。个人体会路由守卫是前端权限控制的核心不要把所有验证都放在后端前端至少要拦住“未登录用户”这一层否则用户直接在地址栏输入内部页面链接能看到一堆报错信息体验远不如优雅跳转登录页。4.2 组件通信父子传值、事件总线与状态管理Vue 组件通信是前端面试高频考点在毕设里同样绕不开。我总结了三种方式的使用场景1. 父子组件传值props / emit这是最基础的通信方式父组件向子组件传数据用 props子组件向父组件抛事件用 emit。比如资源列表页ResourceList和分页组件Pagination之间父组件把总数、当前页作为 props 传给分页组件分页组件切换页码时通过 emit 抛出新页码。2. 事件总线EventBus适合跨组件通信比如登录成功后通知多个组件刷新用户信息。代码很简单// 新建 eventBus.js import Vue from vue export const eventBus new Vue() // 组件A中触发 import { eventBus } from /utils/eventBus eventBus.$emit(refreshUser) // 组件B中监听 eventBus.$on(refreshUser, () { this.loadUserInfo() })3. Vuex 状态管理当多个组件都要读取同一个用户信息、同一份全局配置时用 Vuex 最合适。不过毕设程度的需求大部分用前两种方式就够不用为了用 Vuex 而用。4.3 接口封装axios 统一处理省掉 90% 的重复代码前端调接口最忌讳每个页面各写各的 axios 请求。我做了统一封装所有请求都走一个模块// request.js import axios from axios import { Message } from element-ui import router from /router const service axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 10000 }) service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }) service.interceptors.response.use( response { const res response.data if (res.code ! 200) { Message.error(res.message || 请求失败) if (res.code 401) { localStorage.removeItem(token) router.push(/login) } return Promise.reject(new Error(res.message || 请求失败)) } return res }, error { Message.error(网络异常请稍后重试) return Promise.reject(error) } ) export default service这段代码的价值在于所有接口的 token 携带、错误提示、401 跳转都集中在这一个文件里其他地方只管调接口、用数据。页面代码里写service.get(/api/resources)就行不用关心 token 怎么带、报错怎么弹。5. 项目联调与功能测试前后端都写完之后要做的第一件事不是写论文而是把系统完整跑起来做整体联调。这个阶段最容易暴露接口对接问题、跨域问题、数据格式不一致问题。5.1 联调前准备统一接口返回格式我提前定好了一个统一的接口返回格式前后端都严格遵守{ code: 200, message: 操作成功, data: {} }code业务状态码200 成功400 参数错误401 未登录403 无权限500 服务器错误message给前端提示的文字信息data实际返回的数据对象或数组为什么要统一格式因为前端 axios 拦截器只需要解析这个固定结构就可以做全局错误提示和 token 过期处理。如果每个接口各写各的格式前端代码会非常臃肿而且出错了不好排查。5.2 功能测试清单边测边改别等最后很多同学喜欢把所有功能写完再一起测结果一测全是 bug来回改非常痛苦。我的习惯是每个模块写完就立刻自测。下面是我整理的功能测试清单模块测试项预期结果用户登录正确账号密码登录登录成功跳转首页用户登录错误密码登录提示“用户名或密码错误”用户注册用户名重复提示“用户名已存在”资源上传上传图片/视频/文档上传成功列表出现新资源资源上传上传超过大小限制文件提示“文件过大”资源浏览游客访问资源详情跳转登录页资源搜索按关键词搜索返回匹配资源列表管理员删除他人资源删除成功资源列表消失管理员管理用户状态禁用后该用户无法登录每一行都要实际跑一遍不要“觉得没问题”就跳过。实测下来登录和上传两个模块最容易出问题因为涉及 token、跨域、文件路径多个环节串在一起任何一个环节错位都会导致功能异常。5.3 跨域问题开发环境与生产环境的两种解法跨域是前后端分离开发绕不开的问题我分两种情况处理开发环境Vue CLI 的 proxy 代理在vue.config.js里配置代理让前端开发服务器的/api请求转发到后端地址// vue.config.js module.exports { devServer: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } }这样前端代码里写axios.post(/api/login, data)实际请求会被代理到http://localhost:8080/api/login浏览器层面不存在跨域因为请求发到了同源的前端服务器。生产环境Nginx 反向代理部署到服务器后用 Nginx 把/api请求代理到后端端口location /api { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }这个配置同时解决了静态资源托管和跨域问题Nginx 负责托管前端编译后的 dist 目录同时把/api转发给后端。个人体会跨域问题一定要在开发初期就建立正确认知不要等到联调才处理。很多同学前两个星期写代码一切顺利一到联调发现所有请求都被拦截心态直接崩了。正确的做法是开发第一天就把 proxy 配好后续所有接口调用都是“同源”的注意力才能集中在业务逻辑上。6. 数据库设计与项目部署数据库设计是系统的地基部署是系统的“最后一公里”这两块做好了项目才算真正完整。6.1 数据库设计实操从需求到建表前面 2.3 节已经展示了核心表的建表 SQL这里补充设计思路。一个多媒体共享平台的数据库设计核心是回答三个问题有哪些实体用户、资源、分类、评论这四个实体缺一不可实体之间有什么关系用户上传资源一对多资源属于分类多对一用户评论资源一对多哪些字段是必须的每个实体的关键属性要列全比如用户要有用户名、密码、头像、角色资源要有标题、类型、URL、上传者、分类、状态、时间用 ER 图的思路整理一遍表结构就清晰了。设计的时候记住几条原则字段类型宁大勿小状态用 TINYINT 没问题但是数量、次数这些可能增长的字段建议直接用 INT别用 TINYINT 后来再改。时间字段统一所有表都用create_time创建时间、update_time更新时间两个字段不要有的表叫 createTime、有的叫 created_at前后端对接时字段名统一能省很多事。冗余字段按需添加比如资源表的view_count浏览数和download_count下载数其实可以通过统计表算出来但直接冗余在资源表里查询更快、代码更简单。毕设场景完全够用。6.2 后端部署从 IDEA 到服务器后端的部署方式我推荐用mvn package打成 jar 包然后用java -jar直接跑。具体步骤在项目根目录执行mvn clean package -DskipTests生成target/*.jar把 jar 包上传到服务器可以用 scp 命令或者宝塔面板的文件管理器服务器上执行nohup java -jar xxxx.jar app.log 21 让服务后台运行查看日志用tail -f app.log确认启动成功无报错这里有几个细节端口号默认后端端口是 8080如果你的服务器上 8080 被占了常见的是别的 Java 服务占用了用--server.port8081指定新端口。数据库连接MySQL 数据库如果也在同一台服务器建议创建专门的数据库账号比如media_user不要直接用 root。用 root 一是安全风险二是以后迁移服务器、改连接串都麻烦。配置外置application.yml里的数据库密码、JWT secret 等敏感信息建议打包时排除部署时用--spring.config.location指定外部配置文件。这一步是加分项答辩老师问到“安全性”时你有话说。6.3 前端部署编译与 Nginx 托管前端部署分两步编译 托管。第一步编译在项目根目录执行npm run build编译产物在dist目录。如果编译报错先看是不是依赖没装全执行npm install再重新编译。第二步托管把dist目录里的文件上传到服务器然后用 Nginx 托管server { listen 80; server_name your_domain.com; root /var/www/media-share/dist; index index.html; location / { try_files $uri $uri/ /index.html; } location /api { proxy_pass http://127.0.0.1:8080; } }这里的try_files $uri $uri/ /index.html;很关键——Vue 是单页应用路由是前端路由history 模式刷新页面时如果服务器找不到对应路径的文件就会 404。加上这一行后所有未匹配到的路径都回退到 index.html由前端路由接管。常见问题刷新 404这是 Vue 部署最常见的坑首次部署 vue-router history 模式必踩。解决的思路就是上面加try_files。如果你的路由是 hash 模式URL 里有 #这个问题不会出现但 URL 不好看。6.4 部署文档怎么写才能拿高分最后说说部署文档。很多同学项目做完了部署文档随便写两页结果答辩时老师照着文档操作发现根本跑不起来印象分大打折扣。我的部署文档固定包含这些章节环境要求JDK 版本、Node 版本、MySQL 版本、Nginx 版本1. 安装 JDK、MySQL、Node附安装教程链接和验证命令2. 初始化数据库导入 SQL 文件的具体命令mysql -u root -p media_share.sql3. 后端部署jar 包使用说明、启动命令、查看日志命令4. 前端部署npm install、npm run build、Nginx 配置内容5. 常见问题端口被占用、数据库连接失败、刷新 404 的解决思路写部署文档的核心原则把自己当成一个什么都不会的新手每一步都写清楚每个命令都验证过。比如“MySQL 安装教程”不要只写一句“自行安装”而要写清楚下载地址、安装步骤、设置 root 密码的方法、创建数据库的命令。这不仅是文档也是你答辩时的“提词器”。7. 常见问题与避坑经验写代码的过程就是踩坑和填坑的过程。这一章把我实际遇到的高频问题整理出来帮你少走弯路。7.1 Spring Boot 版本陷阱降版本比配环境快得多最常见的坑就是Spring Boot 版本选择不当。很多同学从网上找教程直接复制最新版本号比如 3.x结果发现 JDK 不兼容、依赖下载失败、配置写法变了整套环境搭了三天还没跑起来。我的建议是JDK 8 Spring Boot 2.7.x这是最稳定的组合网上资料最多遇到问题基本都能搜到解决方案如果你本机已经装了 JDK 17可以选 Spring Boot 3.x但要注意javax.servlet改成jakarta.servlet等 API 差异千万别在毕设前折腾“最新版本”你不是在做技术预研你是在用最稳妥的方式完成学业任务如果实在遇到版本不兼容的问题最快的方法不是去查文档而是直接去 Maven 仓库mvnrepository.com查这个版本对应的依赖写法一步到位。7.2 视频播放 m3u8别在格式转换上浪费生命做过视频类平台的同学应该都遇到过 m3u8 播放问题。m3u8 是 HLS 协议的视频切片格式需要专门的播放器支持。如果在网页里要播放 m3u8 格式的视频推荐用video.js配合videojs-contrib-hls插件或者直接用hls.js。核心代码// 使用 hls.js 播放 m3u8 if (Hls.isSupported()) { const video document.getElementById(video) const hls new Hls() hls.loadSource(/static/sample.m3u8) hls.attachMedia(video) hls.on(Hls.Events.MANIFEST_PARSED, function() { video.play() }) }需要注意的是m3u8 播放可能存在跨域问题因为视频切片请求的是.ts文件这些请求也要走 CORS。如果你用 Nginx 托管视频文件记得在 Nginx 配置里加上跨域头。7.3 MySQL 安装与字符集utf8mb4 是底线MySQL 安装教程网上非常多但有几个细节容易被忽略Windows 安装时选择 UTF-8 字符集不要用默认的 latin1否则后期中文乱码会把你逼疯MySQL 8.x 和 5.7 的驱动配置不一样8.x 用com.mysql.cj.jdbc.Driver5.7 用com.mysql.jdbc.Driver。Spring Boot 2.7 大多配合 MySQL 5.7 或 8.0连接串要写成jdbc:mysql://localhost:3306/media_share?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai数据库名不要用中文有的人为了“好看”把数据库名起成中文结果 SQL 导入时各种报错纯属自找麻烦。7.4 Vue 安装与环境配置Node 版本别太新Vue 项目开发环境配置最容易翻车的是 Node 版本。Vue CLI 对 Node 版本有一定要求Node 14/16 都稳定配 Vue CLI 4/5 都没问题Node 18 不是不行但某些老项目的依赖会有兼容问题如果npm install报错先试试npm install --registryhttps://registry.npmmirror.com国内镜像源大概率是网络问题另外npm install报错时不要慌先看报错信息里的关键词是网络超时、依赖版本冲突、还是权限问题。多数情况下换镜像源、升级 Node 版本、删掉node_modules重新安装就能解决。7.5 其他高频坑后端返回的日期格式Java 的LocalDateTime默认序列化格式是2023-06-01T10:30:00不是2023-06-01 10:30:00。前端显示会很难看需要在后端加配置或注解统一格式。前端静态资源 404图片、CSS、JS 加载不出来先检查 Nginx 配置里的 root 路径对不对再检查文件权限chmod -R 755。数据库连接字符串里的时区问题连接串加serverTimezoneAsia/Shanghai可以解决“The server time zone value ... is unrecognized”报错。部署后日志时间不对服务器系统时区如果不是中国时区日志时间和你本地对不上。解决方案是启动命令加-Duser.timezoneAsia/Shanghai参数。最后再分享一个我自己写这类毕设项目的经验动手之前先把数据库表设计好、接口返回格式定好、前后端联调的 proxy 配好这三件事做好后面至少省一半时间。遇到版本问题、环境问题不要死磕优先换一个更稳的版本组合毕设是用来展示你掌握知识的能力的不是用来证明你有多能折腾环境的。项目能跑、逻辑能讲、坑能说清楚答辩基本就稳了。
阅读完成 · 觉得有帮助?
咨询建站