资讯详情

SpringBoot+Vue3读书笔记共享平台全栈项目实战与部署解析

📅 2026/10/22 4:29:30 | 华诺云谱 👁 阅读
SpringBoot+Vue3读书笔记共享平台全栈项目实战与部署解析
做 Java Web 全栈项目的朋友应该都有体会很多项目做完就扔进硬盘吃灰真正能完整跑一遍、写成文档、拿出来分享的并不多。这次要拆解的读书笔记共享平台是一个典型的前后端分离项目后端 SpringBoot2 MyBatis-Plus MySQL8.0前端 Vue3整套东西从数据库设计到接口开发再到页面联调是一条完整的链路。我会把项目里的技术选型逻辑、核心模块实现、部署细节以及实测中踩过的坑全部展开来讲希望对打算做类似学生项目、毕设或者想练手全栈开发的朋友有一些参考价值。1. 项目整体设计与需求拆解1.1 这个平台到底解决了什么问题先想清楚一个事读书笔记共享平台本质上是“内容生产 内容消费”的双边场景。学生群体阅读之后会产生笔记但笔记通常散落在本地文档、备忘录里缺少一个集中展示、互相借鉴的渠道。平台要做的就是把笔记从私人领域搬到一个可共享的空间里让笔记拥有者能公开发布、设定浏览权限让其他用户能检索、阅读、评价甚至收藏。从功能面上拆解平台的核心模块分为这么几块用户认证注册、登录、个人信息维护密码加密存储登录后通过 Token 识别身份。笔记管理笔记的创建、编辑、删除、草稿保存、公开/私有切换。笔记浏览首页笔记列表、分类过滤、关键词搜索、分页加载。互动功能收藏笔记、发表评论、查看阅读量。个人中心我发布的笔记、我收藏的笔记、账号信息。这里有一个容易被忽略的点笔记的“公开/私有”权限设计。很多学生项目的笔记模块只做了简单的 CRUD忽略了权限判断导致任意登录用户都能访问别人的私有笔记。这个平台在接口层做了访问校验私有笔记只有作者本人能查看避免出现越权问题。1.2 技术栈选型背后的实际考量先聊聊后端的 SpringBoot 版本。这里用的是 SpringBoot2 而不是 3原因很现实很多高校、企业的存量项目依然停留在 SpringBoot2.x生态资料丰富遇到问题一搜就能找到解决方案。SpringBoot3 对 JDK 版本要求更高如果本地环境还是 JDK8那 SpringBoot2 就是最稳妥的选择。当然如果是新项目且环境支持 JDK17选 SpringBoot3 会更面向未来但这个项目在技术上是偏稳定优先的。MyBatis-Plus 实际上是 MyBatis 的增强工具它解决的最大痛点是“样板代码太多”。传统 MyBatis 里每个实体类都要写一大段 XML 映射文件增删改查的 SQL 全部手写费时费力。MyBatis-Plus 提供了通用 Mapper、条件构造器、分页插件、代码生成器单表的 CRUD 几乎不用写 SQL开发效率提升非常明显。选择 Vue3 的原因也很直接。Vue3 的组合式 API 让逻辑复用变得更优雅同一个功能相关的数据和方法可以放在一起不像 Vue2 的选项式 API 那样把 data、methods、computed 拆得七零八落。而且 Vue3 搭配 Vite 开发服务器冷启动速度远快于 Webpack开发体验好一大截。MySQL8.0 相比 5.7 的改进是默认字符集为 utf8mb4可以直接存储 emoji 表情这对笔记内容里可能出现的特殊符号非常友好。8.0 的窗口函数也让一些统计查询变得更简洁比如计算热门笔记排行、按分类统计数量这类需求。2. 后端核心实现解析2.1 项目分层与目录结构后端工程建立在标准的分层架构上目录结构如下src/main/java/ ├── controller/ # 接口层接收请求、参数校验、返回结果 ├── service/ # 业务逻辑层 │ └── impl/ # 业务实现 ├── mapper/ # MyBatis-Plus 数据访问接口 ├── entity/ # 数据库实体类 ├── dto/ # 请求/响应参数对象 ├── config/ # 配置类拦截器、跨域、分页插件 ├── common/ # 公共类统一返回结果、全局异常处理、常量 └── utils/ # 工具类JWT工具、密码加密分层架构的核心逻辑是“各司其职”。Controller 只负责接收和响应不做业务逻辑Service 做具体的事务处理Mapper 访问数据库。这样做的直接好处是出了问题定位快职责边界清晰而且后期扩展加功能时不用在 Controller 里堆代码。这里想强调统一返回结果的设计。所有接口的返回结构统一为一个Result对象包括 code、message、data 三个字段。这样前端只需一套处理逻辑就能应对所有请求不用每一个接口都单独处理成功和失败。实际开发中有的项目接口一会儿返回Map一会儿直接返回实体前端对接起来极度痛苦这个坑我建议大家在设计阶段就避开。2.2 核心接口设计与实现用户认证模块采用的是 JWTJSON Web Token方案。用户登录成功后后端生成一个包含用户 ID 和过期时间的 Token 返回给前端前端将 Token 存储在本地并在每次请求的请求头中携带。后端使用拦截器统一校验请求头中的 Token解析出当前登录用户。一个完整请求的认证链路是这样的用户提交用户名和密码到/api/user/login。后端校验用户名密码密码通过 BCrypt 加密比对。登录成功用 JWT 工具生成 Token设置过期时间比如 24 小时返回前端。前端将 Token 存入 localStorage并写入 Axios 请求拦截器。后续请求的请求头带上Authorization: Bearer token。后端拦截器解析 Token将用户信息放入请求上下文。用户注册时的密码处理要特别注意明文密码绝对不能入库必须用 BCrypt 加密。实际项目中曾见过直接明文存密码的系统一旦数据库泄露所有用户账号直接裸奔。BCrypt 是带盐的散列算法相同密码每次加密结果都不同安全性远高于简单 MD5。笔记列表接口是典型的条件分页查询用 MyBatis-Plus 的 LambdaQueryWrapper 实现LambdaQueryWrapperNote wrapper Wrappers.lambdaQuery(); wrapper.eq(Note::getIsPublic, 1); if (StringUtils.hasText(keyword)) { wrapper.and(w - w.like(Note::getTitle, keyword) .or().like(Note::getContent, keyword)); } if (categoryId ! null) { wrapper.eq(Note::getCategoryId, categoryId); } wrapper.orderByDesc(Note::getCreateTime); PageNote notePage noteService.page(new Page(pageNum, pageSize), wrapper);这段代码值得说几点一是条件构造器的动态拼接不用手动拼 SQL 字符串避免了注入风险二是分页操作只需调用page方法MyBatis-Plus 的分页插件会自动生成LIMIT语句三是对返回的笔记列表做了字段裁剪列表页只返回标题、摘要、封面、作者信息和阅读量不返回全文内容减少网络传输量。笔记详情的访问逻辑里有一个容易忽略的业务点阅读量统计。每次访问详情接口view_count字段加 1。这个操作看似简单但因涉及更新操作如果每次请求都直接update高并发下会有性能问题。更合理的做法是先查后更配合缓存或异步更新。这个项目的数据量级不大直接更新问题不大但设计上保留了优化空间。2.3 数据库表设计与关系梳理数据库设计是整个项目的地基表结构如果设计不合理后面写动态条件查询会很痛苦。这个平台的表设计如下表名核心字段说明userid, username, password, nickname, avatar, create_time用户表username 唯一索引categoryid, name笔记分类表如技术、文学、历史noteid, user_id, title, summary, content, category_id, is_public, view_count, create_time, update_time笔记主表user_id 和 category_id 建普通索引commentid, note_id, user_id, content, create_time评论表note_id 建索引favoriteid, user_id, note_id, create_time收藏表user_id 和 note_id 建立联合唯一索引几个细节值得展开逻辑删除笔记表没有直接物理删除而是加了一个deleted字段通过 MyBatis-Plus 的TableLogic注解实现逻辑删除。这样做的好处是误操作还能恢复数据不会被轻易抹掉。关联关系收藏表用联合唯一索引保证同一用户对同一篇笔记只能收藏一次不会产生重复记录。时间字段统一使用 datetime 类型搭配ON UPDATE CURRENT_TIMESTAMP自动更新修改时间省去在代码里手动赋值。内容字段笔记正文存储的是 Markdown 源文本前端通过前端库渲染。这样编辑时拿的是原始文本展示时渲染成富文本二者解耦。3. 前端实现与前后端联调3.1 Vue3 项目结构与核心配置前端工程基于 Vue3 Vite 构建目录结构如下src/ ├── api/ # 接口请求封装 │ ├── note.js │ ├── user.js │ └── comment.js ├── assets/ # 静态资源 ├── components/ # 通用组件如笔记卡片、评论列表 ├── router/ # 路由配置 ├── store/ # Pinia 状态管理 ├── views/ # 页面级组件 ├── App.vue └── main.js路由配置分为公开路由和需登录路由通过路由守卫控制。比如“个人中心”页面必须登录后才能访问未登录用户访问时直接重定向到登录页。这个逻辑放在前端路由守卫中实现和后端拦截器形成一个双重防护虽然前端校验不能替代后端校验但用户体验更好未登录用户不用发请求就能知道“该登录了”。Pinia 状态管理用于保存当前登录用户信息。登录成功后把用户 ID、用户名、头像存入 store页面刷新时再通过接口重新获取用户信息保证状态不丢失。这里有一个常见误区直接用 localStorage 持久化整个用户对象而 Token 过期后本地用户数据仍然存在导致页面显示登录状态但接口全部报 401。更稳妥的做法是持久化 Token用户信息每次从接口拉取。3.2 核心页面与交互逻辑首页是笔记列表展示卡片信息标题、摘要、分类标签、作者昵称、阅读量、发布时间。列表支持分页加载滚动到底部自动加载下一页。这个交互用到了 Vite 模块导入的方式在加载更多时按需引入组件避免首屏加载过重。笔记详情页是核心页面整体分成上下两块顶部是标题、作者、分类、时间等元信息下方是笔记正文。正文以 Markdown 源文本的形式返回前端用解析库进行渲染代码块有高亮效果。这里有一个细节渲染内容需要进行 XSS 过滤防止用户在笔记中写入恶意脚本代码。实际项目中遇到过有人在笔记里插入外链图片和跳转脚本的情况安全性必须提前考虑。评论区域相对独立加载当前笔记的评论列表支持发表评论和删除自己的评论。评论功能的技术点在于关联查询——评论表里存了 user_id但页面要展示的是用户昵称和头像需要联表查询或者二次查询用户信息。MyBatis-Plus 的单表操作优势在这里体现得很明确手动写一个多表查询 SQL 关联 user 表即可。3.3 前后端接口联调与跨域处理前后端分离项目跨域是绕不开的问题。开发环境下最常见的方案是配置 Vite 的代理。在vite.config.js中设置以下内容server: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }这样前端请求/api/note/list时Vite 开发服务器会把它转发到http://localhost:8080/api/note/list浏览器看起来是同源的不存在跨域问题。生产环境下则通过 Nginx 配置反向代理将/api路径转发到后端服务。后端也做了兜底的跨域配置通过 WebMvcConfigurer 添加全局 CORS 映射。开发时前端可以不用代理直接请求后端接口调试灵活性更高。但要特别注意一旦使用了代理前端的 baseURL 就不要设置成完整后端地址否则代理就失去意义了。接口联调时还有一件重要的事定义好请求和响应的数据格式。这个项目里所有请求参数以 JSON 格式提交响应统一为 Result 对象。实际踩过的坑是前端忘记设置请求头Content-Type: application/json导致后端接收到的参数全是 null调试了半天才发现是格式问题。4. 环境搭建与项目部署实战4.1 本地开发环境准备环境准备是很多新手卡住的地方我按操作顺序把它理清楚。后端需要的基础环境是 JDK8 和 Maven建议直接用 JDK8这是 SpringBoot2 最匹配的版本。Maven 配置好国内镜像仓库否则依赖下载速度让人崩溃。数据库需要 MySQL8.0。安装完成后用 root 账号创建一个数据库CREATE DATABASE book_share DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;然后导入项目自带的 SQL 文件里面包含了建表语句和初始数据。注意 SQL 脚本是在 MySQL8.0 下导出的导入到 5.7 版本可能因 utf8mb4 排序规则报错所以强烈建议保持数据库版本一致。导入成功后修改后端配置文件application.yml中的数据库连接信息spring: datasource: url: jdbc:mysql://localhost:3306/book_share?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver这里有一个高频报错点JDBC 连接串中忘记加serverTimezoneAsia/Shanghai运行时会报时区相关的异常控制台提示 CST 或 UTC 时区无法识别。加上这一行参数就能解决。前端环境需要 Node.js 16建议用 18 的 LTS 版本。安装完依赖后执行npm run devVite 控制台会显示本地访问地址默认是http://localhost:5173。4.2 后端打包与前端构建后端打包直接用 Maven 插件mvn clean package -DskipTests打包完成后在target目录下生成一个 jar 文件使用java -jar 文件名.jar即可启动。实测启动过程中内存默认分配足够无需额外设置 JVM 参数。如果想修改端口在启动命令中加入--server.port9090即可。前端构建生产包npm run build构建产物在dist目录中直接部署到 Nginx 或放到后端静态资源目录下。这里强烈建议生产环境用 Nginx 做一层反向代理一方面把前端的静态文件服务托管起来另一方面通过 Nginx 的/api代理解决跨域问题。Nginx 配置片段参考server { listen 80; server_name your-domain.com; root /path/to/dist; index index.html; location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { try_files $uri $uri/ /index.html; } }使用try_files指令的原因是 Vue 的前端路由是 history 模式刷新页面时 Nginx 需要把不存在的路径重写到 index.html否则会出现 404。这个是一个容易忽略但必踩的部署坑。4.3 项目配套文档的利用思路项目附带的文档包含需求说明、数据库设计说明、接口文档和部署说明。拿到文档后的正确利用顺序是先看需求说明理解项目背景和功能边界再看数据库设计表结构一目了然对整体数据的流向自然就心里有数接口文档用于前后端对接时查阅里面标注了每个接口的请求参数和响应示例部署文档是最后一步按步骤操作即可启动项目。文档的价值不只是照做它还是学代码的辅助材料。看代码时先看对应的接口文档知道这个接口要完成什么功能再回到代码里看实现方式理解会清晰很多。5. 常见问题与排查技巧实录5.1 启动与配置类故障端口被占用SpringBoot 启动报Port 8080 was already in use。解决办法是先找出占用进程或者在启动命令中修改端口。这个算小问题但实际操作中遇到的人不少。后端启动时找不到驱动提示Unable to load authentication plugin caching_sha2_password。这是因为 MySQL8.0 默认认证插件是 caching_sha2_password而项目用到的数据库驱动版本过低。解决办法是更新驱动到mysql-connector-java8.0 版本或者将数据库账号认证方式改为 mysql_native_password。推荐前者升级驱动才是根本解。前端运行报 node-gyp 错误这个通常在 Windows 环境下出现是某些依赖需要本地编译。解决办法是按装 Visual C Build Tools或切换到 Node LTS 版本后重新安装依赖。这个问题不是代码引发的属于环境问题耐心解决即可。5.2 业务与代码类问题分页查询失效表现为传入 pageNum 和 pageSize 后返回数据仍为全部记录。原因是没有配置 MyBatis-Plus 的分页拦截器。需要在配置类中注入该拦截器否则Page对象无法生效。这个问题非常典型属于使用 MyBatis-Plus 时的必备常识忘记注册插件的人不在少数。接口 401 但前端登录状态正常前端显示已登录但请求报未认证。需要检查 Token 过期时间设置以及拦截器中 Token 解析失败时的处理逻辑。实际项目中还遇到过前后端解码 Token 用的密钥不一致导致所有请求都被拦截的奇葩问题排查时记得确认密钥配置在前后端是同一个值。上传图片后无法访问项目的图片上传功能将文件保存到本地磁盘访问时映射为静态资源路径。如果保存路径中有中文或反斜杠问题图片会加载失败。解决方法是统一使用相对路径存储并保证spring.web.resources.static-locations配置正确。5.3 排查思路与调试技巧开发阶段最怕的就是问题迟迟定位不了。分享几个压箱底的排查方法日志先行。拿到一个报错先定位日志输出SpringBoot 的日志默认输出在控制台包含了完整的堆栈信息。重点看 Caused by 后面的内容那才是异常的根源。接口测试工具不能少。用接口测试工具直接调用后端接口把前端剥离出去。如果接口返回正常那问题就在前端如果接口直接报错则直接看后端日志。这套二分法能把问题的排查范围缩小一半。前端排查用浏览器开发者工具。打开 Network 面板看请求的 URL、请求头、请求体和响应状态码。404 是路径错误401 是认证失败500 是后端异常。手动审查一遍请求和响应大多数联调问题都能定位。写在后面的话做这个项目给我最深的感受是一个完整全栈项目真正的难点不在某个具体的技术点而在如何把所有环节串起来。数据库字段少一个索引、跨域配置漏了一行、分页插件忘记注册、文档和实际代码不一致——任何一个细节都会让你多花几小时排查。但反过来说每踩过一个坑对整套技术栈的理解就会深一层。如果你打算基于这个项目二次开发建议先从替换前端页面风格入手然后扩展新的功能模块比如笔记导入导出、用户关注关系、基于内容的推荐算法这些方向都有很大的发挥空间。实践出真知把项目跑起来自己动手改一改收获远比看十篇教程大。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑