☰
SpringBoot+Vue文学创作社交论坛毕设项目完整解析
2026/10/12 6:32:37 网站建设 项目流程

这个标题看起来就像是一个典型的毕设资源包,“SpringBoot+Vue 文学创作社交论坛”加上“完整项目源码+SQL脚本+接口文档”这几个关键词,基本已经把这套东西的家底全亮出来了。作为过来人,我第一反应是:这不仅仅是一套代码,更是一条完整的“Java Web毕设生产线”。如果你想做类似的项目,或者正在纠结文学社区类系统怎么做,这篇内容基本可以帮你把数据库、后端、前端、联调部署的各个环节一次理清。

1. 项目整体设计与架构拆解

1.1 文学创作社交论坛到底在做什么

先别急着看代码,搞清楚这个论坛的核心业务是什么。文学创作社交论坛,本质上是一个UGC内容平台:用户注册登录后,可以发布小说、散文、诗歌等原创文学作品,其他用户可以查看文章、点赞、收藏、评论,还能关注作者。如果再进阶一点,会有作品连载、章节管理、排行榜、审核机制这些玩法。

从毕设的角度说,这个项目覆盖的知识点非常密集:用户体系、角色权限、内容管理、社交互动、数据检索、文件上传,几乎把Java Web方向该有的技术都串了一遍。这也是为什么SpringBoot+Vue前后端分离会成为这类毕设的主流选择——后端只管业务逻辑和数据,前端只管页面交互,分工明确,答辩时也容易讲清楚。

这个项目里的“xabo平台”应该是项目自己起的名字。多一个名字没有坏处,反而让答辩老师感觉这是一个认真做过完整设计和命名的项目,而不是东拼西凑的demo。

1.2 为什么选SpringBoot+Vue而不是传统JSP

如果你还在犹豫要不要随大流用SSH或者JSP做毕设,我建议你直接放弃。SpringBoot的优势在于简化配置,内嵌Tomcat,项目一启动就能跑,省掉了一堆XML配置的破事。Vue则解决了传统页面开发中DOM操作繁琐、组件复用差的问题,data驱动view的思路让前端代码变得非常直观。

前后端分离还有一个实际好处:开发和调试互不阻塞。前端可以用mock数据先跑界面,后端可以拿Postman先测接口,最后再联调。用项目里自带的接口文档,你可以把所有接口约定都写清楚,双方照着接口文档开发大幅减少扯皮。这套协作模式也是现代团队开发的基础形态,写在简历和答辩PPT里都是一个亮点。

1.3 整体技术栈与模块划分

一个完整的论坛项目,技术栈大概长这样:

  • 后端:SpringBoot 2.x、MyBatis或MyBatis-Plus、JWT、Spring Security(也可用拦截器实现鉴权)、MySQL 5.7/8.0
  • 前端:Vue 2.x或3.x、Vue Router、Vuex/Pinia、Axios、Element UI/Element Plus、富文本编辑器
  • 数据库:MySQL,配套SQL脚本
  • 部署:前端打包后扔进Nginx,后端直接java -jar运行

模块划分上,至少要包含这几个核心模块:

模块核心功能涉及技术点
用户模块注册、登录、个人信息、关注JWT鉴权、拦截器
作品模块发布文章、编辑、草稿、章节管理富文本、文件上传
社交模块评论、点赞、收藏、关注关联查询、事务
内容检索按标题/分类搜索作品模糊查询、分页
管理后台用户管理、内容审核、数据统计权限控制、图表

模块划分的目标是让每一个功能点都能在数据库表和后端代码中找到对应位置,这样的项目才是“完整的”,而不是表面堆功能。你在设计的时候也可以从这张表出发去画原型,哪怕只用Excel画个草图,后面写代码也会少走很多弯路。

2. 数据库设计与SQL脚本核心拆解

2.1 核心表结构设计思路

SQL脚本是这套源码里含金量最高的东西之一,我看到很多学生拿到手第一件事是把SQL导进去跑起来,但我要建议你从表设计开始读。核心表至少要覆盖这些:

用户表(t_user)

  • id:主键自增,或者用雪花ID
  • username、password:密码必须用BCrypt等加密工具加密存储,绝对不能明文
  • nickname、avatar、signature:用户资料字段
  • status:账号状态,正常/封禁
  • create_time、update_time:第一个是注册时间,第二个是最后操作时间,做排查特别好用

作品表(t_article)

  • id、user_id:作者外键,但物理外键不必加,逻辑关联就行
  • title、summary、content:标题、摘要、正文
  • cover:封面图URL
  • category_id:分类,关联分类表
  • status:0草稿、1审核中、2已发布、3已拒绝
  • view_count、like_count、collect_count:这三个计数可以用冗余字段,避免每次都count查询

评论表(t_comment)

  • id、article_id、user_id、parent_id:parent_id用来支持楼中楼回复,为Null就是顶层评论
  • content、create_time

点赞/收藏表(t_like、t_collect)

  • 这种关系表建议做联合唯一索引,比如(article_id, user_id),避免同一用户重复点赞

关注表(t_follow)

  • user_id、follow_user_id:一个是粉丝,一个是被关注者

分类表(t_category)

  • id、name、sort:分类名称和排序权重

表设计的核心原则是:每个表只存自己职责范围内的数据,关联关系用ID串联。不要什么都塞一张表,也不要为了省事把评论内容冗余在文章表里。

2.2 SQL脚本里的细节与坑

项目自带的SQL脚本,一般会包含建表语句、索引语句和初始数据。你导入的时候有几个地方要注意:

第一,字符集问题。建表时统一用utf8mb4,因为这个字符集支持emoji和生僻字,文学创作类平台经常有人粘贴特殊字符,用utf8会直接报错或者乱码。对应地,数据库连接串里也要加上useUnicode=true&characterEncoding=utf8mb4或utf8。

第二,引擎使用InnoDB。InnoDB支持事务和外键,MyISAM虽然读快但不支持事务,评论和点赞这种操作一旦并发就容易出数据错乱。新项目不要再用MyISAM了。

第三,初始账号和密码。SQL脚本里一般会带一个管理员账号,密码基本是密文存进去的,比如$2a$10$开头的一串BCrypt密文。你直接拿脚本里的密文登录就行,不要试图用别的方式去解,登录成功比什么都重要。

第四,身份证、邮箱等字段的幂等。比如邮箱用户反馈“明明没注册却提示已被注册”,大概率是SQL脚本里已经插入了测试数据,你只需要在数据库里查一下,把不相干的记录清掉就行。

初始数据这一块建议进入管理后台看看分类列表,如果没有分类数据,前端发布文章的页面可能拉不到分类下拉选项。不要等到页面傻掉才开始查原因,先把分类初始化好。

2.3 索引设计与查询性能

论坛项目的查询场景集中在文章列表、个人作品、搜索结果这几块,索引设计直接决定页面卡不卡。

  • 文章表:status + create_time 建立联合索引,因为列表页基本都查“已发布且按时间排序”
  • 评论表:article_id 加索引,不然文章详情页查评论会全表扫
  • 关注表、点赞表:联合唯一索引,既保证数据唯一性,又让查询走索引

倒排索引那些高级玩意毕设阶段没太大必要,但如果答辩老师问“文章搜索怎么更快”,你可以提一嘴:小规模用LIKE足够了,等数据量上来了可以引入Elasticsearch。这里记住一个原则——索引不是越多越好,过多索引会让插入和更新变慢,而且占用磁盘空间,最重要的查询场景建索引就够。

3. SpringBoot后端核心环节实现

3.1 项目分层与代码结构

后端拿到手先看包结构,标准的三层架构是com.xabo.controller、service、mapper(DAO)、entity、config、common、util。这套结构最经典也最好讲,答辩时按“Controller接收请求→Service处理业务→Mapper操作数据库”这条链路走一遍,思路就清楚。

区别于把业务逻辑全写在Controller里的写法,正常项目Service层一定会写复杂逻辑,比如发布文章时同时更新分类文章数,这个操作要加事务注解@Transactional。还要注意循环依赖和事务失效这几类问题:同一个类内部调用不会走代理,所以事务注解尽量加在Service入口方法上,而不是加到private方法上。

3.2 JWT鉴权与登录态管理

前后端分离的项目,登录认证一般选JWT(JSON Web Token)。原理很简单:用户登录成功后,服务端生成一个token返回给前端,前端把它存起来,后续每次请求都在请求头里带上Authorization,服务端解密校验通过就放行。

项目里一般会有一个LoginInterceptor拦截器或者Spring Security配置。如果你看到的是拦截器版本,核心逻辑大概是这样:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (CORS_PRE_FLIGHT.equals(request.getMethod())) { return true; } String token = request.getHeader("Authorization"); if (token == null || token.isEmpty()) { response.setStatus(401); return false; } // 解析token,获取userId并存入ThreadLocal Long userId = JwtUtil.parseToken(token); UserContext.set(userId); return true; }

这里有几个容易踩的坑,值得强调:

  • 前置OPTIONS请求必须放行。浏览器跨域时,如果请求头里带了自定义Header,会先发一个OPTIONS预检请求,拦截器如果直接把所有请求拦掉,前端就会报401,按钮点击毫无反应就是这个原因。
  • 拦截器配置拦截路径,比如/publish/**、/admin/**这些需要登录的接口,不要all拦截然后自己判断。
  • Token有效期,一般设置7天或24小时,时间太长不安全,太短体验差。项目里一般会有常量配置,你在答辩时可以顺口说一句话阐述这个考虑过程。

ThreadLocal存用户信息这套玩法非常实用。它让整个请求链条里的任何地方都能拿到当前用户ID,Service层和Mapper层不用每次把userId传过来传过去。但要记住在afterCompletion清理掉,防内存泄漏,否则长连接环境下会出现串号这种诡异问题。

3.3 发布文章与文件上传

作品发布是论坛的核心交互。前端用富文本编辑器把内容编辑好后,会以HTML字符串传给后端。后端存储时要注意安全性问题:富文本里可能夹带script标签,这就是典型的XSS攻击,不处理的话用户A可以拿到用户B的Cookie,后果很可怕。

项目一般会做全局过滤器或拦截器处理。比如用Jsoup组件对HTML内容进行过滤,清理掉script标签和危险的onclick属性。热搜里提到的“全局过滤器处理上传pdf文件时xss攻击”,虽然场景是PDF上传,但思路完全一致:对用户提交的富文本和文件内容做好白名单校验。传文件时,文件后缀一定要做白名单校验,图片就只允许jpg、png、gif、webp,不要拿后缀里的php当一个jpg文件给放了进去。

文件上传如果项目里用了本地存储,上传路径一般会配置成可配置项:

app: upload-dir: /data/xabo/upload

这样打成jar包部署时,文件不会散落在jar包内部,免得升级时文件被清掉。如果你看到项目里用的是MinIO这类对象存储,那就是oss的初级形态,配置桶名、AccessKey、SecretKey三个常量就能传文件。这个技术栈写进简历里还算加分,大多数毕设还停留在本地存储。

3.4 点赞收藏与防重复操作

点赞、收藏、关注这类操作,最大的麻烦在于防重复。用户疯狂点击,前端虽然做了按钮禁用,但后端必须兜底。

后端做法其实是数据库自带能力,直接在关系表上建联合唯一索引(article_id, user_id),然后插入时捕获DuplicateKeyException,捕获到说明已经赞过了,就删掉记录,取消点赞,其他情况继续正常插入。这种设计天然支持“点赞再点取消,再点重新点赞”的toggle逻辑,写起来省心,并发下不会出现两条重复记录。如果没有联合唯一索引,就要用select...exists判断,高并发下容易出现同时插入两条的脏数据。

3.5 分页查询与MyBatis配置

文章列表和评论列表都需要分页。项目里一般用的是MyBatis或MyBatis-Plus的分页插件,核心配置是先设置分页拦截器:

@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }

有了这个拦截器,页面里调PageHelper.startPage(pageNum, pageSize)或在Mapper传IPage对象就行。分页参数建议从请求参数里解出来,前端统一传pageNum和pageSize,后端统一返回total和records列表,这套约定在接口文档里要写明。

注意:如果你请求分页列表时发现total永远是0,或者只有第一页数据,先检查分页插件是否注册成功,再检查Mapper的XML里有没有自己写了LIMIT混用。分页插件和手写LIMIT同时出现,会让数据量计算乱七八糟。

4. Vue前端核心实现与页面机制

4.1 前端项目结构与初始化

前端拿到手先看目录结构:src下一般有api、components、router、store、views这五个主要文件夹。

  • api:按模块封装的请求方法,每个文件对应一个后端Controller
  • views:页面级组件,比如Home.vue、Login.vue、ArticleDetail.vue、Admin.vue
  • components:可复用组件,比如ArticleCard.vue、CommentList.vue
  • router:路由配置
  • store:Vuex或Pinia全局状态

正常情况下,每个页面的代码都会拆得比较干净。如果看到一个组件几百行没拆分,说明作者开发时比较匆忙,你接手后可以考虑重构一下。拆分组件不光是为了代码美观,更是为了复用:文章卡片在首页、分类页、个人主页都会出现,做成组件一次开发到处使用。

4.2 路由设计与访问控制

Vue Router是前端页面的导航中枢。项目里一般会有两种路由:普通游客能访问的公开页面和管理员才能访问的后台页面。

关键配置在路由守卫(beforeEach)里,逻辑大概是:检查目标路由是否需要登录,如果需要且当前store里没有用户信息,就跳转登录页。检查目标路由是否需要管理员权限,如果需要且当前用户不是管理员,就跳403页面。

这里有一个细节要特别提醒:前端守卫只是用户体验层面的控制,真正的安全校验必须由后端接口做。如果只做前端隐藏按钮而不做后端权限验证,那懂行的人直接调用管理接口就能拿到管理数据。前端隐藏、后端拦截,两头都得有。

动态路由是另一个常被问到的点。热搜里提到“vue动态路由”,基本原理是:登录成功后,后端返回当前用户的角色和权限菜单,前端根据这个结果动态addRoute注册路由项。管理员能看到用户管理页面,普通用户看不到,这就实现了“千人千面”。不过毕设阶段容易踩的坑是刷新页面后动态路由丢失,所以刷新时要从后端重新拉取菜单,或直接把路由配置全量注册但由菜单栏控制显示项。直接全量注册更稳,菜单栏按角色过滤显示就好,实现成本低一大截。

4.3 Vuex状态管理与登录态同步

前端全局状态一般存三类信息:用户基本信息、token、已读通知等临时数据。Vuex的典型用法是登录成功后commit一个setToken和setUserInfo,把数据放进去。Vuex的缺点是刷新会丢,所以项目里通常会双写:一份在store内存,一份在localStorage持久化。

// store/modules/user.js const user = { state: () => ({ token: localStorage.getItem('token') || '', userInfo: JSON.parse(localStorage.getItem('userInfo') || '{}') }), mutations: { setToken(state, token) { state.token = token localStorage.setItem('token', token) }, setUserInfo(state, info) { state.userInfo = info localStorage.setItem('userInfo', JSON.stringify(info)) }, logout(state) { state.token = '' state.userInfo = {} localStorage.removeItem('token') localStorage.removeItem('userInfo') } } }

这种写法刷新后token还在,用户不会被迫重新登录。Axios请求拦截器里再统一把token塞进Header:

axios.interceptors.request.use(config => { const token = localStorage.getItem('token') if (token) { config.headers.Authorization = token } return config })

响应拦截器也要处理好401状态,token过期时清空本地数据并跳回登录页,否则用户看到一个空白页面会一头雾水。

4.4 Axios封装与接口调用

项目里的接口调用基本统一走axios,而axios已经传入Vue原型或独立模块导出,建议直接看api目录下的文件格式,不要自己重新封装一套,否则有可能在请求拦截器、响应拦截器上重复加逻辑。

常见封装类似:

// utils/request.js import axios from 'axios' import { ElMessage } from 'element-plus' const request = axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 15000 }) request.interceptors.response.use( response => { const res = response.data if (res.code !== 200) { ElMessage.error(res.message) return Promise.reject(new Error(res.message)) } return res }, error => { ElMessage.error('网络异常,请稍后重试') return Promise.reject(error) } ) export default request

封装的好处是统一处理错误码,业务代码里不用每个页面都写try catch和弹窗。走读代码时看到业务代码只有薄薄一层,基本就是封装受益的表现。

4.5 富文本编辑器与作品发布体验

文学创作平台的核心输入是长文本,所以富文本编辑器是标配。项目里用的可能是wangEditor或Quill,前者更贴合国内开发者习惯。集成方式一般是在子组件中引入编辑器,代码大致这样:

mounted() { this.editor = new wangEditor(this.$refs.editorContainer) this.editor.config.uploadImgServer = '/api/upload/image' this.editor.config.uploadFileName = 'file' this.editor.create() }

要注意的是,编辑器上传图片的地址、token携带方式要和各项目需求对应好。如果上传接口需要鉴权Header,wangEditor要配置uploadImgHeaders或自定义上传函数,否则图片上传时会报401。

编辑器的内容存的是HTML字符串,回显时用v-html绑定,这时就有XSS隐患。后端在存储时已经过滤意味着回显时相对安全,但如果后端过滤不到位,前端用v-html时也会中招。所以核心原则还是那句:白名单过滤要放在后端做,前端的v-html只是展示手段。

5. 接口文档设计与前后端联调实践

5.1 接口规范与统一返回结构

接口文档是整个前后端协作的地基。这套项目自带的接口文档,一般会按模块分组,比如用户模块、文章模块、评论模块、管理端模块。每个接口会写明请求方法、路径、请求参数、响应示例。约定统一返回结构很关键,否则前后端字段对不齐,写代码全在调bug:

{ "code": 200, "message": "操作成功", "data": { "id": 1, "title": "春风十里" } }

状态码约定一般如下表:

code含义触发场景
200成功正常请求
400参数错误必填项缺失、格式不对
401未登录/token失效未带token或token过期
403无权限普通用户访问管理接口
500服务器内部错误代码异常

5.2 接口文档里该写什么

项目自带的接口文档,往往不只是用Markdown或Word写一写,也可能是Postman导出的JSON或Apifox的在线文档。不管哪种格式,一个合格的接口文档至少要包含:

  • 接口地址、请求方式、接口描述
  • 请求头(是否需要token)
  • 请求参数:参数名、类型、是否必填、说明
  • 响应参数:参数名、类型、说明
  • 请求示例和响应示例

举个例子,登录接口的文档应该写清楚:POST /api/user/login,参数username和password都是字符串必填,响应里返回token、nickname、avatar等字段。前端拿着这个文档根本不需要问后端任何问题。

写文档确实是磨人活,但好项目一定会配套文档。这不仅仅是给答辩加分,更是因为项目里前端、后端以及数据库之间的衔接如果做到“换人也能继续改”,这种工程规范本身就是招聘单位看重的软技能体现。

5.3 联调过程中常见的接口沟通问题

前后端联调,最常见的排序是这样的:

字段名大小写不一致。后端返回userName,前端期望username,页面显示undefined。定义好规范后,前后端都遵守规范就不会有这种问题。

时间格式不统一。后端返回时间戳,前端要展示yyyy-MM-dd,就需要前端做格式化封装。建议后端直接返回标准字符串格式,让前端省事,比如配置Jackson的日期格式:

spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8

分页参数理解不一致。前端传pageNum从1开始还是从0开始,pageSize默认多少,都需要在文档里写明确认。MyBatis-Plus默认从1开始计,顺序也统一用这个约定。

Mock数据的误差。前端用mock数据联调时,很容易实现的内容在真实接口里字段长度限制不同,导致首次真实联调时样式被内容撑爆。建议mock时尽量按真实字段长度和样式来,不要过度美化。

5.4 接口测试工具的选择

项目中如果配了Postman或Apifox的导出文件,可以直接导入使用。个人推荐Apifox,原因是它同时管理接口文档和测试用例,可以直接跑通接口并把结果同步给全组人看。相比Postman要另外配Newman或者快照,Apifox更省事。

测试接口时有两类要重点验证:边界值和业务规则。比如发布文章标题为空、正文为空、未登录发布,这些都应该返回明确的错误信息和对应的状态码,而不是抛出一整页Tomcat异常页。如果后端提示不够清晰,标准做法是先统一在全局异常处理器里把异常消息包一层。

6. 常见坑点与实操排查速查

6.1 部署运行前的环境准备

拿到源码后,环境配置是最容易卡住人的环节。Java 8或11、Maven 3.6+、Node 14+、MySQL 5.7或8.0,这是最常见的组合。项目如果使用SpringBoot 2.4以上版本,Java版本建议至少8u231,低版本可能获得TLS相关的类加载异常。

前端依赖安装用npm install或者yarn,建议用淘宝镜像源配置,否则等你下载完node_modules,天都黑了。运行后端前,检查application.yml或application.properties里的数据库连接、端口等配置。很多项目自带的是localhost默认配置,但SQL脚本里如果有其他host配置,直接改掉再启动。启动后端最烦的三类报错:

现象原因解决
Port 8080 was already in use端口占用换端口或kill进程
Access denied for user 'root'@'localhost'数据库密码错改application.yml里的密码
Unknown database 'xabo'数据库没创建先执行SQL脚本建库

6.2 前端跨域问题与代理配置

前后端分离,跨域是绕不开的坑。开发环境下,最常见且最优雅的解法是用Vue CLI的devServer代理:

// vue.config.js module.exports = { devServer: { port: 3000, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } } }

这样前端页面地址是localhost:3000,请求/api/login时由Vite或Webpack转发到localhost:8080/api/login,浏览器根本感知不到跨域的存在。如果后端配了CORS,两套方案可以共存,但开发阶段有了代理基本就够了。

如果把项目打包部署到Nginx,同样要在Nginx里做反向代理,把/api前缀的请求转发到后端服务:

server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; location /api/ { proxy_pass http://127.0.0.1:8080/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { try_files $uri $uri/ /index.html; } }

注意history模式路由需要try_files回退到index.html,否则刷新页面就是404。这一行配置能救回很多被坑到怀疑人生的同学。

6.3 版本兼容性与组件版本

热搜里有“springboot版本太高”这条词,大概率是有人在引入依赖时踩了版本不兼容的雷。SpringBoot 2.5+对MyBatis-Plus的兼容性是有要求的,SpringBoot 3.x直接不兼容MyBatis-Plus 3.4及以下版本,你需要换成mybatis-plus-spring-boot3-starter。如果项目本身是SpringBoot 2.3.5,建议保持原版,不要手贱升版本。

Vue 2和Vue 3对应的UI组件库也不同,Vue 2用Element UI,Vue 3用Element Plus。如果用Vue 3的工程,按Vue 2语法写会产生大量警告,页面呈现效果惨不忍睹。保持与项目自带的依赖版本一致是最高原则,毕竟毕设阶段的首要目标是一跑就通。

还有一个常见的坑是var与let混用导致的Scope问题、未安装Vue DevTools时排查困难。Vue DevTools是排查每个组件数据流的利器,可以直接看到state和props的变化。热搜里这么多人搜下载方式,就说明这工具确实好用。

6.4 JAR包反编译能看什么

热搜里有一条“怎么将springboot jar反编译成项目”,我猜是有人拿到的毕设源码不完整,只有jar包或者想拿别人jar里的代码学习。用jd-gui这个工具可以直接打开jar包,反编译出class文件对应的Java代码。但要注意,反编译出来的代码通常没有注释、变量名可能被混淆,而且不会给你SQL脚本和前端代码,只能作为参考和学习使用,不具备完整交付价值。

反编译能帮你看清楚Controller层接口路径、Service层业务逻辑,特别适合快速理解别人项目的接口返回结构和权限设计。但如果想实际修改部署使用,还是建议拿原始Java源码。

6.5 数据库表关系与外键策略的取舍

有人看到表设计没有物理外键就忐忑。实际上,互联网项目里普遍不用物理外键,原因很简单:外键约束会让插入和删除产生级联检查和锁竞争,高并发时性能受影响;而且如果误删主表数据,外键会连带删掉一堆关联数据,非常危险。逻辑外键配合应用层事务,足够保证数据正确性。

举个例子,用户删除自己的文章,物理外键方案是配置ON DELETE CASCADE自动把评论删掉;逻辑方案是在Service方法里手动执行两条删除语句并加@Transactional。两者效果一致,但逻辑方案在复杂业务里更容易控制细节,比如文章删了通知管理员、在回收站留一份快照等。

6.6 从源码包到答辩演示的要点

整套源码和文档都齐了,还差一步:准备答辩演示路径。不要妄想在答辩现场临时敲代码,必须提前规划演示顺序,建议按这条线走:

  1. 演示用户注册、登录、退出
  2. 演示发布一篇带图片的文章
  3. 演示文章列表和文章详情
  4. 演示评论、点赞、收藏、关注
  5. 演示个人主页展示自己发布过的作品
  6. 演示管理员后台的用户管理和内容审核

每步都提前准备好测试账号和测试数据,防止现场网络抽风导致图片加载不出来。答辩时老师通常会挑几个点深挖:JWT的token怎么生成和校验的,点赞怎么防重复,项目怎么部署的。源码里这些点都有对应实现,你按上面的思路梳理出自己的答案,基本就能应对大多数追问。

我个人在两年前完成过一套极其类似的文学社区项目,当时在点赞防重和富文本XSS过滤上栽了不少跟头。现在回头看,这类项目的难点从来不在于某个技术本身,而在于把用户、内容、社交这三个领域揉在一起时,数据关系和状态流转的梳理是否清晰。做毕设最大的收获,其实就是把这个梳理能力练出来。拿到一套完整的源码包后,少碰运气多读代码,把数据库表、Controller路由、前端页面对应关系摸透,答辩和面试就都能立于不败之地。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询