ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于SpringBoot+Vue的小说平台毕设实战:从数据库设计到前后端部署

基于SpringBoot+Vue的小说平台毕设实战:从数据库设计到前后端部署 1. 选题逻辑与系统定位为什么小说平台适合做Java毕设每年带毕设都会遇到一类经典问题题目既要有技术含量又要能在几个月内做完还得让答辩老师一眼看出工作量。从SpringBoot到Vue从数据库设计到接口开发这套技术栈基本覆盖了JavaWeb开发的核心链路而小说平台恰恰能把这条链路完整串起来。我的个人看法是小说系统并不是什么新鲜项目但它非常适合作为毕设原因有三。第一业务模型清晰——小说、章节、用户、书架、评论这些实体关系明确建表设计不会绕晕。第二技术覆盖面广——阅读时长统计涉及Redis缓存全文搜索涉及Elasticsearch或SQL模糊查询互动功能涉及消息推送每个模块都能展示独立的技术点。第三演示效果好——一个功能完整的小说平台演示起来比一个抽象的管理系统直观得多答辩时你可以直接打开页面展示阅读、评论、书架同步的真实操作说服力远强于PPT讲解。先说清楚这个系统到底要做什么。在线小说阅读与管理系统拆开来看包含三层面向读者的前台阅读端、面向作者的作品发布端、面向管理员的后台管理端。阅读端负责小说展示、搜索、分类浏览、阅读器、书架、评论互动发布端负责作者创建作品、维护章节、查看数据管理端负责审核内容、管理用户、处理举报。基于SpringBootVue的前后端分离架构前端走Vue Router控制页面跳转后端用SpringBoot提供RESTful接口通过Axios完成数据交互权限部分采用JWT令牌做身份验证。技术选型上我用的是SpringBoot 2.7.x Vue 3 Element Plus MySQL 8.0中间件搭配Redis和MinIO。SpringBoot版本不要追新2.7.x最稳定兼容性也最好很多第三方库对SpringBoot 3的Jakarta命名空间支持还不完善做毕设没必要冒险。MySQL用8.0是因为它原生支持窗口函数做小说分类排行榜时窗口函数比传统分组聚合简洁得多。MinIO用来存储小说封面图片和作者上传的附件——小说平台和普通CRUD系统的最大区别就在于有大量非结构化数据封面图、头像如果全部塞进MySQL数据库体积会迅速膨胀性能也会急剧下降。有的同学会问为什么不直接用SpringBoot开发单体应用、用JSP写页面这就要谈到JavaWeb到前后端分离演进的背景了。传统的JavaWeb项目Servlet JSP与SpringBootVue的根本差异在于关注点分离程度JSP的方案中Java代码和HTML耦合在同一个文件里前端逻辑改版必须改Java文件而前后端分离后前端项目可以独立运行、独立部署后端只需要按照既定接口契约输出JSON。如果你在简历上写熟练掌握JavaWeb面试官默认你会Servlet、Filter、JSP这些基础但你毕设如果还在用JSP又显得技术栈偏旧。实际上规范的JavaWeb基础Servlet生命周期、Filter拦截机制、Session原理和SpringBoot并不冲突——SpringBoot本身就内置了DispatcherServlet理解底层原理对调试和答辩都有价值。关于系统命名我在项目里把整个工程拆成了三个子模块novel-frontendVue工程、novel-backendSpringBoot工程、novel-admin-web后台管理前端。这样拆分的好处是职责边界清晰答辩时也可以明确地说我采用了前后端分离架构并且把用户端和管理端独立为两个前端工程这本身就是一个可讲的工作量加分项。2. 数据库模型设计小说系统的地基怎么打小说平台的数据模型是整个开发中最不能含糊的部分。表设计如果出问题后期写接口会不断被迫修改表结构、重构代码。我花了差不多一周时间反复调整了这些表核心原则是实体关系明确、查询路径短、扩展留有冗余。下面直接给出我最终敲定的表结构和设计理由。2.1 核心表结构用户、作品、章节、书架五张必备表第一张是sys_user用户表这是任何系统的基础。字段我设计了user_id自增主键、username登录名、password加密存储采用BCrypt算法、nickname昵称、avatar_url头像地址存的是MinIO的路径、role角色标识1为普通用户2为作者3为管理员、status账号状态0禁用1正常、create_time、update_time。角色的设计这里要特别说一下一个用户既可以是读者也可以是作者所以我在设计上允许作者角色继续阅读和评论而不是把作者限制为纯创作者。如果你想要更灵活的方案可以加一张用户角色中间表但做毕设用单字段枚举角色就够了简洁且不容易出错。第二张是novel_info作品信息表。这张表承载了小说书架页面的核心信息字段比较多novel_id、novel_name书名、author_id关联sys_user、category_id关联分类表、introduction简介、cover_url封面图地址、serial_status连载状态1连载中2已完结、click_count点击数、collect_count收藏数、word_count字数、latest_chapter_id最新章节ID、publish_time、update_time。注意latest_chapter_id这个字段——它属于典型的冗余设计每次发布新章节时需要同步更新这张表的对应字段。这样做虽然增加了代码逻辑的复杂度但换来了极高的查询效率书架页面不需要连表查章节表就能直接展示最新章节的信息用户浏览小说列表时也不必对每本小说执行一次子查询。第三张是novel_chapter章节表。这里有一个很多新手都会踩的坑把整本小说的所有章节都塞在一张表里并且把章节内容直接放在业务表里用text字段存储。我最终设计的字段是chapter_id、novel_id索引、chapter_no章节序号、title、content长文本、word_count该章字数、is_free是否免费可扩展VIP章节但前期可全部置为免费、audit_status审核状态、create_time、update_time。关键点在于content字段的数据量可能非常大我建议把章节内容单独拆到novel_chapter_content表与章节元信息一一对应。原因不必说是性能——更核心的是富文本编辑器的内容中可能包含样式标签比如段首缩进、加粗、图片标签它的体积远超普通字段的预期单独存放可以避免章节列表查询时被大字段拖慢响应。第四张是user_bookshelf书架表。字段为bookshelf_id、user_id、novel_id、last_read_chapter_id最近阅读章节、last_read_time、create_time。这张表的价值在于实现同步阅读进度——用户在手机上看了一半换电脑打开时可以直接定位到上次阅读位置。联合唯一索引要加在(user_id, novel_id)上防止同一用户重复收藏同一本小说。last_read_time专门用来做最近阅读列表的排序而书架里常见的时间排序依赖于这个字段。第五张是book_category分类表和sys_comment评论表。分类表就三个字段category_id、category_name、sort_order。评论表要设计成既支持对章节评论也支持对整本小说评论comment_id、novel_id、chapter_id允许为0表示整书评论、user_id、content、parent_id支持楼中楼回复、like_count、status0正常1被删除2隐藏、create_time。这里我多设计了一个parent_id是为了做二级评论这个功能虽然增加一些递归查询的复杂度但演示效果非常好也是答辩时可以重点讲的一个业务亮点。2.2 表关系与索引设计的取舍思路后台管理还需要额外的审核表、举报表但核心业务表就上面这六七张。这部分我想多聊一下索引的使用很多同学建表时完全不加索引导致后期测试数据一多接口立刻变慢。我的原则是所有外键字段必须建索引所有查询排序字段必须建索引。具体来说novel_chapter表的(novel_id, chapter_no)要建联合索引保证查询某本小说的章节列表能利用索引有序性直接按章节号排序而不需要额外的filesortuser_bookshelf表的(user_id, novel_id)联合唯一索引就不重复说了sys_comment表的(novel_id, status)索引则服务于评论列表的分页查询。表之间的外键约束我建议建但不用强制物理外键逻辑外键就够了。用物理外键FOREIGN KEY约束在MySQL里的问题是删除被引用行时必须先删除子表数据步骤繁琐而且在高并发下锁竞争更明显。做毕设时用逻辑关联也就是普通的索引字段配合Service层的事务控制就够了既保证了数据一致性的核心要求又不会在开发时被外键约束频繁卡住。3. 后端SpringBoot核心模块落地权限、发布与阅读链路后端开发阶段是工作量最大的部分我把它按业务链路拆成了几个模块逐个实现。下面按先搭骨架、再做核心业务的顺序把我实际的编码经验记录下来。3.1 JWT鉴权链路从登录到请求带令牌的完整流程传统JavaWeb用Session保存登录状态但前后端分离架构下Session方案存在跨域会话保持和并发扩展的短板尤其Vue前端常常部署在不同端口或域名上Session跨域处理很麻烦。这个项目我弃用了Session方案选择了JWTJSON Web Token做无状态认证。JWT的核心思想是用户登录成功后后端生成一个经过签名加密的字符串令牌返回给前端前端在后续每次请求时把这个令牌放进HTTP请求头的Authorization字段中后端通过拦截器或过滤器解析令牌验证签名和有效期解析出用户信息完成身份识别。由于JWT本身携带了用户基本信息服务端不需要在内存或Redis中保存Session数据。我在项目中实现这条链路用的技术组合是SpringBoot jjwt库 自定义拦截器。具体步骤如下引入依赖在pom.xml中引入io.jsonwebtoken:jjwt-api:0.11.5、jjwt-impl:0.11.5、jjwt-jackson:0.11.5三个包登录接口POST /api/auth/login接收用户名和密码用BCryptPasswordEncoder校验密码通过后生成JWT载荷部分存放userId、username、role三个字段expiration设置为7天签名密钥使用256位以上的字符串我用的是自定义配置在application.yml的jwt.secret自定义拦截器实现HandlerInterceptor接口在preHandle方法中读取请求头Authorization用固定前缀Bearer截取令牌尝试解析如果解析失败则抛出业务异常由全局异常处理器兜底返回401状态码用户信息传递将解析出的用户信息放入ThreadLocal中——我封装了一个UserContext类里面有静态的set和get方法这样Controller层不需要在每个方法里重复解析令牌直接UserContext.getUserId()即可。这个方法在高频请求下性能好但要注意请求结束后必须清理ThreadLocal否则线程池复用的线程会残留上次请求的用户信息造成用户数据串号。这里给第一次写JavaWeb项目的同学提个醒拦截器上的放行路径配置必须精确。登录、注册、小说列表、小说详情、章节内容这些接口是游客可以访问的要放在excludePathPatterns里而发布章节、评论、书架操作必须经过鉴权。我一开始把/api/**全部干掉了拦截导致前端登录接口也返回401排查半天才发现是拦截器把所有请求都拦了登录接口本身还没来得及获取token。3.2 作品发布与章节管理事务与富文本内容存储小说发布是平台的核心业务完整流程是作者在前端填写书名、简介、分类、上传封面图调用POST /api/novel创建作品接着在作品管理页面新建章节编辑内容点击发布调用POST /api/novel/{novelId}/chapter发布成功后后端需要同时做几件事——保存章节内容、更新novel_info的latest_chapter_id、累加word_count总字数。这几个操作必须放在一个事务里执行。所谓事务简单理解就是一组操作要么全部成功要么全部失败。如果章节保存成功但是更新作品的latest_chapter_id失败那么前台展示的章节列表和详情页的最新章节就会不一致用户会看到最新章节点进去是404这种低级错误。SpringBoot中使用Transactional注解是最方便的方式加在Service方法上即可。默认事务在抛出RuntimeException时回滚所以业务代码里必须用异常而非正常流程处理错误。富文本内容存储这块我踩过一次坑。最初的方案是前端直接把富文本编辑器渲染出的完整HTML包含样式标签和图片链接作为字符串传给后端存在novel_chapter_content表里。这样在阅读器里是可以直接渲染的但字数统计就麻烦了因为HTML标签不算字数。我最终改成了双字段方案content字段存原始HTML用于阅读器渲染content_text字段存储去掉标签后的纯文本用于字数统计和搜索。前端提交时编辑器给出纯文本内容用于字数计算而后端也做一次HTML标签剥离作为兜底校验双保险。章节目录的接口设计也有一个容易忽视的细节GET /api/novel/{novelId}/chapter/list不要直接返回章节正文内容只返回章节的id、title、chapter_no、word_count正文单独用GET /api/chapter/{chapterId}读取。这样做的理由很直接章节目录通常是在小说详情页一并请求的同时返回多个章节的正文会极大增加响应体积拖慢详情页加载而用户点击某一章时才拉取单章正文后续翻页阅读时也会经过阅读器逻辑。这叫按需加载是最基本的接口设计原则。3.3 阅读行为链路点亮进度、记录时长与书架自动同步阅读模块是我个人觉得最考验细节的部分。用户点进章节后前端需要做两件事一是把当前章节的阅读进度保存到书架表二是上报阅读时长。很多同学会设计成每次进入章节都执行一次完整更新这就是典型的性能浪费。我最终做成了两步。第一步比较轻量进入章节时调用POST /api/bookshelf/progress传novelId、chapterId后端执行一条INSERT ... ON DUPLICATE KEY UPDATE的SQL利用书架表的联合唯一索引有则更新、无则插入一条语句完成所有逻辑。第二步是阅读时长前端在用户离开阅读页、切换页面或退出浏览器时调用POST /api/reading/log把本次阅读时长以增量形式上传后端累加到阅读统计表。这种做法比定时上报要省请求量而且时机精准。为了展示效果更好我还在阅读器底部做了同步书架的提示按钮如果本次阅读章节与上次不同会弹出一个轻提示已更新阅读进度。这个交互让用户感知到我的数据被记录下来了在演示阶段特别有用。另外click_count点击量的统计我一开始是每次访问详情页就UPDATE novel_info SET click_count click_count 1后来发现高并发下这个操作会频繁锁行。改法是把点击量先累加到RedisINCR命令每5分钟或累计达到50次才批量刷回MySQL。这样既保证最终一致性又能避免数据库行锁竞争。如果是做线上项目这是标准做法就算是毕设你把缓存 定时刷库的思路讲出来也比一条裸UPDATE高级得多。4. 前端Vue页面体系与阅读体验实现后端接口齐了之后就是前端。Vue 3项目我用了create-vite脚手架初始化目录结构做了模块划分而不是把一堆组件全堆在views下面。4.1 前端路由与页面模块划分路由规划直接体现了一个前端的清晰度。我的router/index.js按业务领域拆成了几个路由模块/首页小说轮播图推荐 分类入口 近期热门/novel/:id小说详情页简介、目录、章节列表/reader/:chapterId阅读器页核心阅读界面/category?categoryIdxxxpagexxx分类列表页/search?keywordxxx搜索结果页/bookshelf我的书架需要登录/author/novel/manage作者管理后台需要作者或管理员权限/admin/*管理员后台模块页面懒加载路由守卫beforeEach用来做权限控制非常方便。我在全局路由守卫里读取localStorage中保存的JWT令牌和用户信息检查目标路由的meta中是否包含requiresAuth或requiresAdmin字段如果是则判断角色不符合就跳转到登录页。前端路由守卫只是体验上的控制——因为按钮和菜单可以隐藏但后端接口仍要鉴权这个我在上一章说过。前端守卫的目的是让未登录用户看不到入口后端拦截器才是真正的安全防线两层配合才叫完整的权限体系。页面代码上我用了Element Plus的组件库但自定义的样式也不少。首页的书籍卡片、详情页的封面悬浮效果、阅读器的背景皮肤切换这些视觉效果都是自定义CSS实现的。Vue组件的核心优势在于组件复用——我的BookCard.vue组件在首页、分类页、搜索页、书架页四个地方被复用只需要传递不同的novelInfo对象即可不用重复写展示逻辑。4.2 阅读器组件的关键实现翻页、字号与切换样式阅读器是整个前端里最有技术含量的部分。一个合格的阅读器组件需要支持字号调节、背景皮肤切换白色、浅黄、绿色、黑色夜间模式、目录侧边栏滑出、上一章/下一章切换。实现这些的核心其实就是状态管理和样式切换字体大小用data里的fontSize变量控制模板中绑定stylefont-size: px用和-按钮增减限制范围是14px到22px。背景皮肤用数据对象数组管理每一项包含className和name点击切换时动态给阅读区容器加class。目录侧边栏用的是el-drawer抽屉组件从右侧滑出数据来自小说详情页已经加载的章节目录接口。上一章/下一章则直接改变当前路由参数chapterId重新请求正文接口并把阅读器滚动位置清到顶部。这里有一个体验细节就是章节加载状态。章节正文接口一般有300到500ms的延迟如果不做加载提示用户会以为页面卡死了。我封装了一个简单的方式切换章节时把阅读区遮罩一层半透明的loading状态接口返回后再渲染正文。这个效果不用上Element Plus的Loading组件也能实现但加了会让演示体验提升不少。对于深夜看小说这个高频场景夜间模式是阅读器的标配功能。我在阅读器页面上加了皮肤切换后实测发现夜间模式不是简单的换个背景色就行正文文字颜色也要跟着变。系统提供以下几个组合白底黑字、淡黄底深棕字、浅绿底灰字、黑底浅灰字。页面切换皮肤时同时改背景色和文字颜色刷新后通过localStorage保存用户偏好这个细节在答辩时也可以提——我考虑了用户阅读场景的差异化体验并做了个性化偏好持久化。4.3 搜索与分类防抖、分页和筛选条件的组合搜索是平台的高频功能。我实现了一个搜索页面顶部是输入框和搜索按钮下面展示结果列表。这里有几个好习惯可以分享。第一是防抖debounce处理。在小说名搜索建议功能里每输入一个字符就请求一次后端接口会被服务器拒绝。我用了自定义的debounce函数用户停止输入500ms后才真正发起请求代码不到10行但演示时输入剑和剑来的间隔请求明显减少。第二是查询参数封装。搜索页支持关键字、分类、连载状态、排序方式四个条件组合。我把这些参数封装成一个searchQuery对象拼接成URL查询参数传给后端GET /api/search接口。因为参数是响应式的用户切换筛选条件时自动触发重新查询不需要手动维护多个页面状态变量。后端接口用Spring Data JPA或MyBatis-Plus的LambdaQueryWrapper动态构造查询条件这就体现了ORM框架处理复杂查询的便捷性。第三是分页加载。加载更多按钮触发pageNum 1并把新数据追加到列表尾部而不是替换列表这个交互在移动端上很自然。分类页我还会在顶部展示当前分类下的子分类导航比如玄幻下面细分为东方玄幻异界大陆王朝争霸前端通过同一接口传categoryId即可实现不需要单独的接口。5. 互动模块评论、点赞和排行榜中的实用套路小说平台不能只有读还得有互动。这部分我不打算展开全部功能代码而是挑几个我认为最值得写的技术点深入讲。5.1 评论模块楼中楼回复的姿态控制与敏感词过滤评论区的数据模型在第二章已经聊过这里讲两件实现上的事。第一是回复接口的设计POST /api/comment/reply接收parentId、novelId、content三个参数。如果parentId是0表示直接评论整本小说如果非0表示这条是某条评论的回复。前端渲染时判断parentId是否为0把回复内容缩进展示在父评论下方并显示用户名格式。第二是敏感词过滤的实现方式。这个功能可轻可重最轻的做法是维护一个敏感词表评论提交时逐条遍历用字符串的contains方法做匹配替换。这个方案在小数据量下完全可行我的系统里就是用的这个方案一张sys_sensitive_word表启动时加载进内存的Set集合提交评论时如果命中敏感词直接返回业务异常提示评论内容包含敏感词汇。如果你想让这个功能炫耀一点可以引入前缀树算法Trie把敏感词构建成树结构匹配效率从O(n*m)降低到O(n)但做毕设的话用Set足够了重点是把流程跑通。评论列表的查询里还有一个容易踩的坑评论表要分页评论回复也要分页两层分页会让前端渲染变得特别复杂。我的方案是第一层只分页顶级评论每条顶级评论下面默认最多加载三条回复LIMIT 3并提供一个展开全部回复的按钮点击后再请求该评论下的完整回复列表。这种折中方案对毕设展示来说完全够用而且交互也很常见。5.2 排行榜缓存Redis缓存热门榜单的过期策略小说平台一般都有热度榜收藏榜新书榜这些榜单模块。直接查数据库做排行很容易想到但每次打开首页都执行一次ORDER BY click_count DESC LIMIT 10这样的查询在点击量大的时候会给数据库增加不必要的压力——尤其多个榜单一起查就是好几条SQL。我的实现思路是把榜单数据缓存到Redis里key设计为ranking:click:daily、ranking:collect:weekly这样值为排行榜的小说基本信息JSON列表过期时间设为30分钟到1小时。前端请求排行榜接口时后端先从Redis查命中直接返回未命中则查MySQL并回填Redis。过期时间越短数据越新鲜但数据库查询次数也越多我做的是动态过期白天高峰期过期时间设为20分钟凌晨时段功能少、压力小过期时间设长到2小时也没关系。Redis在这套系统里还不止干这一件事。我顺手把热门搜索词也做了每次用户搜索成功后把关键词写入Redis的ZSet结构分数1然后定时把Top N关键词同步回MySQL的表里供首页展示热搜词条。一个中间件复用两种功能在答辩时很有说服力——你可以在系统设计部分写引入Redis实现热门榜单缓存和热搜词统计比单纯说用了Redis做缓存有力得多。5.3 动态通知机制用WebSocket做有新章节发布的实时消息小说平台有个场景很适合用WebSocket做实时推送用户收藏了一本连载中的小说作者发布新章节后收藏者希望能收到提醒。如果前端用定时轮询接口的方式既麻烦也不优雅。我在后端集成了SpringBoot自带WebSocket支持实现了一个轻量级通知模块。流程大概是作者发布章节成功后Service层调用WebSocketService.sendMessageToUser(userId, message)向目标用户的WebSocket会话推送一条JSON消息内容格式类似{type:NEW_CHAPTER,novelId:1,novelName:xxx,chapterTitle:第x章 yyy}。前端在全局Vue组件里创建WebSocket连接连接时通过URL参数携带userId实际项目必须做鉴权握手毕设可以简化收到消息后弹出一个轻提示。不用集成Spring Security做复杂的WebSocket握手鉴权但基本思路要有。实时消息模块的注意事项主要是连接管理用户关闭浏览器导致连接断开时后端要能感知到并从会话池中移除。我在WebSocket的afterConnectionClosed回调里清理了的就是当前会话避免无效推送。如果会话连接管理不好部署起来连接数会缓慢泄漏导致内存升高这是个隐蔽的性能坑。6. 打包部署与答辩准备从开发到演示的完整闭环开发完成只是成功了一半部署和演示环节出问题导致答辩翻车的情况每年都见得到。这一章把我的部署配置和答辩准备经验完整写出来。6.1 前后端分离部署Nginx与SpringBoot的配合环境部署我用的是一台2核4G的云服务器系统为CentOS 7。部署分三块后端jar包、前端静态文件、Nginx反向代理配置。后端打包含两个注意点。第一是SpringBoot的jar包要用Maven的package生命周期生成target/novel-backend-0.0.1-SNAPSHOT.jar第二是必须配置生产环境的application-prod.yml内容包含数据库连接URL、Redis地址、JWT密钥、MinIO服务的Endpoint。启动命令我用的是nohup java -jar novel-backend.jar --spring.profiles.activeprod server.log 21 这个命令的含义是以后台进程方式运行Jar使用prod环境配置日志输出到server.log。注意nohup和配合使用才能让程序在断开SSH连接后继续运行。前端部署相对简单。在Vue项目根目录执行npm run build生成dist目录然后把这个目录上传到服务器的/usr/share/nginx/html/novel路径下。Nginx配置里需要做两件事一是location /指向前端静态文件的目录做try_files $uri $uri/ /index.html——这是SPA路由的经典配置如果不加这个Vue Router的history模式刷新页面时会报404二是把/api、/ws等路径反向代理到后端服务的端口8080同时配置proxy_set_header Host $host、proxy_set_header X-Real-IP $remote_addr这样后端才能获取到客户端的真实IP用于后面的登录日志和异常监控。关于MinIO我单独建了一个minio目录存放jar包和启动脚本启动后用mc命令创建bucket并把bucket的访问权限设为只读公开这样封面图片可以通过http://服务器IP:9000/novel-cover/xxx.jpg直接访问。部署顺序要严格先启动MySQL和Redis再启动MinIO最后启动后端jar包。我踩过的坑是后端服务启动时如果连不上数据库SpringBoot会启动失败因为DataSource初始化不成功但日志只会在后段打印连接超时排查起来费时间。6.2 性能整理与答辩演示路线答辩演示和平时测试是完全不同的场景需要提前编排一套清晰的演示顺序。我的建议是进门先展示登录注册快速进入首页打开一本热门小说用阅读器翻几页切换到夜间模式加进书架再演示发布一本测试小说和评论回复。这样大概5分钟就能把系统亮点全部串起来。这个演示顺序对应到答辩讲解的逻辑是注册登录展示JWT鉴权首页展示缓存排行榜阅读器展示前端交互体验书架展示数据持久化和节本自动同步作者发布展示事务处理和后端接口能力评论和WebSocket展示实时互动。每个演示点都对应一个技术点这样答辩老师问这个怎么实现的你可以马上给出明确答复。关于性能优化这个项目我只做了必要的措施MySQL的慢查询日志开启并检查慢SQLRedis缓存的热门接口数据Nginx开启Gzip压缩减少前端文件体积。这些优化不用做太多把一条链路做透讲清楚就足够了。6.3 答辩前必须能答上来的8个高频问题根据我参加和旁听过不少毕业答辩的经验这些问题是老师最爱问的建议提前梳理答案为什么用前后端分离架构答提高开发效率前后端可并行开发部署灵活数据交互标准化通过RESTful接口返回JSON格式。JWT和Session的区别为什么选JWT答JWT无状态、不占服务端存储、天然支持跨域和分布式部署适用于前后端分离场景Session需要共享存储或做粘性会话处理。如果用户量很大你现在的系统瓶颈在哪答数据库连接数和磁盘I/O会成为主要瓶颈可以引入读写分离分库分表、增加Redis缓存命中率、对静态资源做CDN加速。排行榜数据怎么保证实时性和一致性答缓存更新用主动失效和过期结合——访问期间如果榜单数据源变化最多延迟一个过期周期展示刷库操作通过定时任务兜底实现最终一致性。MinIO和传统文件存储的区别答MinIO是开源对象存储服务提供S3兼容API适合存储大量非结构化数据支持扩容和权限管理比直接存数据库更适合实际生产场景。前端如何获取登录用户信息答登录成功后后端返回JWT前端把JWT存到localStorageaxios拦截器在每次请求时自动携带这个令牌路由守卫根据令牌是否存在来判断用户登录状态。事务都用在哪里答发布章节保存章节更新小说元信息、用户注册插入用户初始化书架记录、评论发布插入评论更新评论数这些场景都加上了Transactional。WebSocket连接需要鉴权吗答需要。正式系统应该在握手阶段校验用户的JWT令牌防止未授权用户建立连接或接收到不属于自己的消息。每个问题都不需要长篇大论三五句话给到关键点加一句落地方案就足以证明你确实是自己做的这个项目。做这个系统前后用了大约一个半月的时间最耗时的是数据库表设计和阅读器前端的细节调整反而是后端CRUD接口开发速度最快因为有SpringBoot自带的自动配置和MyBatis-Plus的代码生成器兜底。如果你也在做类似的毕设项目我的核心建议是不要一开始就追求功能堆砌先把一本书从发布到阅读的完整闭环做通再逐步加互动和实时特性每一步都理解了为什么这样做答辩时你根本不会怯场。
返回列表