☰
基于Spring Boot的学生读书笔记共享系统:毕设选题与全栈实现
2026/10/13 10:26:19 网站建设 项目流程

又到毕业季,后台私信里问得最多的还是同一个问题:毕设到底做什么题目才不容易翻车?市面上那些商城、管理系统、外卖平台早就烂大街了,答辩老师一眼就能看出来你是从哪扒的模板,问两句就露馅。今天我想把一个我带过的学生反复打磨过的选题拿出来聊聊——基于Spring Boot的学生读书笔记共享项目。这个题目的业务场景很真实,技术栈也是Java方向公司里最常用的那一套,功能规模对毕设来说不大不小刚刚好,而且天然带“内容 + 互动”属性,想加亮点、写优化都有地方下手。

这篇文章我打算按做项目的真实流程来讲:从题目怎么定、技术选型为什么这么选,到数据库怎么建模、核心功能怎么写、部署时踩过什么坑,最后连答辩时老师爱问什么也一起整理给你。整套源码我已经做了脱敏和注释补全,导进IDEA就能跑,免费分享给正在发愁的同学。适合三类人:一是计算机相关专业、正在纠结毕设选题的大四学生;二是想通过一个完整Spring Boot全栈项目来充实简历、准备找工作的Java开发;三是刚学完Java基础、特别想看看真实项目到底长什么样的朋友。

1. 项目整体定位与技术选型

1.1 毕设题目为什么挑中“读书笔记共享”

选毕业设计题目有个很重要的原则:业务边界要清楚,但又能让老师看出你有独立设计能力。纯商城、纯增删改查的管理系统,业务逻辑简单到没东西讲,答辩时只能用“我用到了某某框架”来撑场,很容易被追问到半导体。你说说看,这个场景里用户能写笔记、能分享笔记、能看别人的读书心得、能评论互动,天然就包含了“用户身份”“内容创作”“内容展示”“社交反馈”这一整条主线。它不像社区论坛那么大,也不像个人博客那么单一,边界清晰但五脏俱全,改成“学习笔记共享”“技术文章共享”也完全说得通。

从另一个角度看,读书笔记这种内容型产品,和大学生生活贴得非常近。你自己去图书馆自习、写课程总结、整理考研资料,都是这个系统的使用场景。在做需求分析时,你不需要去凭空想象“商家需要什么、运营需要什么”,你只要把自己当成用户,功能自然就浮现出来了。这在写开题报告、需求文档的时候特别占便宜,写出来的东西有真实感,不是那种一眼假的伪需求。

1.2 技术栈选型背后的权衡

这套项目主技术栈是Spring Boot + MyBatis Plus + MySQL,再加Redis做缓存、JWT做身份认证,前端用Vue 3 + Element Plus,前后端分离。下面逐个说为什么这么定。

Spring Boot是当前Java后端开发的事实标准,它把Spring繁琐的XML配置全部自动化了,内嵌了Tomcat,打包成jar直接就能跑。选它首先是为了降低工程方面的负担,让你把注意力放在业务逻辑而不是配置上。MyBatis Plus是MyBatis的增强工具,单表查询不用写XML映射,BaseMapper里现成的CRUD方法直接调用,分页、逻辑删除、自动填充这些功能都内置了,能省下很多重复代码。MySQL作为关系型数据库,存储用户、笔记、评论这些有明确关系的结构化数据,它是久经考验的默认选择,你出去工作大概率也绕不开。

Redis在这里不是硬性要求,但我强烈建议加上,因为它是你在答辩时的一个“差异化亮点”。热门笔记列表、阅读量、验证码这些场景,用Redis缓存或者做计数器非常合适。你用不上高并发,但要能讲清楚“为什么这里用Redis而不用MySQL”,这一句话就能让老师觉得你真的思考过。JWT做登录态是现在前后端分离项目的主流方案,服务端不存储Session,用户登录后拿一个签名字符串,后续请求带上就行。后面我会专门讲它的实现流程。

有人可能问,为什么不直接上Spring Cloud微服务?我的回答是:毕设的单体项目不要为了微服务而微服务。微服务要拆服务、配注册中心、搞分布式事务,对本项目来说完全是大炮打蚊子。真拆了,你不仅部署不起来,答辩时还会有老师追问你“分布式事务怎么做”,到时候很容易把自己绕进去。单体架构部署简单、逻辑清晰、好调试,对毕设是正确选择。这一点你在答辩时完全可以正面表达,老师反而会觉得你思路务实。

1.3 项目结构怎么组织

项目我用Maven多模块管理,看起来更专业,也方便单独复用。工程结构大概是下面这样的:

  • note-common:通用工具类、统一返回结果、异常处理
  • note-system:系统核心模块,用户、笔记、评论、点赞等业务代码
  • note-framework:配置类、安全拦截、Redis配置
  • note-web:Controller层、启动类

如果你觉得多模块麻烦,做成单模块按包分层也完全够用:controller、service、mapper、entity、config、common、utils。包结构清楚,答辩老师看你的项目结构就不会觉得乱。我的经验是,包命名一定要见名知义,别出现什么utils2、test之类的诡异目录,细节处最体现工程素养。

2. 系统功能模块拆解

2.1 用户模块:注册登录与个人信息

用户是系统的身份基础,没有登录态就谈不上“我的笔记”和“共享”。注册功能我做了两种方式:普通的用户名+邮箱注册,以及基于Redis的邮箱验证码注册。用户名会做唯一性校验,密码不是明文入库,而是用BCrypt加密后存储。BCrypt是Spring Security里集成的一种哈希算法,它每次生成的密文都不一样,但校验时又能正确匹配,比简单MD5安全得多。很多Demo项目用MD5加盐,但如果你能在项目里用BCrypt,答辩时就是一个小加分点。

登录成功后,后端会生成一个JWT令牌返回给前端。之后前端访问需要登录的接口,都在请求头里带上这个令牌。令牌里只放用户ID和用户名,不塞密码等敏感信息,过期时间我设的24小时。这里有个细节:为了让用户改完头像、昵称后能立刻生效,一些接口会通过JWT里的用户ID实时查询数据库,不依赖令牌里的固定信息。

个人中心部分包含头像上传、昵称、个人简介、学校院系这些基本信息。头像上传走的是本地文件存储,把文件保存到服务器指定目录,保存相对路径到数据库,访问时通过映射接口读取。当时如果想省事,也可以直接用FastDFS或OSS,但毕设项目里自己实现一个简单的上传接口反而更能体现基本功。

2.2 笔记模块:创作与内容管理

笔记模块是整个系统的核心,主要功能包括写笔记、存草稿、编辑、删除、私密笔记、公开笔记。写笔记时我用的是Markdown编辑器。Markdown的好处是纯文本、占用空间小、格式简单,保存到数据库就是一段带标记的字符串,前端渲染时再解析成HTML。对比传统的富文本编辑器,它省去了图片Base64入库那种臃肿的事情,对毕设来说适配成本低。

数据模型上,笔记表里有一个关键字段status,我用了三种状态:0草稿、1私密、2公开。草稿只有作者自己能在“草稿箱”里看到,私密笔记只能作者本人查看,公开笔记才进入共享列表、可以被别人浏览。这个设计的好处是,“共享”不是一个开关,而是一种状态,后面你要加“审核中”之类的状态,直接在这个字段上扩展就行。

笔记列表需要支持分类展示、标签筛选、关键词搜索。分类可以用一级分类字段,标签我单独建了一张标签表做多对多关联。搜索阶段先用MySQL的LIKE模糊查询,比如标题匹配、内容匹配、摘要匹配,配合联合索引已经能应付毕设的演示场景。如果你有余力,可以在论文里写“下一步计划接入Elasticsearch做全文搜索”,这个后面具体讲。

2.3 共享与互动模块:评论、点赞、收藏

读书笔记共享的核心不只是“能看”,而是“能互动”。这套系统里互动功能做了三个:评论、点赞、收藏。

评论表关联了笔记ID和用户ID,展示时要用用户昵称和头像拼接评论列表。评论区要按时间倒序排,新评论靠前。删评论的权限分两种:评论作者可以删自己的评论,笔记作者可以删自己笔记下的任意评论。这个权限控制在service层判断,不能光在前端按钮上做隐藏,因为接口是可以被手工调用的,后端校验必须做。

点赞功能是面试和答辩时的高频考点。设计上要记住一个原则:点赞记录表要加唯一约束,比如(用户ID, 笔记ID)不能重复,否则用户多发几次请求就点赞了多次。我直接用INSERT IGNORE的方式插入点赞记录,如果记录已存在就忽略,再配合Redis计数器缓存点赞总数,定期同步回数据库。这样的设计既防重复点赞,性能也不差,老师问到“怎么处理重复请求”你就能答上来。

收藏功能和点赞很像,但语义不同,它更像“存书签”。一个用户能收藏很多篇笔记,一个笔记能被很多人收藏,所以收藏表同样用(用户ID, 笔记ID)做唯一约束。不同点是收藏需要展示“我的收藏”这个列表,所以查询时要用用户ID去关联笔记表,还要记得过滤掉已经删除或转私密的笔记,不然收藏夹里会出现404。

2.4 首页与检索:让好内容被看见

共享内容光堆在数据库里没用,系统需要一个内容出口。首页我做了三个板块:最新笔记、热门笔记、推荐标签云。最新笔记按创建时间倒序,热门笔记按点赞数+评论数+阅读量加权排序。这个排序算法不用搞复杂了,一个带权重的分数公式就够了:得分 = 点赞数 * 3 + 评论数 * 5 + 浏览量 * 0.5,按得分倒序排列,你看,这就是一个简单的热度榜,答辩时还能顺带说说权重的设计依据。

搜索功能支持三种维度:按标题搜、按标签搜、按作者昵称搜。前端搜索框输入关键词后,后端通过接口参数判断搜索类型。因为读取频繁,热门搜索结果我加了Redis缓存,key设置成search:hot:{关键词},过期时间10分钟,防止热点内容频繁查数据库。

3. 数据库设计与核心表结构

3.1 核心表的设计思路

数据库设计是答辩必问的环节。我的建议是:不要建太多表,每张表都要能说清楚“它存在的理由”。这个项目一共设计了7张表,每张我都给你拆开讲。

用户表、笔记表、评论表、点赞表、收藏表、标签表、笔记-标签关联表。前五张是业务主表,后两张是标签体系。所有表统一用自增bigint主键,创建时间created_time、更新时间update_time用datetime类型,并加了逻辑删除标记deleted,默认0表示未删除。逻辑删除的好处是数据不真删,误操作还能恢复,在答辩时也是可以提的设计细节。

3.2 用户表与笔记表字段说明

用户表字段如下:

字段名类型说明
idbigint主键
usernamevarchar(50)用户名,唯一
passwordvarchar(100)BCrypt加密后的密码
emailvarchar(100)邮箱
nicknamevarchar(50)昵称
avatarvarchar(255)头像地址
schoolvarchar(100)学校
majorvarchar(100)专业
introvarchar(255)个人简介
statustinyint状态:0正常,1禁用
created_timedatetime创建时间
update_timedatetime更新时间
deletedtinyint逻辑删除:0否,1是

用户名和邮箱都要建唯一索引,否则注册接口会并发写入重复数据。密码字段长度给到100,因为BCrypt哈希后的字符串有60个字符左右,给太短会出现入库失败。这个小坑我见过很多同学踩。

笔记表是系统里字段最多的一张表,包含标题、摘要、正文Markdown、封面图、分类、状态、浏览量、点赞数、评论数等。标题和摘要单独建字段,是为了列表页查询时不需要加载完整正文,性能会好很多。正文用一个mediumtext或者longtext存Markdown原文,展示时前端渲染。

笔记表的status字段我前面说了有三态,查询公开笔记时SQL里永远要带where status = 2 and deleted = 0。千万别漏了deleted条件,不然删过的笔记还会在列表里冒出来。

3.3 互动与标签相关表设计

评论表设计得比较简单:id、note_id、user_id、content、reply_user_id(回复某人的用户ID)、parent_id(父评论ID,做楼中楼)、created_time、deleted。点赞表和收藏表结构很相似,都是id、note_id、user_id、created_time,再加一个note_id和user_id的联合唯一索引。两张表为什么分开?因为业务语义不同,点赞是瞬时状态,收藏是持久列表,混在一张表里后期扩展会很难受。

标签设计上,标签表只有id、name、note_count三个字段,name加唯一索引。笔记和标签是多对多关系,通过关联表note_label关联,关联表就三个字段:id、note_id、label_id。创建笔记时,前端传来的标签名可能是不存在的,后台处理时先查一遍,不存在就自动创建,然后再建立关联。这个“有则查、无则建”的逻辑很简单,但很实用,在写代码时你会碰到。

4. 核心功能实现细节

4.1 JWT登录鉴权的完整流程

登录鉴权是每个全栈项目都绕不开的环节。我用的是Spring Boot拦截器 + JWT的方案,下面把流程理顺一下。

用户输入用户名密码后,controller层接收请求,调用service层校验用户名是否存在、密码是否正确。注意校验顺序:先查用户,如果不存在直接返回“用户不存在”;存在再调BCrypt的matches方法比对明文密码和数据库里的哈希值,匹配失败返回“密码错误”。验通过后,用jwt工具类生成一个token字符串。生成时需要传入用户ID和用户名作为claim,然后设置过期时间,最后用密钥签名。

生成好的token返回给前端,前端存到localStorage里。之后每次请求,前端通过axios拦截器在请求头里加Authorization: Bearer token。后端定义一个HandlerInterceptor拦截器,在preHandle里取出请求头,解析token。解析成功就从claim里拿到用户ID,放进ThreadLocal里供后续业务逻辑使用;解析失败直接返回401,提示登录已过期。

这里有一个容易踩坑的点:你的拦截器要放行登录、注册、获取公开笔记列表这些匿名接口,不然用户还没登录就什么都看不到了。放行路径我用一个数组配置:/api/auth/**、/api/note/public/**这些。业务接口统一要走鉴权拦截器。实现了之后,你可以在答辩时说清楚“哪些接口匿名可访问,哪些需要登录”,这比笼统说“我用了JWT”要细得多。

4.2 笔记权限控制与共享链接的实现

笔记权限是安全相关的重要部分。用户只能操作自己的笔记,不能让改价请求把别人的笔记改了,这是后端安全意识的基本体现。我在实现时先通过用户ID查出笔记,比对笔记的user_id和当前登录用户ID,不一致就抛出“无权操作”。很多人只用前端按钮的隐藏去处理,这完全不够,接口可以直接被调,后端判断才是最后一道防线。

共享链接这块,我提供一个有意思的功能:用户把笔记设为公开后,可以生成一条专属分享链接。这个链接不是直接把笔记ID暴露出去,而是把ID映射成一个UUID短码,存到分享链接表里。别人访问这个链接时,后台拿短码反查笔记ID,再验证笔记状态是公开的才能展示。这么做的意义是:分享链接本身变成了一种可管理的资源,用户可以一键取消分享,不必把隐私笔记暴露在一个可穷举的数字ID上。

4.3 图片上传与访问映射

系统里有两类图片:用户头像和笔记封面。原生的图片上传有两个隐患,一是文件类型可以被伪造,二是路径遍历攻击。所以校验上我做了三件事:第一,限制扩展名,白名单里只有jpg、jpeg、png、gif;第二,限制文件大小,Spring Boot里我配置了spring.servlet.multipart.max-file-size为2MB;第三,上传后重新生成随机文件名,不沿用用户上传的原始文件名,防止特殊字符导致路径问题。

存储路径我放在项目外的独立目录,比如/usr/local/note/upload,而不是项目内部,这样可以避免重新部署时被覆盖。上传成功后把访问路径存入数据库,前端用完整URL访问。为了避免跨域问题,我在配置类里注册了一个资源映射,把/upload/**映射到本地磁盘目录,这样前后端分离环境下图片也能正常加载。

4.4 缓存策略与防缓存穿透

我用Redis做了两个最典型的场景:邮箱验证码和热门笔记。验证码的key是email:code:{邮箱},过期时间5分钟,用户注册时提交验证码,后端比对;比对成功即让key失效。热门笔记列表在缓存里存JSON字符串,key是hot:note:list,过期时间30分钟,查不到就查数据库再回填,这就是最常见的Cache-Aside模式。

这块可以主动和老师讲一个点:缓存穿透。如果有人一直请求一个不存在的笔记ID,每次Redis查不到、数据库也查不到,就会把压力打到数据库上。我的处理方式简单而有效:即使数据库查不到,也把一个空对象或者null写入缓存,给短一点的过期时间,比如1分钟。这样能挡住大量恶意请求。虽然不是工业级处理,但在毕设里体现出“我知道这个问题并且有方案”,就已经比很多人强了。

5. 环境搭建与项目运行步骤

5.1 准备工作清单

拿到源码后第一步不是双击运行,而是把环境准备好。我踩过的坑挺多,给你列一个基础版本清单,照着准备就行。

  • JDK 1.8以上(建议直接装JDK 8,兼容性最好,或者JDK 11也行)
  • Maven 3.6以上
  • MySQL 5.7或8.0
  • Redis 5.0以上
  • IDEA 2020之后版本
  • 前端工程用Vue CLI或Vite,要求Node.js 14以上

其中MySQL需要先执行我提供的sql文件,它会自动建库建表并插入测试数据。Redis不需要预置数据,启动后由程序自动写入。如果你电脑上没装Redis,Windows用户可以直接下载Windows版Redis压缩包,解压后双击redis-server.exe启动就行。

5.2 后端配置与启动要点

把项目导入IDEA后,需要修改配置文件里的连接信息。我的配置在application.yml里,核心就是数据源和Redis地址:

server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/note_share?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: yourpassword redis: host: localhost port: 6379 mybatis-plus: global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0

这里有三处容易出错的地方:数据库名要跟你实际创建的库名一致;serverTimezone必须设成Asia/Shanghai,否则时间会差8个小时;password要换成本机真实密码。MyBatis Plus开启逻辑删除配置后,删除操作就自动变成UPDATE了。

后端启动前,先确认Redis服务开着,否则启动时会报连接失败。启动类就是一个带@SpringBootApplication注解的类,右键运行就行。等控制台出现Spring Boot的启动logo和“Started Application in xxxx seconds”,后端就起来了。然后处理前端,如果你的前端也是源码里带的,用命令方式启动:前端代码下执行npm install装依赖,然后npm run serve,默认端口一般是8081。前后端分离后,接口完整地址是http://localhost:8081/api通过代理转发到http://localhost:8080,这样避开跨域问题。

5.3 前端联调与验证

后端启动后,先用Swagger或者Postman测几个关键接口,别急着打开浏览器。测一下注册、登录、创建笔记,确保接口正常。然后启动前端,用浏览器打开前端页面,注册一个用户,写一篇笔记,去首页看看同步状态。这里最常用的排查思路是:打开浏览器开发者工具F12,看Network面板,接口报404就查路径拼写,报500就去看后端日志,报401就查token有没有带。

首次联调时很可能遇到预检跨域问题。因为我最终用了代理转发,开发环境基本能躲开,但如果后端改了端口,前端页面打开却调不到接口,就看前端的vue.config.js里target是不是指向正确端口。联调通了,你的系统就算真正跑起来,后面所有演示都有底气。

6. 毕设答辩常见问题与应对思路

6.1 原理型问题:框架机制别含糊

答辩老师很喜欢问“为什么用Spring Boot”。你不能只答“它简化了配置”,要能讲出两点:一是Spring Boot自动配置的原理,启动类上的@SpringBootConfiguration、@EnableAutoConfiguration注解会把符合条件的配置类加载进IoC容器;二是它内嵌了Tomcat,所以能把项目打成一个可执行jar包。答到这两层,老师一般就会放过你。

“JWT和Session有什么区别”也是高频问题。你可以这么说:Session依赖服务器内存存储登录状态,多机部署时要解决会话共享问题;JWT是无状态的,令牌里就携带用户信息,服务端不需要保存会话,更适合前后端分离和分布式场景。然后补一句“缺点是密钥泄露会有风险,所以我会设置过期时间并在客户端安全存储”。这样一条完整逻辑链就出来了。

6.2 业务设计型问题:展示你的思考

老师可能问“点赞功能怎么防止重复点赞”。你要把唯一约束、INSERT IGNORE、Redis计数这套完整说出来。问“数据库为什么这么设计”,你要回答三范式基本满足,又结合了这个项目读多写少的场景做了适当冗余,比如笔记表里冗余了点赞数和评论数字段,避免查询时每次都去做聚合统计。这个点很多人想不到,你说了就是亮点。

如果老师问“你的项目有什么可以继续优化”,千万不要说“没有”。你可以准备两个方向:一是搜索方面,当前用的是MySQL模糊查询,数据量大了效率会下降,所以可以引入Elasticsearch做全文检索;二是内容推荐,可以根据用户浏览记录和标签偏好做简单的协同过滤推荐。这两个都点到为止,能让老师觉得你有技术视野但又不会冒进。

6.3 如何应对“是不是网上找的代码”这种灵魂拷问

说实话,每年答辩都有老师会问这种问题。应对方法不是嘴硬,而是表现出你确实理解了每一行代码。答辩之前,把项目里几个核心类完整读一遍:JWT工具类、JwtInterceptor拦截器、NoteServiceImpl实现类、GlobalExceptionHandler统一异常处理。老师随便问个方法,你都能说出来它是在干什么。哪怕你说得不完全严谨,但只要不是背书式地回答,老师心里自然有数。

还有一个实用技巧:主动展示你“改过”的地方。比如你给某个功能加过一个校验,或者调整过数据库字段,就说“这块我在开发时遇到了什么情况,所以做了这样的调整”。真人做项目就是会遇到问题、解决问题,这个细节本身就是最好的证明。

7. 常见问题排查与实操经验

7.1 启动与依赖相关问题

端口8080被占用是最常见的启动失败原因。解决办法有两个:一是杀掉占用进程,Windows下用netstat -ano | findstr 8080查出PID,然后taskkill /pid xxxx /f;二是直接改server.port为8081。Maven依赖下载慢或者拉不下来,把Maven仓库地址换成国内镜像,在settings.xml里配置阿里云镜像。依赖出现jar包冲突时,检查IDEA右侧的Maven面板,点一下刷新按钮重新导入依赖,多数报错能解决。

JDK版本太高也会出问题。有人图省事装了JDK 17,但某些依赖版本对JDK 17兼容性不好,会出现一些奇奇怪怪的报错。我给的思路是:能跑就按原来的配置,新手优先用JDK 8,最稳,也最贴合大部分公司实际环境。

7.2 数据库连接常见报错

“Access denied for user”说明数据库账号或密码错误。换成你本机安装MySQL时设置的实际账号密码。“Unknown database”说明连接字符串里的数据库名不存在,回MySQL执行source xxx.sql把库建好。“Communications link failure”一般是MySQL没启动或者端口不对,把MySQL服务打开再用命令行连一遍确认。另外,高版本MySQL的驱动类名是com.mysql.cj.jdbc.Driver,注意别用成旧的com.mysql.jdbc.Driver。

很多人遇到的时区问题,就是url里少了serverTimezone=Asia/Shanghai。现象是数据库存的时间差了8个小时,加了这个参数再重启就好了。这种问题不要慌,优先看报错日志的第一行,定位到具体是数据源还是Redis,再对症下药。

7.3 中文乱码与文件上传问题

中文乱码分两种情况。一种是接口返回的中文乱码,检查数据库表和连接串是不是utf8;另一种是前端页面乱码,检查前端文件本身的编码是不是UTF-8。统一在后端配置里加一层响应编码处理,能避免大多数乱码问题。

文件上传失败大概率是大小或者类型校验不通过。提示“超出大小限制”,就改multipart配置里的max-file-size。提示“文件类型不允许”,就检查你是否真的选了jpg/png格式,因为有些截图文件后缀名是.png,但实际编码格式不对。还有种情况是上传成功但前端图片不显示,排查后端有没有加资源映射、路径前缀是否为/upload/**,经常是路径写错导致图片404。

7.4 前后端联调与跨域问题

前后端分离项目第一次连调,最常见的是跨域报错,浏览器控制台会出现CORS字样。解决方式有两种:一是后端加全局CORS配置,允许指定来源;二是前端开发环境配代理,像我前面说的用vue.config.js的proxy把/api开头的请求转发到后端。我推荐第二种,因为生产环境前后端部署在很多情况下同源,代理方案更接近实际。

接口联调时的错误定位,有一个实用的流程:先看Network面板里的请求状态码。404是路径不存在或controller映射写错;405是请求方式不对,比如后端是POST但你用GET调;500是后端逻辑异常,去IDEA控制台看异常栈;401/403是登录鉴权失败,检查token是否过期或没有放进请求头。按这个顺序排查,90%的联调问题都能解决。做项目的时候养成看控制台习惯,比瞎猜高效得多。

最后再分享一个我个人的体会:做毕设最怕的不是技术难点,而是做一个自己都没跑起来的东西就交上去。这套读书笔记共享系统,你花两三天把逻辑吃透,再亲手跑一遍,改一改界面上的文案,加入一张自己设计的Logo,答辩的时候你的状态会完全不一样。源码和SQL脚本我都整理好了,注释写得很全,你直接拿去跑一遍,再对照这篇文章里的设计思路去读代码,比单纯在网上找的“能用就行”的黑盒模板要强太多。如果后面想扩展成学习社区、考研资料共享甚至团队笔记协作,也完全是在这个底子上再往深走一步的事。

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

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

立即咨询