ARTICLE DETAIL

资讯详情

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

SpringBoot3+Vue3交友平台系统设计实战:从架构到部署

SpringBoot3+Vue3交友平台系统设计实战:从架构到部署 1. 从项目标题说起这个交友平台到底在解决什么问题拿到“springboot3基于vue3的交友平台系统设计(编号146090174)”这个标题时第一反应不是急着上手写代码而是先琢磨清楚一件事这类项目在毕设、课设、个人作品集里出现频率极高但大多数人做出来的东西只是“能登录、能加好友、能发消息”的CRUD堆叠根本没有触及交友平台的本质。我理解的核心需求是这样的交友平台不是普通的内容社区它背后有一条完整的业务链——用户注册与身份认证、资料完善与兴趣标签、用户推荐与匹配、好友关系管理、即时聊天、动态互动以及最容易被忽略的审核与安全机制。任何一个环节做得太浅整个系统都会显得“假”。而选型定了 springboot3 和 vue3说明你的技术栈是当前主流的前后端分离方案这也意味着你需要把前端工程化、后端接口设计、数据库建模、部署上线整条链路都走通。这篇博文我会从一个实战者的角度把整个系统从设计到落地的关键环节拆开讲重点说清楚三个问题为什么这么做、怎么做、踩过哪些坑。文章末尾我会给出一份完整的核心代码片段和配置文件参考让你拿去就能改、改完就能跑。2. SpringBoot3 与 Vue3 的组合为什么是当前最优解2.1 版本选型背后的技术逻辑SpringBoot3 和 Vue3 不是凭空选出来的组合而是被生态推着走的必然结果。SpringBoot3 在 2022 年底正式发布底层基于 Spring Framework 6最重要的变化是强制 JDK17同时全面拥抱 Jakarta EE 命名空间javax 变 jakarta。这意味着你不能再拿老一套 JDK8 的思维去写代码了但也正因为如此SpringBoot3 的启动速度、内存占用、响应式编程支持都比 SpringBoot2 有明显提升。Vue3 这边组合式 API 是最大的分水岭。Vue2 时代的 Options API 写业务逻辑时一个组件里 data、methods、watch、computed 各据一方代码一多就要靠 mixin 去抽公共逻辑抽到最后依赖混乱到你自己都分不清这个方法是从哪个 mixin 进来的。Vue3 的 setup 语法糖配合 Composition API让同一段业务逻辑天然归属在一起算是真正解决了复杂组件状态管理的痛点。这套组合放到交友平台场景里优势非常具体高并发下的响应能力交友平台典型的“瞬间流量”发生在用户活跃高峰期比如晚八点到十一点。SpringBoot3 内置的虚拟线程JDK21 环境下和处理模型比 SpringBoot2 更适合应对大量 IO 密集型请求虽然个人项目未必真的能压到那个量级但架构上不输。前后端独立开发效率Vue3 Vite 的开发服务器热更新速度比 Webpack 快一个数量级改一行代码一秒钟内就能看到效果这在实际开发中非常影响心情和节奏。生态成熟度SpringBoot3 对应 Spring Security 6、MyBatis-Plus 3.5、Knife4j 4.x 都已经稳定兼容Vue3 这边有 Element Plus、Pinia替代 Vuex、Vue Router 4、Axios 全家桶文档齐全遇到问题搜得到答案。2.2 技术栈清单与版本对应我直接给你一份实践过的、能跑通的所有核心依赖版本对照照着配不会踩版本坑。组件版本建议说明JDK17SpringBoot3 强制要求建议直接用 21虚拟线程更好用SpringBoot3.2.x3.1 后的版本更稳3.2 对虚拟线程支持更完善MyBatis-Plus3.5.5升级了新分页插件避免旧的 PaginationInnerInterceptor 报错Spring Security6.2.x和 SpringBoot3 配套配置方式有变化注意不兼容旧代码JWTjjwt 0.12.x新包名改成了 io.jsonwebtoken和旧版本的 import 路径不同Vue3.4.x安装时用 create-vue 脚手架Vite 5Vite5.x模板自带无需单独选Element Plus2.7.xUI 组件库表单、表格、弹窗全用它Pinia2.1.x状态管理比 Vuex5 靠谱官方推荐这套选型的核心原则只有一个所有库都跟着官方最新稳定路线走不贪新不守旧。比如你搜到一堆“MyBatis-Plus 新版分页插件写法变了”的帖子就是因为有人用了 3.5.5 却拿着老版配置在抄这种坑一旦踩上排查时间远超重新搭一遍。3. 交友平台核心模块拆解不要做成普通“通讯录”3.1 用户画像模块交友推荐的基石很多人做这个项目用户表就三个字段用户名、密码、性别。这太应付了。交友平台的核心价值在于“匹配”而匹配需要的是用户画像维度身高、学历、职业、城市、兴趣标签、性格标签、照片墙、个人签名、活跃度、在线状态。我建议用户表保持基础字段简洁个性信息单独拆一张 profile 表用 user_id 一对一关联。这样做的好处是以后扩展“更多维度”的筛选条件时不需要动主表查询列表时如果不需要详情也可以避免大字段拖累 IO。CREATE TABLE user_profile ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint NOT NULL COMMENT 用户ID, nickname varchar(64) NOT NULL, avatar varchar(255) DEFAULT NULL COMMENT 头像URL, gender tinyint DEFAULT NULL COMMENT 1男 2女 0保密, birthday date DEFAULT NULL, height_cm int DEFAULT NULL, education tinyint DEFAULT NULL COMMENT 学历编码, city varchar(32) DEFAULT NULL, job varchar(64) DEFAULT NULL, bio varchar(500) DEFAULT NULL COMMENT 个性签名, tags varchar(255) DEFAULT NULL COMMENT 兴趣标签ID逗号分隔, PRIMARY KEY (id), KEY idx_user_id (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户画像表;这里有个容易被忽略的细节tags字段不能只存中文标签字符串否则将来做“按标签筛选用户”时 SQL 非常难写。正确做法是标签主表tag存标签定义用户标签关系表user_tag存 userId tagId 多对多关系列表页展示时再聚合。如果你嫌复杂也可以学我用“标签ID逗号分隔 后端解析后再批量查标签名”的折中方案但基础表设计一定要留扩展余地。3.2 匹配推荐模块从“简单筛选”到“有点智能”这一块是论文和答辩时最容易出彩的地方。推荐不能只靠一条 SQL 按城市性别筛出来那样显得太傻。用用户画像匹配可以算出一个“相似度分数”按分数倒序推荐。我的做法是把每个用户映射成一组特征标签比如【健身】【摄影】【程序员】【养猫】把标签集合转成向量然后算当前用户和目标用户之间的 Jaccard 相似系数。公式很简单J(A, B) |A ∩ B| / |A ∪ B|打个比方你的标签是【健身、摄影、读书】对方的标签是【健身、跑步、读书】交集是【健身、读书】 2并集是【健身、摄影、读书、跑步】 4相似度 2/4 0.5。分数越高越靠前。这只是一个雏形但论文里可以讲清楚“基于标签的协同过滤思想”并留出扩展接口以后换成 embedding 向量做深度推荐也不至于推翻整个架构。实际实现时你可以在后端用一次查询把候选用户的标签都拉出来然后在内存里跑相似度计算。数据量小的时候这种方式最快数据库不用做复杂 join也没必要引入 Redis 做缓存虽然加了 Redis 显得更高级但小项目性能瓶颈不在这。3.3 好友关系与聊天模块别把“关注”和“好友”混为一谈交友平台的好友关系一般有三种状态陌生人、已申请、已是好友。关系表很难只用一个字段表达清楚建议用方向性设计CREATE TABLE user_relation ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint NOT NULL COMMENT 主动方, target_user_id bigint NOT NULL COMMENT 被动方, status tinyint NOT NULL DEFAULT 1 COMMENT 1待验证 2已通过 3已拉黑, create_time datetime NOT NULL, update_time datetime NOT NULL, PRIMARY KEY (id), UNIQUE KEY uk_user_target (user_id, target_user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;处理好友申请的逻辑很关键你查看目标用户详情时需要知道“我是主动方还是被动方”因为不同的方向对应不同的按钮状态。如果我是主动方且 status1显示“等待对方验证”如果我是被动方且 status1显示“接受/拒绝”。这一步查询逻辑看似简单前后端联调时最容易乱建议后端在返回用户详情 DTO 时直接附带relationStatus字段让前端少做一层判断。聊天模块我走了 WebSocket 的技术路线SpringBoot3 里用spring-boot-starter-websocket比较顺。单机部署时可以在一个服务内维护 Session 映射消息发出去后按接收方 userId 找到对应 WebSocket Session直接推送。如果以后上集群再引入 Redis 消息订阅来广播架构上不冲突。Component public class ChatEndpoint extends TextWebSocketHandler { private static final MapLong, WebSocketSession SESSIONS new ConcurrentHashMap(); Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { Long userId (Long) session.getAttributes().get(userId); SESSIONS.put(userId, session); } Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { JSONObject msg JSON.parseObject(message.getPayload()); Long toUserId msg.getLong(toUserId); WebSocketSession toSession SESSIONS.get(toUserId); if (toSession ! null toSession.isOpen()) { toSession.sendMessage(new TextMessage(msg.toJSONString())); } } }这段代码是最简版本没有存离线消息也没做已读回执。如果你想在答辩时增加亮点建议加一个消息发送记录到数据库加一个is_read字段并在对方下线时写离线消息表等对方上线后再补推。这样一个简单的改动工作量不大但体现出的“需求完整性”远超普通课设。3.4 动态广场与内容审核交友平台不能变成“法外之地”动态功能让平台有“社区感”但它也是内容安全风险最集中的地方。我的意见是哪怕是为了应付答辩动态发布接口也必须做文本敏感词过滤和图片安全审核的预留位。文本过滤我用了开源的 sensitive-words 库基于 DFA 算法在服务端对发布内容做敏感词检测发现后拒绝发布或替换成*。图片审核方面个人项目接阿里云/腾讯云的审核 API 需要实名认证且要花钱可以做成一个策略接口默认实现是本地占位只有名称没有真实逻辑论文里把这个设计写清楚说明“接口可扩展接入云服务”这比你硬说自己实现了什么更可信。动态表的核心字段包括user_id、content、imagesJSON 数组字符串、location、like_count、comment_count、status0待审 1已发布 2已删除。点赞和评论拆成单独的表不要用一个大字段去统计数字因为并发下要保证数据一致性用 Redis 加缓存再定时落库是理想方案但为了简单我用的是“点赞记录表 动态表冗余计数字段事务更新锁”的方式。4. 前后端实操从脚手架搭建到接口联调的完整流程4.1 后端工程初始化与基础配置创建项目我建议直接用 Spring Initializrstart.spring.io选好 SpringBoot 3.2.x、Java 17、依赖选择 Web、Security、MySQL Driver、Validation、Lombok。生成完导入 IDE 后先把application.yml按自己的环境配好。我的核心配置参考如下server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/friend_platform?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver data: redis: host: localhost port: 6379 mybatis-plus: mapper-locations: classpath:mapper/*.xml global-config: db-config: id-type: auto logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0两个提示都是实战得来的教训SpringBoot3 的 MyBatis-Plus 分页插件写法变了。在新版中要这样注册Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }千万别再抄老博客里PaginationInterceptor的名字类在 3.5.5 里已经没了。Jackson 处理 LocalDateTimeSpringBoot3 默认会把LocalDateTime序列化成数组前端拿到的不是字符串非常难受。配置类里加一行spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: Asia/Shanghai如果你返回 JSON 里还有 Long 类型的 ID雪花ID记得对前端精度丢失做处理把所有 Long 字段加JsonFormat或者在配置里把 Long 转成 String。4.2 Spring Security 与 JWT 鉴权实现交友平台里每个需要登录的接口都要认证但不能每个请求都去数据库查密码。我的方案是 JWT 无状态认证用户登录成功后发放 token后续请求在 header 里带Authorization: Bearer token后端写一个 OncePerRequestFilter 去解析校验把 userId 放进 SecurityContext。Spring Security 6 的配置代码跟旧版有差异。最显著的变化是WebSecurityConfigurerAdapter被废弃了你必须用SecurityFilterChainEnableWebSecurity的方式。再造一个步骤列表给你照做就通写JwtUtil工具类负责生成 token 和解析 token。写JwtAuthenticationFilter继承OncePerRequestFilter从 header 取 token解析出 userId塞进 SecurityContext。在 Security 配置类中设置csrf.disable()sessionManagement为 STATELESS。路径放行规则/api/auth/**放行其他接口需要鉴权。注册PasswordEncoder为BCryptPasswordEncoder注册过滤器。登录接口的逻辑是流程里最容易出问题的环节先查用户是否存在再用passwordEncoder.matches(rawPwd, encodedPwd)比对比对成功后签发 token。注意不要直接把密码字段返回前端也别在日志里打密码。4.3 前端 Vue3 项目搭建与页面结构设计用 Vite 脚手架创建项目npm create vuelatest friend-frontend交互式选择时Router、Pinia、ESLint、Prettier 都选是测试之类的可以不要。进入项目后先装依赖npm install npm install element-plus axios前端目录结构建议按业务模块拆而不是一直堆 componentssrc/ api/ # 接口请求封装按模块分文件 router/ # 路由配置 stores/ # Pinia 状态 views/ login.vue register.vue home.vue # 用户推荐列表 profile.vue # 个人中心 profile-edit.vue chat.vue # 聊天页面 moments.vue # 动态广场 components/ layout/ user-card.vue chat-window.vue utils/ request.js # axios 封装拦截器Axios 封装时一定要加请求拦截器和响应拦截器。请求拦截器统一带上 localStorage 里的 token响应拦截器判断 status 码如果是 401 就跳登录页。这个部分是所有页面联调的基础写好后能省大量重复代码。4.4 前端核心页面实现要点登录页和注册页相当于门面UI 做得好不好看在次要逻辑没闭环才是大问题。注册时要校验用户名唯一性、密码两次输入一致、手机号/邮箱格式、年龄范围这些前端校验和后端校验都要做。记住前端校验是为了用户体验后端校验才是安全底线。推荐列表页home.vue是最核心的展示页面。页面加载时调用推荐接口后端返回用户列表相似度分数是否已是好友前端用卡片布局展示点击“喜欢”或“不喜欢”按钮后可以调用记录动作的接口也可以先本地隐藏这张卡片提高浏览流畅度。交互反馈一定要及时否则用户会觉得卡。聊天页的坑最多。WebSocket 连接要在用户进入聊天页时才建立离开时关闭消息气泡要用 v-for 渲染自己发的靠右、对方发的靠左收到 WebSocket 新消息时把消息 push 进列表同时滚动到底部。这里有一个体验细节连续 push 多条消息时底部滚动如果每次都强制滚到底部会导致用户中途想往上翻历史时被拽下来。建议只在用户当时位于底部时才自动滚底。动态广场的页面是一个两列瀑布流布局卡片展示内容和图片点赞和评论使用局部刷新不必整个页面重新请求。发布动态时用表单弹窗上传图片组件调用后端upload接口成功后把返回的 URL 拼在 images 数组里。5. 数据库设计与接口规范这些细节决定项目上限5.1 核心表结构全景我完整列出建表建议共六张核心表足够撑起一个能答辩的系统user: 账号表id、username、password、phone、status、create_timeuser_profile: 用户画像表同上文tag: 标签表id、name、typeuser_tag: 用户标签关系表id、user_id、tag_iduser_relation: 好友关系表上文已给出 SQLchat_message: 聊天消息表id、from_user_id、to_user_id、content、type、is_read、create_timemoment: 动态表id、user_id、content、images、like_count、comment_count、status、create_timemoment_like: 动态点赞表id、moment_id、user_id、create_timemoment_comment: 动态评论表id、moment_id、user_id、content、create_time这些表之间不要在数据库层建外键逻辑层约束就够了。外键在高并发时影响写入性能也会让数据迁移变得僵硬这是行业实践里普遍认同的做法。5.2 API 接口路径规范接口设计要遵循 RESTful 风格外还要明确统一返回结构最好定义成ResultT包装类Data public class ResultT { private Integer code; private String message; private T data; }code200 表示成功400 表示参数错误401 表示未认证500 表示服务异常。前端 axios 响应拦截器拿到 code 后统一提示不用每个页面手写错误处理。核心接口列表按模块分类模块接口方法说明认证/api/auth/registerPOST注册认证/api/auth/loginPOST登录用户/api/user/{id}GET获取用户详情画像用户/api/user/profilePUT修改资料推荐/api/recommend/listGET推荐用户列表分页关系/api/relation/addPOST发送好友申请关系/api/relation/acceptPOST同意申请聊天/api/chat/historyGET拉取二人聊天记录动态/api/moment/pageGET动态分页列表动态/api/moment/publishPOST发布动态动态/api/moment/likePOST点赞/取消点赞上传/api/upload/imagePOST图片上传5.3 分页与条件查询的常见坑推荐列表需要分页但交友平台最好是“滑动加载”后端接口传pageNum和pageSize前端滚动到底部时把页码加一再去请求然后追加到数组后面。MyBatis-Plus 的分页查询注意返回的是IPageT前端需要的字段是records、total、current、size不要搞混。条件筛选是另一个大坑按照年龄、城市、学历筛选时参数可能为空。SQL 语句里不能傻傻地拼where city要用 MyBatis-Plus 的 LambdaQueryWrapper 做条件判断LambdaQueryWrapperUserProfile wrapper Wrappers.lambdaQuery(); wrapper.eq(StringUtils.hasText(city), UserProfile::getCity, city); wrapper.ge(minAge ! null, UserProfile::getBirthday, maxBirthdayByAge); wrapper.le(maxAge ! null, UserProfile::getBirthday, minBirthdayByAge);注意年龄和生日的模糊转换你想筛 20-30 岁生日范围是倒过来的。如果前端传的是年龄区间后端得想办法转换。我建议接口直接收birthdayStart、birthdayEnd前端用日期选择器这样最不容易出错。6. 部署上线从开发到公网可访问的完整链路6.1 后端打包与运行SpringBoot3 项目打包成可执行 jar 很简单mvn clean package -DskipTests生成target/friend-platform.jar放到服务器上运行。我用的是阿里云轻量服务器2核4G 足够跑这套系统。先装好 JDK17 和 MySQL8yum install -y java-17-openjdk启动命令nohup java -jar friend-platform.jar --spring.profiles.activeprod app.log 21 注意生产环境数据库密码不要写在 yml 里用环境变量注入spring: datasource: password: ${DB_PASSWORD}启动后访问 actuator 或写个简单的/api/ping接口测试连通性。6.2 前端打包与 Nginx 配置Vue3 项目执行npm run build后静态文件在dist目录。用 Nginx 托管转发/api和后端 WebSocketserver { listen 80; server_name your-domain.com; root /usr/share/nginx/html/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; } location /ws/ { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; } }WebSocket 的代理配置很容易踩坑。如果少了proxy_set_header Upgrade $http_upgrade;那几行浏览器会一直连接失败控制台报 101 Switching Protocols 失败之类的错。别问我怎么知道的我在这上面浪费过一下午。还有一个前端路由问题Vue Router 默认是 history 模式刷新某个二级页面时 Nginx 会返回 404。解决办法是在 Nginx 加 try_fileslocation / { try_files $uri $uri/ /index.html; }这句话的意思是找不到对应文件时回退到 index.html把路由交给前端处理。6.3 HTTPS 证书配置加分项就算个人项目我也建议把 HTTPS 上了。免费证书一大把申请简便。Nginx 里配置server { listen 443 ssl; ssl_certificate /etc/nginx/cert/your_domain.pem; ssl_certificate_key /etc/nginx/cert/your_domain.key; # 其他配置同 80 server }配置完别忘了把 80 端口的请求重定向到 443。7. 我从这个项目里挖出来的坑问题排查与经验实录7.1 SpringBoot3 Spring Security 6 的 CORS 配置前后端分离部署后前端是 80 端口、后端是 8080 端口跨域问题必然出现。Spring Security 6 的 CORS 配置要在 SecurityFilterChain 里加http.cors(Customizer.withDefaults());光这样还不够还要定义一个 CorsConfigurationSource BeanBean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config new CorsConfiguration(); config.addAllowedOriginPattern(*); config.addAllowedHeader(*); config.addAllowedMethod(*); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(/**, config); return source; }很多初学者只在 Controller 加CrossOrigin但对于需要走过滤器的 JWT 请求仅注解往往无效必须两边配合。7.2 WebSocket Session 并发问题ChatEndpoint 里用的 ConcurrentHashMap 表面上前线程安全但实际上一个用户可能从多个设备/多个标签页登录会产生多个 WebSocket Session。按 userId 覆盖存储会踢掉前面登录的设备。我建议改成MapLong, ListWebSocketSession发送时遍历所有 session 推送。如果要求不高覆盖方案也能用但答辩时被老师问到“多端登录”就露馅了。7.3 图片上传存哪里直接用本地磁盘存文件开发没问题部署后会有坑重启服务文件还在但重新部署服务器时文件丢了。建议上传接口把文件写到服务器某个固定目录比如/data/uploadsNginx 再加一个location /uploads/映射到该目录。如果以后用云存储 OSS只需要把 upload 服务改成对接 OSS 的上传 URL 即可业务代码不用变。7.4 数据库连接池报错阿里云 MySQL 默认最大连接数可能不多SpringBoot 默认连接池 HikariCP 的 maximum-pool-size 默认是 10但如果你本地其他工具也占连接可能会报Too many connections。调一下配置spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 57.5 时间显示时区差 8 小时这问题太经典了数据库存的时间是2025-01-01 12:00:00前端显示成了04:00:00。原因大概率是 JDBC 连接串没带serverTimezone或者 Jackson 没配时区。解决方法是连接串加serverTimezoneAsia/ShanghaiJackson 加time-zone: Asia/Shanghai两边对齐。8. 项目扩展方向与个人实操心得如果按上面的内容全部做完这已经是一个功能完整、能部署、有亮点的交友平台系统。但如果想让它在毕设或简历里更有分量我建议你再做三件事一是加入基于 Redis 的在线状态管理。用 Redis 存一个online:userId的 keyWebSocket 连接时写入断开时删除前端再轮询或订阅这个状态就能在好友列表里显示“在线/离线”。这个一眼就能让交互深度上一个台阶。二是增加基于几何距离的附近的人功能。用 MySQL 的 longitude 和 latitude 字段存坐标虽然实现的 SQL 比较粗暴但配合 Haversine 公式可以在论文里讲得头头是道。如果数据量大再提一句使用 GeoHash 做索引理论深度就够了。三是做消息推送通知。用户 A 给用户 B 发了好友申请B 的页面上要有红点提醒。简单做法是每次请求接口时返回未读申请数量也可以做一条notification表统一管理。最后说点我自己的体会。这个项目最花时间的从来不是写代码而是前后端接口设计时没有提前把数据格式定死。我今天定createTime明天又改成create_time前端跟着一遍遍改心态崩了人只想摆烂。所以项目一开始我强烈建议你先把所有接口的请求响应 JSON 样例文档写好哪怕就写在 Markdown 里前后端各拿一份对着开发后面每天都能省下至少两个小时扯皮时间。另外做这类系统千万不要为了显得技术多而堆砌组件。你要明白答辩老师问的问题不是“你用了什么热门的中间件”而是“你在这个系统里解决了什么问题、怎么解决的”。把交友推荐、好友状态、消息可靠送达这些业务层面的细节讲透比你说自己用了 K8s 更让人信服。老老实实把每一步做扎实这套系统的含金量已经在绝大多数课程设计之上了。
返回列表