1. 选题与需求拆解陕西民俗平台要解决什么问题很多人在毕业设计选题的时候会纠结是做一个通用管理系统还是做一个偏业务的站点。我这次选了中国陕西民俗网平台核心原因是它天然具备两条线一条是面向游客和普通用户的文化展示线一条是面向管理员的维护管理线。这样的结构特别适合本科毕业设计展示全栈能力也方便写成论文。项目标题虽然是“SpringBootVueMySQL”但实际交付物还包括数据库脚本、论文和部署文档。这四样东西加在一起才是能过答辩的完整闭环。只写代码不写文档或者代码跑不起来都是答辩现场最容易翻车的点。我后面会详细讲这部分先说说这个平台到底要做什么。1.1 需求梳理前台展示与后台管理的双向设计我最初做需求分析的时候没有照搬网上那些几十个功能模块的宏大方案而是围绕两个角色来拆普通用户游客浏览首页、按分类查看民俗项目、搜索关键词、查看民俗详情、发表评论、收藏感兴趣的内容。管理员登录后台、维护民俗分类、新增/编辑/删除民俗条目、审核评论、发布公告、查看用户列表。前台用的是博客类网站的表现形式后台则是一套典型的管理表格。这样做的好处是前台页面可以重点打磨视觉和交互后台表格可以重点体现CRUD的逻辑和权限控制两者加在一起工作量刚好覆盖一个学期项目的合理范围不会因为功能太多导致代码质量失控。1.2 为什么“民俗数据”比“新闻管理系统”更适合全栈设计我身边有不少同学选“新闻管理系统”“图书管理系统”其实这类题目很容易做成一堆表单的堆叠答辩时讲不出亮点。而陕西民俗这个方向本身就有很强的内容属性数据天然分门别类传统戏剧、民间舞蹈、传统美术、民俗节庆、传统小吃每个分类下面都有丰富的条目。一条民俗记录的信息结构比较复杂名称、所属地区、分类、简介、详细介绍、图片、浏览量等设计表结构时能讲到点子上。前台展示效果好首页放几张非遗图片配合轮播和卡片布局直观上就比纯文字表格有说服力。所以如果你正在纠结课题方向我的建议是选一个“内容有厚度”的领域哪怕是一个地方民俗、一家小店铺的商品展示都比空泛的增删改查更容易出彩。这个平台的选题核心就是用全栈技术把陕西地域民俗文化结构化地展示和管理起来。1.3 功能清单与页面规划我把功能最终圈定为这些模块方便自己写代码时不会跑偏模块功能点说明用户端首页轮播图、分类导航、推荐民俗、公告栏首屏要抓眼球浅色古朴风格民俗列表页分类筛选、关键词搜索、分页按分类或地区快速过滤民俗详情页图文详情、浏览量统计、评论区核心内容展示页面用户互动登录注册、评论、收藏评论需管理员审核可选管理后台民俗分类管理、民俗信息管理、评论管理、公告管理、用户管理管理员专属带登录拦截每个页面都是明确可验收的。我当时用了一张页面清单贴在项目文档首页每次开发完一个模块就打勾整个节奏会非常稳。2. 技术选型与版本兼容SpringBoot、Vue、MySQL怎么才能搭得顺选型这件事很多教程直接说“用SpringBootVueMySQL就行”但实际动手时版本之间互相卡的情况能浪费你一整天。我这里直接给出我验证过的一套稳定组合以及为什么选它们的理由。2.1 我最终锁定的技术栈版本技术版本选择理由JDK1.8最稳妥与大多数SpringBoot版本兼容答辩环境普遍是Windows下的JDK1.8Spring Boot2.7.x稳定且资料多比3.x少很多坑适合毕业设计MyBatis-Plus3.5.x单表CRUD不用写SQL能节省大量时间MySQL8.0支持JSON字段、性能好导入导出方便Vue3.4.x Vite构建快组件语法现代化Element Plus2.x后台表格、弹窗、表单开箱即用Pinia2.x管理登录状态比Vuex更简洁这里特别说一下Spring Boot版本。很多同学看新教程直接上3.x结果JDK版本要求从8变成17有些服务器还不支持最后折腾在环境问题上。毕业设计追求的是稳定和可复现能不冒险就不冒险。用SpringBoot 2.7 JDK 1.8这套组合无论是Windows本地还是云服务器几乎不会出现启动失败的问题。2.2 前后端分离的架构与跨域处理平台采用前后端分离后端跑在localhost:8080前端开发服务器跑在localhost:5173两者通过HTTP接口通信。分离的好处是职责清晰前端专注于页面交互后端只提供JSON数据。但分离也带来一个问题——跨域。前端请求后端接口时浏览器会拦截不同端口的请求。我的解决方案是在后端加一个全局跨域配置把所有请求都放行Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }这段代码的作用是允许所有来源访问后端接口。allowCredentials(true)是给登录后携带Cookie用的如果你用Token方式登录这一项也可以不开启。我实际使用的是JWT Token方案所以allowCredentials这里只做了兼容性保留。2.3 关于MyBatis-Plus与手写SQL的取舍这项目的数据库操作我大部份基于 MyBatis-Plus 的mapper.selectPage()和mapper.selectById()。比如分页查询民俗列表只需要调用一次PageFolklore page folkloreMapper.selectPage( new Page(current, size), new LambdaQueryWrapperFolklore() .eq(StringUtils.hasText(categoryId), Folklore::getCategoryId, categoryId) .like(StringUtils.hasText(keyword), Folklore::getTitle, keyword) .eq(Folklore::getStatus, 1) .orderByDesc(Folklore::getCreateTime) );这样能少写大量重复SQL专注于业务逻辑。但有几个场景我保留了手写SQL多表联查民俗信息加分类名称、统计评论数量、首页热门推荐。手写SQL能精确控制JOIN和索引也让论文里“数据库设计”章节有内容可写。所以你不用纠结“用工具还是手写”推荐把单表操作交给框架把复杂查询自己写出来两种都有展示反而更全面。3. 数据库设计民俗数据拆成几张表最合理数据库是整个系统的地基做不好后面写什么都费劲。我设计表的时候完全是从平台的实际业务流程出发而不是照搬书上的范式理论。3.1 核心数据表一览平台一共用了8张表分别是表名用途关键字段user普通用户账号id, username, password, nickname, avatar, statusadmin管理员账号id, username, password, last_login_timefolklore_category民俗分类id, category_name, sort, statusfolklore民俗详情主表id, category_id, title, summary, content, cover_image, images, region, view_count, statuscomment用户评论id, folklore_id, user_id, parent_id, content, status, create_timefavorite用户收藏id, user_id, folklore_id, create_timeannouncement网站公告id, title, content, status, publish_timesystem_config首页配置id, config_key, config_value这张表的数量不算多但足够覆盖所有功能而且每一张表都能在论文的ER图里讲清楚。3.2 民俗主表字段的设计思路folklore表是内容核心我特意设计了几个容易忽略但很实用的字段summary摘要字段。列表页展示的简短文段避免每次详情页读大段content文本提升列表页性能。region地区字段。陕西地域文化有很强的地区属性比如华县皮影、凤翔木版年画、安塞腰鼓分地区展示是很自然的需求。cover_image和images封面图和相册图。封面图用在卡片和列表images用JSON格式存多张图片地址。view_count浏览量。用户在详情页打开时接口里直接updateById加一首页“热门推荐”就基于这个字段排序。status上下架状态。管理员可以暂时隐藏某条民俗不需要物理删除。这里要重点说说images字段。有些刚接触后端的人会习惯再建一张“图片子表”但毕设规模其实没必要。MySQL 8 支持JSON类型我用JSON存一个图片路径数组插入时序列化进去读取时直接反序列化成List给前端简单又省事。如果未来要单独查询图片再拆表也来得及。3.3 表关系的几个关键点folklore与folklore_category是多对一关系通过category_id关联。comment与folklore、user的关系是每个字段一个外键逻辑物理外键我没有加。parent_id字段用于实现评论的楼中楼回复虽然平台里只做了一层嵌套但留这个字段就有扩展空间。物理外键不加的原因也很实际毕业设计里代码操作逻辑比约束更灵活MyBatis-Plus 在删除或批量操作时有物理外键反而容易报错。从功能角度逻辑外键在业务层控制就够了。3.4 数据初始化民俗内容从哪里来数据库脚本里除了建表语句我预留了两类初始化数据系统数据admin账号、默认分类列表、首页轮播配置。民俗展示数据我整理了几十条具有代表性的陕西民俗条目比如秦腔、华县皮影戏、凤翔木板年画、陕北秧歌、陕西剪纸、社火表演等每条只保留基本信息内容由自己归纳组织。这里有一点要提醒不要直接大段复制百科原文。无论是课程设计还是正式项目版权和查重都是实际问题。我的做法是把每一条民俗提炼成“名称概述来源地区传承情况”几句话算是二手资料整理不会太短也不会堆砌。论文里也会注明资料来源为公开出版物和官方网站。4. 后端接口实现重点登录鉴权、内容展示与后台管理后端我按controller-service-mapper三层结构拆分包名沿用com.shanxi.folklore这样一个与项目关联的命名。下面挑几个核心接口讲这些也是答辩时老师最喜欢追问的地方。4.1 统一返回体与全局异常处理前端无论请求什么接口返回格式必须一致不然联调时前端每个人都要单独做一次数据解析。我封装了一个通用结果类Data public class ResultT { private Integer code; private String message; private T data; public static T ResultT ok(T data) { ResultT r new Result(); r.setCode(200); r.setMessage(操作成功); r.setData(data); return r; } public static T ResultT error(String message) { ResultT r new Result(); r.setCode(500); r.setMessage(message); return r; } }再加一个全局异常处理类捕获业务异常和空指针异常返回统一格式。这样后端即使报错前端拿到的也是{code:500, message:系统异常}这种标准结构不用在控制台瞎猜。4.2 JWT登录鉴权流程用户和管理员登录都用JWT实现流程是用户提交用户名密码。后端校验用户表密码用 BCrypt 加密后做比对。生成Token返回给前端Token里带上用户ID和角色。前端把Token存到本地之后每次请求都放到请求头的Authorization字段。后端拦截器解析Token校验通过才放行受保护接口。登录接口大致长这样PostMapping(/api/user/login) public ResultLoginVO login(RequestBody LoginDTO dto) { User user userService.login(dto.getUsername(), dto.getPassword()); String token jwtUtil.generateToken(user.getId(), USER); LoginVO vo new LoginVO(); vo.setToken(token); vo.setNickname(user.getNickname()); return Result.ok(vo); }管理端和用户端的Token我通过角色字段区分。拦截器里判断当前请求路径是否以/api/admin开头如果用户角色不是ADMIN直接返回“无权限”。这样只用一套鉴权逻辑就能保护整个后台。4.3 核心接口清单我把后端接口列一个表方便你对照着理解整个系统的能力方法路径功能权限POST/api/user/register用户注册公开POST/api/user/login用户登录公开POST/api/admin/login管理员登录公开GET/api/folklore/page分页查询民俗列表公开GET/api/folklore/{id}民俗详情浏览量1公开GET/api/folklore/recommend首页热门推荐公开POST/api/comment提交评论登录用户GET/api/comment/list/{folkloreId}查询某条民俗的评论公开POST/api/favorite添加收藏登录用户GET/api/favorite/my我的收藏列表登录用户POST/api/admin/folklore新增民俗管理员PUT/api/admin/folklore修改民俗管理员DELETE/api/admin/folklore/{id}删除民俗管理员GET/api/admin/folklore/page后台分页查询管理员GET/api/admin/user/page用户列表管理员PUT/api/admin/comment/status修改评论状态管理员这个接口表我直接写进了论文的“系统详细设计”章节。实际写代码的时候你会发现每个接口都是围绕“查一圈、增一条、改一列、删一行”在展开但正因为有了业务场景和权限分层整体才有逻辑深度。4.4 文件上传与图片处理的坑民俗内容里有大量图片所以上传接口是必须的。我后端用的是原生Spring MVC的MultipartFile配置一个文件存储路径file.upload-path./upload/上传接口保存图片后返回访问URL。这里有两个容易出错的地方访问路径要映射Servlet需要额外配置静态资源映射把/upload/**指向物理路径否则浏览器访问不到图片。文件名不能随意我统一用了UUID 原始后缀的重命名方式避免中文文件名乱码和重复覆盖。PostMapping(/api/upload) public ResultString upload(RequestParam(file) MultipartFile file) { if (file.isEmpty()) { return Result.error(请选择文件); } String originalFilename file.getOriginalFilename(); String suffix originalFilename.substring(originalFilename.lastIndexOf(.)); String fileName UUID.randomUUID().toString().replace(-, ) suffix; File dest new File(uploadPath fileName); file.transferTo(dest); return Result.ok(/upload/ fileName); }因为部署时upload文件夹很可能不在jar包目录下部署文档里我特意写了“手动创建upload目录并检查路径分隔符”这一步Windows和Linux路径分隔符不同这类问题也是答辩演示时最容易卡壳的地方。5. Vue前端核心页面与交互从首页轮播到后台表单前端用Vue3 Vite Element Plus项目结构按真实工程习惯拆分避免把所有代码都塞进一个巨型组件里。5.1 前端目录结构我在src下划分了这几个目录src ├── api // 按模块封装的接口请求 ├── assets // 静态资源 ├── components // 公共组件轮播、分页、卡片 ├── router // 路由配置 ├── stores // Pinia状态管理 ├── utils // axios实例、token工具 └── views // 页面级组件 ├── home ├── folklore ├── user └── adminutils/request.js中封装了一个axios实例统一做三件事请求自动带Token、响应码非200时弹出提示、遇到401跳转登录页。这一步是整个前端联调的定心丸能让每个请求都不重复写错误处理。5.2 首页与民俗详情页实现首页主要靠几个异步请求拼装数据轮播公告、分类导航、推荐列表。我用onMounted里同时发起三个请求数据回来之后分别填充到对应响应式变量。const categoryList ref([]); const recommendList ref([]); onMounted(async () { categoryList.value await getCategoryList(); recommendList.value await getRecommendFolklore(); });民俗详情页用动态路由/folklore/:id进入页面后拿路由参数请求详情接口。页面布局是左侧图文展示区右侧热度信息与收藏按钮。详情页还包含评分列表和评论表单评论提交时需要判断用户是否已登录未登录则弹出登录对话框。这个交互点很能体现前端对用户状态的处理。5.3 管理后台的路由守卫与权限控制后台路由单独挂在/admin路径下组件里带有侧边栏和顶部栏的布局。我在路由配置里加了一个全局前置守卫router.beforeEach((to, from, next) { const token localStorage.getItem(admin_token); const isAdminRoute to.path.startsWith(/admin); if (isAdminRoute !token) { next(/login?redirect to.fullPath); } else { next(); } });这个守卫的作用是只要用户没有管理员Token访问任何后台页面都会被请到登录页。我们前后端都做了权限校验而不是单纯依赖后端拦截——因为前端要负责“不显示无权限的入口”后端要保证“即使绕过前端也不能访问数据”两层配合才算安全。5.4 后台核心表格与表单弹窗后台管理界面用的Element Plus以民俗管理为例页面结构是顶部搜索栏关键词输入、分类下拉、查询按钮。中间表格显示封面缩略图、标题、分类、地区、浏览量、状态、操作按钮。底部对话框新增和编辑复用同一个表单组件通过formData.id判断是新建还是更新。操作列编辑、上下架、删除三个按钮。el-table :datatableData v-loadingloading el-table-column label封面 width100 template #default{ row } el-image :srcrow.coverImage stylewidth: 60px; height: 60px; fitcover / /template /el-table-column el-table-column proptitle label标题 width220 / el-table-column propregion label地区 width120 / el-table-column label状态 template #default{ row } el-tag :typerow.status 1 ? success : info {{ row.status 1 ? 已上架 : 已下架 }} /el-tag /template /el-table-column /el-table页面不用写得太复杂重点是完整。前端做到“所有后台功能都能在页面上找到入口”答辩时演示就很顺畅。6. 打包部署与论文整理让源码当场跑起来才是硬道理毕业设计和平时练习最大的差别是学生做的项目“必须要能在别人的机器上运行”。所以打包、部署、文档这三样比多写一个页面重要得多。6.1 前端打包与后端集成开发阶段前后端分离没问题但最终交付时最好做到“一键启动”。我的做法是执行npm run build生成dist目录。把dist目录复制到后端项目的src/main/resources/static下。后端用Maven打包成单个jar文件。这样部署时只需要启动一个Spring Boot应用静态页面和接口都在同一个端口下不会出现“前端文件有了但接口跨域”的问题。npm run build mvn clean package -DskipTests java -jar target/folk-platform.jar6.2 服务器部署与初始化步骤答辩前我找了一台云服务器做演示环境步骤是安装JDK1.8和MySQL8.0。导入database.sql初始化数据和表结构。把jar包和upload目录传到服务器同一目录下。修改application.yml中的数据库账号密码启动测试。用Nginx做域名访问配置反向代理到8080端口。这一步最容易被忽略的是upload目录。我在部署文档里写明“如果上传图片后无法访问检查jar包同级目录下是否有upload文件夹并确认通过URL访问/upload/xxx.jpg时路径能正确匹配”。我自己就因为少建了一个目录现场演示图片全部白屏过。6.3 论文章节安排与“查重”避坑论文我是按标准软件工程流程写的结构如下绪论选题背景、国内外研究现状、研究内容。相关技术介绍SpringBoot、Vue、MySQL、前后端分离。系统分析可行性分析、需求分析、用例图、流程图。系统设计总体架构、数据库设计、接口设计。系统实现每个模块的代码截图、页面截图、核心代码说明。系统测试功能测试用例、性能简单测试、结果分析。总结与展望。写论文最容易出问题的是技术介绍部分很多人会整段照搬官方文档。我的经验是每一段都用“我在项目中用来解决什么问题”来结尾比如“Spring Boot具有自动配置和起步依赖的特性可以在减少手动配置的同时快速搭建独立运行的应用。本项目通过Spring Boot完成RESTful接口的编写和静态资源配置避免了大量XML配置文件显著提升了开发效率。”这样既写了理论基础又带出了项目结合点查重和评阅都更稳妥。6.4 部署与答辩前实测清单我在答辩前一周专门做了一次全流程冒烟测试把操作步骤打成了一个清单测试项操作预期结果数据库初始化执行database.sql8张表全部创建管理员账号可登录用户注册登录前台注册新用户登录后评论和收藏可用管理员登录后台地址登录跳转管理首页侧边栏正常新增民俗填写表单、上传图片前台列表出现新记录图片加载评论审核后台屏蔽一条评论前台详情页评论消失修改密码管理员修改自身密码退出后新密码可登录因为清单上每一项都提前跑过答辩时即使被问到“系统崩溃怎么办”我也能直接说清楚哪些问题在部署文档里有处理方案。这种准备方式能让两个小时的实习成果变得很扎实。7. 复盘与扩展方向毕设代码怎么才能有“项目感”整套系统做完之后我回头复盘最大的收获不是掌握了增删改查而是理解了“一个能落地的系统”和“一个能跑通的功能集合”之间的差别。7.1 我的核心体会演示链路比功能数量更重要很多同学在网上找几个开源模板改一改就算做完了结果答辩时问到底层原理一无所知。真正要做的是把所有功能串成一条能够在五分钟内完整演示的价值链路用户注册 → 浏览民俗分类 → 查看某一条皮影戏详情 → 发表评论 → 收藏 → 后台审核评论 → 修改民俗信息 → 前台验证结果。这条链路覆盖了前后端交互、权限控制、数据流转、状态变更所有关键环节。只要链路是通的哪怕功能少一点你都完全有资格讲清楚整套系统是如何运作的。7.2 平台后续可以扩展的方向陕西民俗只是一个细分领域同样的架构完全可以扩展成其他类型的内容平台。我列出了几个有价值的方向供你参考增加非遗地图把region字段升级成经纬度坐标结合地图组件展示陕西各地非遗分布比纯列表直观很多。接入小程序端前端已经做了移动端适配基础小程序可以复用全部接口重点是重新写一套UI组件。增加管理员审核流民俗条目由普通用户投稿管理员审核后上线这会让系统从“单向展示平台”升级为“内容共建平台”。增加数据统计通过浏览量、收藏量、评论数做热门排行并生成简单报表既体现算法逻辑也为后续推荐功能打基础。最后一提这套项目虽然不是商业级系统但已经包含了一个成熟网站的基本要素用户体系、内容模型、后台管理、权限控制、部署方案。把它吃透上来就能理解真实公司的前端和后端是怎么协作的。你如果也打算拿这一套做毕业设计我建议直接把标题里的“SpringBootVueMySQL”当作技术底座把重心放在“内容深度”和“功能完整度”上这样不管答辩老师盯数据表、接口还是页面你都能拿得出东西。