ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SpringBoot3+Vue3校园交友系统毕业设计全解析

SpringBoot3+Vue3校园交友系统毕业设计全解析 每年到了三月和十月总有一批学弟学妹抱着电脑来找我开头第一句基本都是“哥毕业设计选什么题好最好能跑起来、有源码、能答辩那种。”问得多了我发现校园交友系统这类题目几乎年年有人选但真正能做完整、能讲明白原理的人少之又少。大多数情况是从网上扒一个旧项目SpringBoot还是2.x前端还在用Vue2和Element UI代码能跑但答辩一追问就露馅。所以这次我干脆把一套基于SpringBoot3 Vue3的校园交友系统整个拆开讲一遍。这篇东西面向零基础但也不是那种“照着敲一遍就完事”的教程我会把技术选型、数据库设计、核心接口实现、前端页面整合、常见坑点一次说清楚。项目里配套的源码、数据库脚本、文档、答疑都齐活你照着做不仅能跑还能在答辩时讲出设计思路。不管你是想拿它当毕业设计还是单纯想学前后端分离开发这篇都值得看完。1. 校园交友系统到底怎么做整体设计与技术选型1.1 为什么选这个课题毕业设计选题的底层逻辑校园交友系统在毕业设计里属于“既讨巧又扎实”的类型。讨巧在于业务场景贴近日常生活用户注册、登录、个人主页、动态发布、点赞评论、关注、私信聊天这些功能人人都用过需求一说就懂不需要评委去脑补什么复杂的业务背景。扎实在于它能覆盖前后端分离开发的完整链路数据库设计、RESTful接口、身份认证、文件上传、实时通信、前端路由、状态管理几乎每个模块都能单独拿出来讲十几分钟。相比之下有人选“学生管理系统”“图书馆管理系统”这类题目功能确实简单但技术点太单薄答辩PPT写不满三页。有人选“电商系统”“外卖平台”功能是多了但核心逻辑全在订单状态机和支付回调上一个没做透就容易翻车。校园交友系统刚好卡在中间入门门槛不高但技术深度完全够用适配大多数本科毕设的难度要求。适合拿这个题目的有三类人一是Java后端方向、想展示SpringBoot3新特性的同学二是前端方向、想把Vue3组合式API和TypeScript用起来的同学三是纯应付毕业、需要一套能跑能演示能讲清流程的系统的同学。无论你是哪种这套项目的核心目标都是一致的用最合理的成本做一套功能完整、能演示、能答辩、代码能看懂的校园社交系统。1.2 技术栈为什么是SpringBoot3 Vue3 MySQL技术选型不能拍脑袋每一步都得有理由。先说后端SpringBoot3是当前Java后端的主流新版本它底层依赖Spring Framework 6和Jakarta EE 9和旧版最大的区别就是javax包全部换成了jakarta包。这一点很多人第一次迁移时都会踩坑网上抄来的老代码里都是import javax.servlet.*放到SpringBoot3项目里直接编译报错。用SpringBoot3做毕设本身就是一个可以写进文档和答辩PPT的亮点至少说明你没有拿五年前的老技术糊弄事。再来看Vue3。Vue3相比Vue2最大的变化是组合式APIComposition APIsetup语法糖让逻辑复用变得非常舒服。以前Vue2时代写一个页面要把data、methods、computed分开写业务一复杂文件又长又乱Vue3里面可以按功能把响应式数据和操作函数放在一起配合onMounted之类生命周期钩子使用代码结构清晰得多。而且Vite作为Vue3的默认构建工具启动速度比Webpack快了一个量级开发体验好到回不去。数据库我用的是MySQL 8.0。选择它的原因很简单SpringBoot3生态里对MySQL的支持最成熟JDBC驱动、MyBatis-Plus、Druid连接池的整合资料也最全。你要是用达梦、PostgreSQL当然也行但没必要在毕设阶段给自己增加工作量。MySQL 8.0默认字符集utf8mb4存emoji不会乱码像个人简介、聊天消息这种字段简直是刚需。1.3 功能模块怎么划分先想清楚再做很多新手拿到项目就急着写代码写到一半发现功能之间互相牵扯改来改去。正确做法是先画功能脑图把系统的模块边界定清楚。这套校园交友系统我按业务域拆成六大模块用户模块注册、登录、退出、个人资料编辑、头像上传、密码修改。匹配模块按标签/兴趣/院系维度做用户列表展示支持搜索和筛选。动态模块发布图文动态、动态列表流、动态详情、点赞、评论。关注模块关注/取关用户、查看粉丝和关注列表。消息模块私信聊天基于WebSocket实现实时收发。管理模块后台统计用户数、动态数基础的用户禁用操作。模块拆分之后前后端的接口划分也就自然出来了。每个模块对应一组Controller、Service、Mapper开发时可以并行推进出问题也好定位。这套划分也是后期写毕业论文时“系统设计”章节的现成骨架评委问你系统有哪些功能、模块间怎么解耦你直接按这张图就能讲清楚。2. 数据库设计先别急着写代码表结构就是系统的地基2.1 核心表设计用户、动态、聊天消息数据库设计是毕业设计答辩最容易问的点。你要能说出来“为什么这样建表”“为什么用这个字段类型”“表之间的关联关系是什么”而不是一上来就贴建表SQL。我这边核心表一共7张围绕“用户”和“动态”两条主线展开。第一张是user表保存账号认证信息。字段包括id、username、password、nickname、avatar、role、status、create_time。密码字段我用varchar(100)存的是BCrypt加密后的哈希值不是明文。这里有个细节很多人喜欢把用户所有信息塞在一张表里我建议把资料扩展字段拆到user_profile表比如gender、birthday、college、major、bio、tags。原因很简单列表页展示时只查user表不会带出大字段性能更好扩展字段单独维护也不会污染核心认证表。第二块是动态内容相关的表。post表存动态主体id、user_id、content、images、like_count、comment_count、create_time。images字段我用的varchar(500)多张图片用逗号拼接存储这是一个权衡过的方案如果你另建一张post_image表查询时要多一次join对于毕设项目来说性价比不高当然如果你想让数据库结构看起来更“正规”拆表也不是不行。评论表comment就是id、post_id、user_id、content、root_id、reply_user_id、create_time其中root_id用来支持一级评论嵌套避免无限极评论把数据结构搞复杂。第三块是关系与消息。follow表记录关注关系两个字段user_id和follow_user_id加一个唯一索引防止重复关注。chat_message表是聊天记录字段有id、from_user_id、to_user_id、content、is_read、create_time。聊天记录必须落库不然WebSocket断线重连后历史消息就丢了。like表记录点赞user_id、post_id两个字段联合唯一防止用户重复点赞。2.2 三个容易忽略的设计细节第一个细节是索引。很多零基础同学的建表语句里一个索引都没有数据量小的时候没感觉答辩时评委问“用户量大了怎么优化”就答不上来。post表的user_id要加普通索引因为要查“某个用户的动态列表”chat_message表的from_user_id和to_user_id要建联合索引因为聊天气泡要查两个方向的会话follow表的两个字段建唯一索引。索引不是越多越好覆盖查询条件的基本就够。第二个细节是逻辑删除。用户如果注销账号直接用DELETE物理删除会把关联数据搞乱。我这边在user表加了deleted字段默认0注销时置为1。MyBatis-Plus自带TableLogic注解配置之后所有查询自动加WHERE deleted 0不需要手动写条件非常省心。第三个细节是时间字段。所有表的创建时间统一用datetime后端用LocalDateTime接收前端拿到后格式化。千万别用timestamp存默认CURRENT_TIMESTAMP虽然也能用但遇到时区问题排查起来非常痛苦毕业设计没必要给自己埋这个雷。2.3 初始化数据让系统一启动就有内容一个空荡荡的系统演示起来毫无说服力。我建议在data.sql里预置20个左右的模拟用户每位用户有完整的昵称、头像、院系、标签再配上三四十条动态数据。模拟用户之间有关注关系、有聊天记录、有互评互动这样你打开系统页面时信息流是满的聊天窗口是有内容的老师演示体验会好很多。准备这些数据的时候我有个小技巧标签设计一定与“交友匹配”强关联比如“篮球”、“摄影”、“考研”、“游戏”、“音乐”。用户搜索筛选全靠这些标签命中如果标签太抽象比如“热爱生活”反而不好匹配。数据准备好之后还要记得清一下自增主键的起始值避免插入时主键冲突。3. 后端核心模块手把手拆解3.1 项目骨架搭建与依赖版本后端项目我建议直接用Spring Initializr生成官网地址填好项目信息依赖勾选Spring Web、Spring Security后面会去掉默认配置、MySQL Driver、Lombok、Validation。SpringBoot3的版本我用的3.2.x对应JDK要求是17及以上。pom.xml里核心依赖要列清楚spring-boot-starter-web是web基础mybatis-plus-spring-boot3-starter是MyBatis-Plus针对SpringBoot3的专用starter注意新版的mybatis-plus已经改了Maven坐标加了spring-boot3后缀mysql-connector-j是MySQL驱动SpringBoot3中旧的mysql-connector-java坐标已经不能用了jjwt-api、jjwt-impl、jjwt-jackson三件套做JWT令牌。dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-spring-boot3-starter/artifactId version3.5.5/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-api/artifactId version0.11.5/version /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-impl/artifactId version0.11.5/version /dependency dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt-jackson/artifactId version0.11.5/version /dependency再强调一次javax到jakarta这个变化是坑王之王。网上好多老教程代码里写import javax.annotation.Resource;放进SpringBoot3项目直接报错。解决办法只有一个把javax改成jakarta对应的Maven坐标也要换成jakarta.*系列。这是SpringBoot3迁移最核心的一步也是答辩时能展示的技术细节。3.2 JWT登录认证与安全拦截的实现校园交友系统大部分接口都需要登录才能访问这里我用JWTJSON Web Token做无状态认证。登录成功后后端生成一个包含用户ID和过期时间的token返回给前端前端把token存在localStorage里每次请求在请求头带上Authorization: Bearer token后端用拦截器统一校验。JWT工具类核心是生成和解析token。生成时设置subject为userId设置过期时间我用的7天用Keys.hmacShaKeyFor(secret.getBytes())生成签名密钥。这里有个生成密钥的注意事项密钥长度至少要256位32个字节不然jjwt会抛WeakKeyException。很多新手直接写abc123当密钥运行报错一脸懵。正确做法是写一段32位以上的字符串。private static final String SECRET campus-social-system-secret-key-2024-please-change; private static final long EXPIRE_TIME 7 * 24 * 60 * 60 * 1000; public static String generateToken(Long userId) { return Jwts.builder() .setSubject(String.valueOf(userId)) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() EXPIRE_TIME)) .signWith(Keys.hmacShaKeyFor(SECRET.getBytes(StandardCharsets.UTF_8)), SignatureAlgorithm.HS256) .compact(); } public static Long parseToken(String token) { Claims claims Jwts.parserBuilder() .setSigningKey(Keys.hmacShaKeyFor(SECRET.getBytes(StandardCharsets.UTF_8))) .build() .parseClaimsJws(token) .getBody(); return Long.valueOf(claims.getSubject()); }拦截器这边实现HandlerInterceptor接口在preHandle里从请求头取token解析失败直接返回401成功就把userId存到ThreadLocal里方便Controller直接获取当前登录用户。千万记得要把登录、注册这两个接口放进白名单不然第一次访问就直接被拦在门外。这一步是前后端分离开发里非常容易出问题的地方很多同学前端页面都写好了一调用接口全部401就是因为忘记配置放行路径了。3.3 匹配推荐与私信聊天怎么实现匹配模块听起来高大上本质就是一个带条件的列表查询。我在user_profile表存了tags字段格式是逗号分隔的字符串。匹配的逻辑我分了两级第一级是用户主动筛选按院系、性别、标签模糊查询第二级是标签匹配度排序把当前用户的标签拆开和目标用户的标签做交集交集的个数越多排名越靠前。这个逻辑用SQL写比较复杂我直接在Service层用Java实现数据量小的时候性能完全没问题关键是代码好懂、答辩好讲。私信聊天是本系统最需要展示功能我用WebSocket做实时通信。SpringBoot3里用ServerEndpoint写WebSocket端点关键配置是注册ServerEndpointExporter不然部署到外部容器会冲突内置Tomcat环境则没问题。每个客户端连接时在queryString里携带token后端解析出userId建立一个userId - WebSocketSession的映射存到ConcurrentHashMap里。Component ServerEndpoint(/ws/chat) public class ChatWebSocketServer { private static final MapLong, Session SESSION_MAP new ConcurrentHashMap(); OnOpen public void onOpen(Session session, QueryParam(token) String token) { Long userId JwtUtil.parseToken(token); SESSION_MAP.put(userId, session); } OnMessage public void onMessage(String message, Session session) { // 解析消息为 ChatMessage 对象 // 保存到数据库 // 根据 toUserId 找到目标 session推送消息 } OnClose public void onClose(Session session, QueryParam(token) String token) { Long userId JwtUtil.parseToken(token); SESSION_MAP.remove(userId); } }这里有一个细节特别提醒确保消息先落库再通过WebSocket推送。哪怕推送失败用户下次刷新页面也能从数据库拉取历史消息不会丢消息。我在本地测试时就遇到过Session已关闭但还在往里面写数据导致抛异常的情况后来在推送前加了个session.isOpen()判断就好了。这个设计能在答辩时作为“消息可靠性”的亮点讲出来。3.4 统一返回、统一异常与接口文档前后端分离项目里接口返回格式必须统一。我定义了一个ResultT类所有接口返回{ code: 200, message: success, data: ... }。前端axios拦截器统一判断code不是200就弹错误提示不需要每个页面单独处理错误状态。全局异常处理用RestControllerAdvice捕获业务异常、参数校验异常、兜底的Exception返回对应的错误码和提示信息。这个类是必须写的不然一旦代码里有个小bug前端拿到的是满屏的堆栈信息体验非常糟糕。加上全局异常处理器之后至少页面能弹出“系统繁忙”的友好提示不至于白屏。接口文档我用的是Knife4jSpringBoot3对应依赖是knife4j-openapi3-jakarta-spring-boot-starter底层走的是OpenAPI3规范SpringDoc。别用老款的knife4j-spring-boot-starter那个是Swagger2SpringBoot3下不兼容。配好后访问/doc.html就能看所有接口定义支持在线调试这个对答辩演示来说也是加分项。4. 前端Vue3项目从0到14.1 用create-vue把项目骨架搭起来前端脚手架我用官方的create-vue命令是npm create vuelatest。创建过程中它会问你需不需要TypeScript、Vue Router、Pinia、Vite等我建议零基础同学全部选No先跑通基础路线再逐步加东西有点基础的同学可以选TypeScript项目结构会规范很多。项目的核心目录长这样src/api放axios请求封装和具体接口方法src/assets静态资源src/components通用组件src/router路由配置文件src/storesPinia状态管理src/views页面组件src/utils工具类token存取、时间格式化等创建完项目后先跑npm install装依赖再npm run dev看页面能不能起来。这里有个Vue3官方的温馨提示Node.js版本必须大于18太老的环境跑不起来Vite。我见过太多同学卡在这一步查了半天才发现是Node版本的问题。4.2 路由守卫、状态管理与axios拦截器路由守卫是登录态控制的关键。用router.beforeEach判断目标路由是否在免登录白名单里不在的话检查token是否存在。token过期的话就跳回登录页。这段逻辑写在src/router/index.js里router.beforeEach((to, from, next) { const token localStorage.getItem(token); if (to.path ! /login !token) { next(/login); } else { next(); } });Pinia在Vue3里取代了Vuex写法更简洁。我建了一个useUserStore存用户信息、登录态以及登录、退出两个action。登录成功后把用户信息和token都存起来页面刷新后从localStorage恢复用户信息。这样做的好处是用户刷新页面后个人信息不会丢还能根据角色控制按钮显隐。axios封装是前端开发的常规操作。我建了src/utils/request.js实例化axios时设置baseURL加请求拦截器自动带token响应拦截器统一处理错误码。响应拦截器里有一个重要逻辑如果后端返回401清除token并跳转登录页不然用户登录过期后还在当前页面浏览器又不报错体验很迷惑。文件上传也要额外处理Content-Type要由浏览器自动设置成multipart/form-data不能手动指定否则后端接收不到文件。4.3 页面与组件的实现思路页面实现我建议遵守一个原则核心页面自己做通用页面用组件库。组件库我用的Element Plus它是目前Vue3生态里最成熟的UI库安装方式npm install element-plus按需导入或者全量引入都行。零基础同学我建议全量引入省心不纠结配置问题。登录注册页是最简单的一个表单加一个按钮表单校验用el-form的rules属性。动态列表页展示所有用户的帖子每张帖子带作者头像、昵称、内容、图片、点赞数、评论数。这里有个核心思路不要试图把评论全部塞进动态列表点开详情页再加载评论列表页数据量小很多接口响应也快。个人主页展示用户信息、标签、他发布的动态还可以切换查看他的关注和粉丝。聊天页面相对复杂一些。我这边设计成左侧会话列表、右侧聊天窗口。会话列表查询当前用户参与过的所有聊天记录按最新消息时间倒序聊天窗口展示两个人的消息气泡输入框发送后通过WebSocket推送。前端WebSocket连接时记得也要带token参数new WebSocket(\ws://localhost:8080/ws/chat?token${token})。接收消息后用push到messages数组页面自动滚动到底部这个小细节能让演示效果真实很多。5. 联调、部署与常见问题排查5.1 前后端联调代理配置与跨域前端默认跑在5173端口后端跑在8080端口直接请求会产生跨域问题。解决办法最优雅的是在Vite里配置代理前端请求地址直接写/api代理转发到后端// vite.config.js server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true, rewrite: (path) path.replace(/^\/api/, ) } } }注意rewrite会把/api前缀去掉后端Controller里写的映射路径就不带/api前缀。这样只需要后端加一个全局CORS配置允许所有来源开发用线上部署时也不会因为跨域问题被卡脖子。后端CORS配置可以用WebMvcConfigurer加addCorsMappings允许的路径设为/**允许的请求头里要加Authorization不然token带不过去。5.2 常见问题速查表现象原因解决办法后端启动报Failed to configure a DataSource数据库没连上或配置缺失检查application.yml的url、username、password确认MySQL已启动报java.lang.ClassNotFoundException: javax.servlet.*SpringBoot3兼容性问题把代码里所有javax引入改为jakartaJWT生成报WeakKeyException密钥长度不足密钥字符串长度大于32个字节前端请求接口报Network Error代理没配或后端没启动检查Vite代理配置确认8080端口可访问404但接口路径看起来没问题Controller注解没写RestController排查是否返回页面而不是JSON加上ResponseBody连不上WebSocket报403token校验失败检查连接URL上token是否正确、是否过期中文乱码字符集配置缺失application.yml中characterEncodingutf-8Linux环境注意server.tomcat.uri-encodingUTF-85.3 零基础同学的避坑心得第一个建议是不要在环境还没准备好时就狂写代码。我见过太多人花一晚上装JDK、装Node、配MySQL然后烦躁得想放弃。建议按顺序来先装JDK17再装MySQL8再装Node18每个都验证安装成功后再开始建项目。每一步验证过再走下一步出错时你能确定问题出在哪一环。第二个建议是学会读日志。前端看浏览器F12的Console和Network后端看IDEA控制台输出的Exception信息。遇到报错不要急着问人先复制报错信息去搜索引擎看一眼90%的问题都能找到答案。答疑群里最容易遇到的情况是同学贴一张报错截图但不贴环境信息、不贴完整配置这种问题谁也帮不了。提问时把报错、运行环境、已尝试过的办法交代清楚效率会高很多。第三个建议是做完一个模块就马上测试。不要等所有功能写完了再一次性启动那样一旦报错都不知道是哪里改崩的。我自己的习惯是每写完一个Controller就启动一次后端用Swagger调用一下每写完一个页面就刷新浏览器点一点。这样做项目90%的时间代码都是能跑的状态心态不会崩进度也不会拖。第四个建议关于答辩代码能跑只是一个底线能把设计思路讲清楚才是高分关键。很多同学答辩时只会说“这个功能实现了”却说不清为什么用JWT不用Session、为什么用WebSocket不用轮询、为什么加索引、为什么用逻辑删除。这套项目里的每一个技术决策在文档里我都写了原因建议你至少把“JWT认证流程”“WebSocket消息收发流程”“数据库表关系”这三张图记熟答辩时能画出来讲效果完全不一样。我到现在还留着当时做第一个前后端分离项目的数据库设计稿上面全是红笔改过的痕迹。做毕业设计的过程就是这样一开始信心满满中途被各种环境问题磨得没了脾气但等系统真的跑起来、页面流程走到通那种成就感还是很真实的。如果你也正在被SpringBoot3和Vue3的版本问题折磨记住这句话版本问题不是你的问题是新老技术交替时必经的路口跨过去就好了。后面遇到具体问题随时拿着报错信息来问这套项目的源码、数据库脚本和文档都整理好了按文档顺序一步步来大部分坑都可以绕过去。
返回列表