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

文章详情

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

SSM+VUE实现戏曲文化交流小程序:毕设项目全流程拆解

SSM+VUE实现戏曲文化交流小程序:毕设项目全流程拆解 每年这个时间点咨询毕业设计的人就多起来了。戏曲文化交流小程序这个题这两年出现的频率挺高它确实有天然优势既沾了传统文化弘扬的边又不是那种一眼看到底的纯增删改查系统。技术栈写的是SSMVUEJava Web方向沿用多年的经典组合岗位对口、资料多、踩坑经历随手就能搜到。这篇文章不聊虚的直接把这类项目从选题拆解、数据库设计、后端分层、前端VUE对接到最终部署和答辩会被问到的问题一次讲清楚。不管是刚拿到题还在观望的同学还是想参考别人完整思路的开发者都可以照着这份内容往下走。1. 为什么这类毕选题要选SSMVUE它到底香在哪1.1 毕设选题要满足的隐藏要求很多同学选题目的时候只看好不好做忽略了毕业设计真正要做的事它不是让你造一个多牛的系统而是要完整展示一套软件工程流程。从需求分析、数据库建模、后端接口设计、前端页面联调到测试和文档每一步都得能从代码里找到对应实现。戏曲文化交流小程序恰好覆盖了这些环节。它有用户端内容展示有用户注册登录有发帖评论的互动模块还有后台管理系统负责内容维护。这个体量不大不小对于一个人完成来说非常合适。功能太简单比如只做一个资讯展示答辩的时候没啥可讲功能太复杂比如要做在线支付、直播推流又超出大多数人的能力范围。戏曲交流这种选题定位刚好卡在中间偏上的位置。1.2 SSM三件套到底谁管谁SSM是Spring SpringMVC MyBatis的缩写很多同学背概念会背真问起来又说不清三个框架的边界这其实是答辩时第一个容易露馅的地方。Spring管的是对象和事务。Service层的业务对象由Spring容器创建和管理事务也统一交给它控制你不需要在每个业务方法里手写连接开启和提交。SpringMVC管的是Web层路由前端请求打到哪个Controller方法参数怎么绑定返回的JSON怎么渲染都由它处理。MyBatis管的是SQLMapper接口定义方法XML文件写SQL语句两者根据约定绑定。三个框架各管一层分工很清楚。答辩的时候如果能说出Spring负责解耦和事务SpringMVC负责请求分发MyBatis负责数据持久化三层各司其职这比笼统说一句用了SSM框架要强太多。1.3 VUE前端和小程序形态怎么理解很多同学拿到这个题目会有疑问标题写小程序技术栈却是VUE这里到底怎么实现常见且合理的做法是用户端用VUE写一套移动端H5页面按照小程序的页面风格和交互习惯来设计底部Tabbar、页面跳转、列表加载这些交互全部对齐小程序体验。开发完成后如果要真正上线到微信小程序可以在H5页面基础外套一层承载壳通过web-view嵌入或者用多端框架做迁移。毕设演示阶段用浏览器直接跑移动端H5页面效果和用小程序打开几乎一致而且比拿着Android模拟器折腾要省心得多。后台管理端则用VUE配合现成的组件库实现比如Element UI或Vant数据表格、弹窗表单、上传控件这些都能直接拿来做。为什么要选VUE而不是JSP因为VUE做前后端分离之后前端项目和后端项目完全独立各跑各的进程调试时只需要关心接口数据格式效率确实比页面里嵌Java代码高。2. 功能模块拆解把毕设需求变成能写的页面2.1 双端模块的拆分思路这类项目标准做法是拆成用户端和后台管理端。用户端面向普通用户功能围绕看戏、学戏、聊戏。后台管理端面向管理员功能围绕内容维护、用户管理、数据统计。两个端不能混在一个页面里否则权限会乱代码也会变得难维护。用户端核心模块包括首页、戏曲分类浏览、剧目资讯、交流社区、个人中心。首页通常放轮播图、分类导航、最新资讯推荐戏曲分类按剧种组织比如京剧、越剧、豫剧、黄梅戏、评剧交流社区是用户发布帖子、评论互动的地方个人中心承载我的收藏、我的帖子、个人资料修改。后台管理端则相对固定登录认证、轮播图管理、分类管理、资讯管理、剧种剧目管理、帖子审核、评论管理、用户管理和简单的数据统计面板。这里要注意后台的帖子审核功能建议保留因为交流社区如果没有审核机制管理员角色就显得多余答辩时也容易被问如果用户发了违规内容怎么办这种问题。2.2 戏曲内容怎么组织才不显得空戏曲内容不能只有一张表打天下否则系统撑不起来。建议拆成两层剧种分类和剧目内容实体。剧种是分类维度比如京剧、越剧、黄梅戏剧目是具体内容比如京剧《贵妃醉酒》、越剧《梁祝》、黄梅戏《天仙配》。一个剧种下面挂多个剧目自然形成一对多的关系。除了剧目还应该有资讯内容。可以做戏曲演出公告、名家动态、戏曲知识科普这几类。资讯表单独拿出来是因为内容和结构跟剧目差别很大混在一起会导致字段冗余查询也麻烦。这样内容体系拆完以后首页推荐、分类浏览、搜索功能都有了数据来源演示效果不会空虚。2.3 交流社区怎么设计才像交流很多毕设的交流模块只是机械地做发帖回复其实可以稍微多做一丢丢体验上的东西。发帖时允许用户选择分类比如京剧讨论越剧交流问答求助闲话戏曲这样帖子列表页可以按分类筛选不至于所有内容堆在一起。帖子详情页除了正文还可以支持多个图片这一点在页面展示上视觉效果会好很多。评论模块要区分对象。一条评论既可以针对帖子也可以针对剧目详情页这样设计表结构的时候用一个targetType字段区分而不是给每类内容单独建评论表。至于审核后台审核通过后帖子才在前台列表可见管理员可以驳回并填写理由。这套机制让系统闭环也体现了内容安全管理的思路。3. 数据库设计从需求到表结构的一次到位3.1 核心表清单与职责边界数据库设计是答辩的重头戏老师看到表结构基本上就能判断这个项目有没有认真做。核心表建议这么划分表名职责关键字段说明user用户信息username、password、nickname、avatar、role、status、create_timeopera_type剧种分类name、description、cover_url、sortopera剧目内容type_id、title、description、content、video_url、cover_urlarticle资讯文章title、cover_url、summary、content、views、publish_timepost交流帖子user_id、title、content、images、category、status、viewscomment评论user_id、target_type、target_id、content、parent_id、create_timecollect收藏user_id、target_type、target_id、create_timebanner轮播图image_url、link_url、sort、status用户表里role字段建议用tinyint类型0表示普通用户1表示管理员演示前手动往库里插一个管理员账号比写死在后端配置里灵活。password字段用MD5或SHA加密存储不要明文存这既是安全要求也是答辩加分点。3.2 表关系设计的几个关键决策主关联关系是operate表通过type_id关联opera_type表形成剧种到剧目的一对多。post表通过user_id关联user表评论表通过target_type和target_id实现多态关联既能评论帖子也能评论剧目。收藏表的设计同理用targetType区分收藏的是剧目还是资讯。这里有个很多同学容易犯的错误把评论表和收藏表分别拆成帖子评论表剧目评论表剧目收藏表资讯收藏表看起来分类清晰实际上代码里要写四套增删改查而且扩展一个新内容类型就要再建两张表。用target_type target_id一个字段组合就解决的事拆表反而是给自己挖坑。数据库设计的核心原则是面向扩展而不是面向当前页面展示。3.3 字段细节决定了系统好不好维护每个表都建议带上create_time如果有状态流转再加update_time。status字段是另一个容易被忽略的重点资讯、帖子、剧目都需要类似字段0代表待审核或下架1代表已发布可见这样做比直接删数据要安全得多也为后面的审核机制提供数据基础。逻辑删除也是个实用细节。比如用户注销或者违规帖子下架不一定非得DELETE掉加一个deleted字段查询时统一带上deleted0条件保留数据痕迹。索引方面user表的username要做唯一索引post表的category和status建议做普通索引因为在列表页经常按这两个字段筛选。数据量小的时候索引效果看不出来但表结构里体现出来是专业度的象征。4. 后端SSM实战分层架构与核心代码实现4.1 统一返回结果和全局异常处理前后端分离项目里接口返回的数据格式必须统一。很多同学写接口时有的返回String、有的返回Map、有的直接返回对象导致前端axios封装没法统一处理。我建议从第一行代码就定死一个Result类结构public class Result { private Integer code; private String msg; private Object data; public static Result success(Object data) { Result result new Result(); result.code 200; result.msg 操作成功; result.data data; return result; } public static Result error(String msg) { Result result new Result(); result.code 500; result.msg msg; return result; } }Controller层每个接口都返回Result对象前端只看code就知道请求成没成功不用在error回调里做各种解析。全局异常处理可以用ControllerAdvice标注一个类捕获Exception统一转成Result格式返回这样业务代码里就不需要大量try-catch代码更干净。4.2 MyBatis动态SQL处理多条件查询列表页最常见的需求是关键字搜索 分类筛选 分页。如果针对每种情况都写一条SQL代码会爆炸。MyBatis的whereif组合就是来解决这个问题的select idsearchPosts resultTypecom.example.entity.Post SELECT * FROM post where status 1 if testkeyword ! null and keyword ! AND (title LIKE CONCAT(%, #{keyword}, %) OR content LIKE CONCAT(%, #{keyword}, %)) /if if testcategoryId ! null AND category #{categoryId} /if /where ORDER BY create_time DESC /select分页推荐使用PageHelper一行PageHelper.startPage(pageNum, pageSize)再查列表返回结果会自动带上页码信息。这套组合在小项目里极其稳定不用自己手写limit和count省下的时间可以用来补测试用例。4.3 登录鉴权不用JWT也能做得体面很多同学一提到登录鉴权就想到JWT但在SSM毕设项目里引入JWT意味着要处理生成、解析、过期刷新等一堆逻辑反而增加了复杂度。更务实的做法是自己生成token存库用户登录成功后用UUID生成一个唯一字符串把userId和token的映射关系存到数据库用户表里前端后续请求都通过请求头Authorization携带这个token后端写一个拦截器统一校验。public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token request.getHeader(Authorization); if (token null || !1.equals(redisOrDbCheck(token))) { response.setContentType(application/json;charsetutf-8); response.getWriter().write({\code\:401,\msg\:\请先登录\}); return false; } return true; } }登录拦截器只管登录没登录权限区分用角色字段判断。管理员接口额外加一个判断普通用户访问后台接口直接拒绝。这种方式代码量少解释起来也好懂答辩时提到我用token鉴权不用session是因为前后端分离后session跨域维护成本高这个回答比我用的是JWT更能体现理解深度。4.4 图片上传不能只写到一个static目录交流发帖、剧目管理、轮播图管理都需要图片上传。最简单的做法是Controller接收MultipartFile保存到本地磁盘一个uploads目录再把访问URL返回给前端。这里有个关键配置必须把上传目录映射成静态资源访问路径否则图片上传成功但前端打不开。在SpringMVC配置类里加资源映射Configuration public class WebConfig implements WebMvcConfigurer { Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceMapping(file:/绝对路径/uploads/); } }这个配置很容易被忽略很多同学前后端联调时发现图片404找半天不知道问题出在静态资源映射上。另外上传时要注意限制文件类型和大小只允许jpg、png、gif大小在5MB以内避免被人传一个木马文件上去。5. 前端VUE实现从零到能演示的完整路径5.1 前后端分离的项目目录怎么组织VUE前端建议拆成两个独立子项目而不是一个项目里又跑用户端又跑后台。用户端放一个目录叫app后台管理放一个目录叫admin。两者都是独立的VUE项目启动端口不同部署时互不干扰。为什么不用路由来区分因为用户端的风格和后台完全不同组件、依赖、打包体积都不一样拆开以后你只改动后台时不用重新构建用户端效率高很多。VUE项目内部按功能模块组织api目录放所有请求接口utils目录放axios封装和工具函数views目录放页面组件router目录配置路由。有一点提醒所有请求不要直接写在页面组件里而是封装到api目录的函数中这样页面组件只负责调用接口地址改了也只需要改一个文件。5.2 axios封装决定了你联调时的幸福指数axios封装做不好联调阶段全是重复代码。一个基础版封装要处理三件事统一baseURL、统一请求头加上token、统一处理响应状态和错误提示import axios from axios const service axios.create({ baseURL: process.env.VUE_APP_BASE_API || http://localhost:8080/api, timeout: 10000 }) service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] token } return config }) service.interceptors.response.use( response { const res response.data if (res.code ! 200) { return Promise.reject(new Error(res.msg || 请求失败)) } return res }, error { console.error(接口错误, error) return Promise.reject(error) } )环境变量里的baseURL记得区分开发和生产开发环境跑VUE的8080端口代理到后端生产环境直接指向同域名下的/api路径。这里如果忘了处理跨域会出现开发环境调通、一部署就失灵的情况我在实战里见过太多次。5.3 列表页与详情页的组件化写法用户端首页和资讯列表、剧目列表的结构高度相似建议抽成公共组件。比如ItemCard组件接收一个数据对象渲染成图片在上、标题在下的卡片分类列表页和推荐列表都复用它。VUE的props传参写起来非常简单但很多同学为了省事直接在每条v-for里写完整DOM改动样式时需要一个个改非常低效。列表页逻辑要关心的是加载状态、空数据状态、加载更多。初次进入页面显示loading骨架屏请求回来后渲染列表如果列表为空显示一个暂无内容的占位滚动到底部触发下一分页加载。这三个状态能覆盖用户所有使用场景也显示出你对前端交互的理解是到位的。5.4 发帖和评论的交互细节发帖页的关键是表单校验。标题不能为空字数限制50字内内容不能为空且不少于10个字这些校验在前端做一遍后端的接口入参校验也要做一遍。前端校验提升用户体验后端校验保证数据安全缺一不可。评论交互要注意的是提交后的处理。评论成功后不要重新加载整个帖子页那样体验很差更优的做法是把接口返回的新评论封装成评论对象push到当前评论列表数组的最前面同时刷新评论计数。这样页面无跳转、无闪烁观感好很多。收藏功能的交互同理点击收藏后图标变实心再次点击取消同步请求后端接口即可。这些细节看起来不起眼在实际演示时会给老师留下这个学生是真的做过项目的印象。5.5 从H5页面到小程序形态的适配技巧如果学校要求看到小程序形态最实用的方案是开发阶段完全用VUE写移动端H5页面设计稿按照375px宽度来做页面用flex弹性布局和rem单位这样页面天然适配手机屏幕。要演示小程序时可以将H5页面嵌入到一个小程序壳中用web-view组件承载这样既保留VUE的开发效率又能在微信开发者工具里展示出小程序的运行形态。如果是使用uni-app这类多端框架则可以在开发初期就启用小程序编译模式VUE语法基本不变只是路由和页面生命周期要遵循框架规范。这里要提醒一句不要等到开发完再想着转小程序启动时就确定方案否则后来改页面结构会非常痛苦。选择H5嵌web-view的好处是不改现有代码演示成本最低。6. 联调、测试与常见问题排查实录6.1 跨域问题第一时间就解决它前后端分离开发时最经典的问题就是跨域。前端跑在http://localhost:8080的VUE开发服务器后端跑在http://localhost:8081的Tomcat两者的端口不同浏览器出于安全策略会拦截请求。解决方式有两种开发阶段最简单的是在VUE项目里配置devServer代理把/api路径代理到后端地址devServer: { proxy: { /api: { target: http://localhost:8081, changeOrigin: true } } }这样前端请求/api/login会被代理转发到http://localhost:8081/api/login浏览器视角里请求是同源的跨域问题消失。如果需要真正跨域调用比如打包后放在不同域名下后端配置CORS过滤器才是长久之计。两种方案建议都实现开发用代理生产用CORS避免部署环境不一致时再折腾。6.2 数据库中文乱码和时区问题MySQL默认编码如果不是utf8mb4插入中文数据会变成问号。数据库建库时要指定字符集连接串也要加上useUnicodetruecharacterEncodingutf8。答辨前最好把数据库连接配置里的中文编码参数补齐这是排查乱码问题的第一道关卡。时区问题往往更隐蔽。数据库连接串版本8以上的MySQL如果不加serverTimezoneAsia/Shanghai启动时会直接报错这是遇到必踩的坑。加上以后Java侧的时间对象和MySQL的时间字段才不会有8小时的偏差。6.3 运行报错速查表把常见报错整理成一张表可以有效减少反复排查的时间错误现象可能原因解决方案前端请求报404接口路径写错或后端未部署接口先查后端的Tomcat控制台请求日志确认接口路径和请求方式请求返回500后端代码异常看Tomcat日志堆栈锁定到具体行一般是空指针或SQL错误数据库访问报ClassNotFoundJDBC驱动版本和MySQL版本不匹配检查pom.xml里的mysql-connector版本换对应版本登录后请求未授权token没传或拦截器配置路径不对检查axios请求头是否加Authorization拦截器的排除路径是否配全图片上传成功但访问404静态资源映射未配置检查WebConfig里的资源映射路径和绝对路径是否一致日期字段返回一串数字Jackson序列化格式问题在日期字段加JsonFormat(patternyyyy-MM-dd HH:mm:ss)这个表格不建议临时抱佛脚开发过程中每撞上一个问题就在里面记一笔。等到最终写LW文档的系统测试章节时直接把这些整理成测试用例省不少时间。7. 部署上线与毕业答辩准备要点7.1 本地跑通一套的最小配置本地环境建议统一为JDK 1.8、Tomcat 9、MySQL 5.7或8.0、Maven 3.6、Node 14。JDK版本别太新SSM项目在JDK 17以上偶尔会遇到反射相关的兼容问题用1.8最稳。后端项目用Maven构建成WAR包放到Tomcat的webapps目录即可或者开发阶段直接在IDEA里配置Tomcat启动。前端在用户端和后台管理项目目录下分别执行npm install和npm run serve开发环境即可访问。数据库导入项目附带的SQL文件注意导入前检查建库语句的字符集设定。7.2 答辩时老师最爱问的几个问题答辩问题基本集中在为什么这么设计和某个功能怎么实现的两类。准备时重点搞定以下几个方面。为什么选SSM而不用SpringBoot这是高频问题。回答思路SSM更贴近底层能清晰看到Spring配置、MyBatis映射、SpringMVC拦截器的组装过程SpringBoot虽然简化了配置但把细节封装掉了毕设用SSM更能体现对Web开发核心组件的掌握。这个回答逻辑通顺老师一般不会再追问。用户的密码安全怎么做要说清楚MD5加密存储并且加密时加盐。如果只是MD5暴力破解成本很低加个固定salt会好很多。线程安全问题。比如多个用户同时收藏同一个剧目数据库会不会出问题。回答思路数据库自带事务保证收藏操作明确设置唯一索引后重复收藏会被数据库拦截业务层再加异常处理即可。如何保证发帖内容不违规后台审核机制加上前端输入校验和长度限制必要时后端加敏感词过滤接口。能说清楚这两层已经足够。7.3 LW文档千万别写成流水账毕设文档的常见问题是把系统功能介绍写得像产品说明书。LW文档应该体现的是分析过程而不是功能罗列。需求分析部分先描述现状与痛点再引到本系统要解决什么数据库设计部分要画清楚表关系并解释每个设计决策的理由测试部分用表格列用例包含操作步骤、输入数据、预期结果、实际结果。有个小技巧文档里的截图不要随便截完就贴要保证图上出现清晰的路径、关键数据并且给图加编号正文引用编号做说明。老师看到图文对应印象分会高很多。代码不要大段复制粘贴到正文只放关键方法片段和核心配置否则查重铁定过不去。最后再分享两个实际经验。第一这类项目哪怕是直接拿别人的源码来改造也建议把用户登录、发帖、评论这三个核心流程自己重新手敲一遍。因为答辩老师大概率会从这三个流程里挑细节问你亲手写过一遍心里才有底。第二Demo前记得备份数据库演示过程中万一误删了数据还能一分钟恢复现场不然紧张状态下真的救不回来。动手写就完了项目本身难度不大但认真对待和敷衍了事最后呈现出来的完成度完全不一样。
返回列表