☰
Java 项目实战: 交友项目 - 产品定位、功能模块与客户端原型解读
2026/10/15 21:29:51 网站建设 项目流程

概述

交友项目是一个陌生人社交 App,后端要用一套服务同时支撑移动端 App 和运营后台。这篇不看代码怎么写,先把产品本身讲清楚:它卖给谁、有哪几块功能、每块功能的界面长什么样,以及每个界面背后都躺着一个必须用后端技术解决的问题。

纲要

  • 陌生人社交的产品命题:怎么让两个互不认识的人建立连接
  • 目标用户画像与竞品对照(花田 / SOUL / 陌陌)
  • 产品形态:C 端移动 App + B 端运营后台,共用一套后端
  • 六大功能模块清单(按 Tab 结构组织,与原型页一一对应)
  • 客户端原型线框:登录页、交友页、圈子页、我的页
  • 从界面反推后端:功能 → 技术 → 对应章节的映射表
  • 后端工程形态:Maven 聚合工程的五个顶层模块
  • 三个最容易搞错的认知偏差

陌生人社交的产品命题

熟人社交(微信这一类)的连接是已有关系的线上化——你加了对方,因为你们本来就认识。陌生人社交反过来,连接关系在打开 App 之前根本不存在,所以产品的全部功夫都花在一件事上:

怎么在用户零关系、零内容的情况下,把一个可能愿意跟他聊天的陌生人推到他面前。

这个问题的答案在不同产品里长得不一样,落到交友项目上是三条路径:

  • 推荐流:左滑不喜欢、右滑喜欢,双方都右滑即配对成功,进入可聊天状态。冷启动靠算法和用户填的兴趣标签,不靠社交关系链。
  • 地理位置:搜附近的人,按距离倒序。陌生人社交里“离得近”天然比“画像像”更容易促成线下见面,这是一个很直接的驱动力。
  • 弱压力破冰:语音匹配(发匿名语音、收匿名语音,听完选喜欢 / 不喜欢)、测灵魂(答题给用户打标签分类)、今日佳人(每天推一个高缘分值的对象)。

注意最后这条被很多初学者忽略,但它恰恰是陌生人社交的难点——直白的搭讪压力太大了。匿名语音、答题匹配这些机制的本质是给用户一个“不用直接开口”的接口,把破冰成本降到最低。讲义里“沟通弱势群体”这个目标人群说的就是这批人。

目标用户画像与竞品

讲义给的用户数据很具体:整体以 30 岁以下为主,其中18—25 岁是核心受众。进一步分了四类:

人群主要诉求在产品里的落点
上班群体在陌生人面前建立人设,扩大交际圈圈子动态、个人资料页
学生群体找有共同话题的长期关系,乐于表达兴趣标签、测灵魂、推荐
文艺群体找同好,在小圈子里交流圈子推荐频道、兴趣社群
沟通弱势群体现有线上沟通方式无效,需要更有效的破冰手段语音匹配、今日佳人、缘分值

竞品选了三个,都有明确的对标点,不是随便挑的:

产品定位对项目的参考价值
花田兴趣匹配 + 线下活动结合内容运营与归属感的做法
SOUL弱化颜值、强调“灵魂”匹配测灵魂、标签分类、算法匹配
陌陌基于地理位置的移动社交搜附近、附近的人、距离排序

三个竞品有一个共同点:都在弱化肤浅的目的,把“探索自我”当成娱乐性卖点。做技术的时候也要记住这一点——匹配不只是算距离和标签,它承担的是产品体验。

产品形态:一套后端,两个前端

交友项目不是只有 App。它同时有两端:

端形态使用者主要做什么
C 端移动 App(Flutter + Android)普通用户交友、圈子、消息、小视频、个人中心
B 端后台管理系统(Web)运营 / 客服 / 审核用户管理、动态与小视频审核、举报处理、数据统计

两端调的是同一套后端服务。这是全篇唯一需要点一句的架构动因:如果为 App 和后台各写一套逻辑,“同一份用户数据、同一套审核规则、同一份内容”就会被复制两份,后面必然走样。把业务能力抽到独立的服务里、两个前端通过 HTTP 接口复用,这就是课程后面要讲的微服务 + 分层架构的起点——具体拆分方式属于「技术架构」那一章的活。

C 端 App
Flutter + Android

后端服务集群
app-server

B 端运营后台
Web

用户 / 资料服务

动态 / 圈子服务

消息 / 推荐服务

MySQL

MongoDB

Redis

六大功能模块清单

按客户端底部 Tab 的顺序把功能拆开。讲义和原始讲解给的口径一致:注册登录、交友、圈子、消息、小视频、我的。

模块核心能力对应原型页后续章节要解决的关键技术
注册登录手机号 + 短信验证码登录,首次登录完善资料登录页、首次登录信息完善阿里云短信、验证码 Redis 缓存、JWT 无状态鉴权
交友项目(左滑右滑)、搜附近、今日佳人、桃花传音、测灵魂、推荐好友交友页MongoDB geo 地理位置查询、推荐算法、缘分值计算
圈子发布动态(文字 + 最多 6 图)、好友动态、推荐动态、点赞 / 评论 / 转发圈子页MongoDB 存动态、MQ 异步削峰、Redis 计数
消息好友列表、即时聊天、互动通知(喜欢 / 点赞 / 评论 / 系统)消息页环信 IM 集成、消息落库、会话列表排序
小视频推荐视频流、发布视频、评论、关注小视频页FastDFS 分布式文件存储、SpringCache 缓存
我的个人资料编辑、访客记录(谁看过我)、通用设置、黑名单、钱包我的页阿里云 OSS 存头像、百度人脸识别审核、MongoDB 存访客

两张表里已经埋了整门课的引子。记住一个判断标准:凡是界面上要“跨用户聚合数据”的地方(动态流、访客、推荐),后端都不会简单——它要处理海量写入、去重和排序。凡是要“上传文件”的地方(头像、小视频、动态配图),一定绕不开对象存储或分布式文件系统。凡是“要实时”的地方(聊天、通知),一定绕不开第三方 IM 或消息中间件。

客户端原型解读

原型文件是交友项目移动端原型V1.2,一共 4 个主要页面加若干子页。下面挑四个最能代表产品形态的画成线框,文案全部取自原型,没有编造。

屏 1 登录页

登录页只有一条主路径:手机号 + 短信验证码。原型里连“重新发送”的倒计时和次数限制都标了出来,说明这不是个占位页。

+----------------------------------------+ | | | 交友项目 | | | | 项目 slogans | | | | [ 请输入手机号 ] | | [ 请输入验证码 获取验证码 ] | | | | [ 手机号登录注册 ] | | | | 已发送至 138****8888 | | 重新发送 (50s) | +----------------------------------------+

要点:

  • 文案项目 slogans是原型里的品牌标语占位(原型文件里实际拼作项目slogn,属笔误,正式产品应为 slogan)。
  • 获取验证码不是点击即发:发送后按钮变为重新发送 (50s)带倒计时,倒计时结束才可重发;超过 3 次需要等 1 小时。这条约束后端必须校验——前端按钮只是提示,防刷要靠服务端记录发送次数和冷却时间。
  • 校验规则两条:手机号位数错误时输入框标红并提示请输入正确的手机号;验证码错误时输入框抖动后清空、标红,并弹出验证码错误。
  • 登录成功且是首次登录时,不直接进首页,而是跳「首次登录信息完善」;这个状态后端要能判断(用户资料是否已完善),不能只靠前端记。
  • 这个页面在本篇只需要知道“有验证码 + 有倒计时 + 有次数限制”三件事。验证码真正的实现(阿里云短信 SDK、自动装配封装、Redis 缓存键设计)在后面的短信验证码与登录章节。

屏 2 交友页

交友页是项目的核心页,主体是一张可左右滑动的用户卡片,顶部是几个入口。

+----------------------------------------+ | 项目 搜附近 桃花传音 测灵魂 | +----------------------------------------+ | ------------------------------------ | | | | [ 用户头像 ] | | | | 黑马小美 | | 单身 · 本科 · 年龄相仿 | | 缘分值 89 | | | | ------------------------------------ | | | | [ 不喜欢 ] [ 喜欢 ] | | | | 今日还能发送 9 次 | +----------------------------------------+ | 交友 圈子 消息 小视频 我的 | +----------------------------------------+

要点:

  • 顶部四个入口:项目(左滑右滑卡片)、搜附近、桃花传音(语音匹配 / 漂流瓶式匿名语音)、测灵魂(答题分类)。
  • 卡片信息结构固定:头像、昵称、性别、学历、年龄描述(原型写作单身 本科 年龄相仿)、缘分值。缘分值是项目自己的匹配度指标,不是简单距离。
  • 左右滑的约束写在原型注释里:左划喜欢,右划不喜欢,每天限量不超过 100 个,开通会员可增加限额。页面上显示的是今日还能发送 9 次/今日还能接受 9 次——限额是按天计数的状态,必须服务端持久化,不能用本地缓存糊弄。
  • 双方互相喜欢则配对成功。这是典型的双向写场景:A 右滑 B 的时候,如果 B 之前右滑过 A,就要立刻建立好友关系。并发下同一对用户互相右滑,做不好会插入两条好友记录,这类幂等性问题在后面写业务代码时会反复遇到。
  • 搜附近页面的约束:附近的人根据用户距离倒序显示,展示头像、昵称、性别、标签、年龄、距离,点击进用户主页;原型给的示例文案是您附近有 25 个好友,选择跟他们聊聊吧!。距离倒序 = MongoDB 的地理位置索引 +$near查询。
  • 测灵魂是分级的:初级 / 中级 / 高级灵魂题,回答完初级题解锁下一级问题,点锁定题提示请先回答上一级问题;测试完有结果页可分享。题目在后台维护,每次提交更新用户属性——也就是说这个模块同时是内容管理和用户画像写入口。

屏 3 圈子页

圈子是“朋友圈的陌生人版”,顶部两个频道切换。

+----------------------------------------+ | 圈子 推荐 | 最新 发动态 | +----------------------------------------+ | 黑马小美 单身 · 本科 · 年龄相仿 | | 黑马程序员 1024 程序员节快乐 | | [ 图1 ] [ 图2 ] [ 图3 ] | | 10 分钟前 20km 赞 评 转 | | ------------------------------------ | | 黑马小美 单身 · 本科 · 年龄相仿 | | 黑马程序员 今天也要好好写代码 | | [ 图1 ] [ 图2 ] | | 1 小时前 3km 赞 评 转 | | ------------------------------------ | | 共 15 条评论 | | [ 添加评论 ] | +----------------------------------------+ | 交友 圈子 消息 小视频 我的 | +----------------------------------------+

要点:

  • 频道分推荐和最新。推荐频道是根据问卷及喜好推荐相似用户动态,最新频道按时间倒序——两者数据源不同,前者走推荐服务,后者直查库。
  • 动态可带图或视频:图片最多不超过 6 张或发布一个小视频。发布页的约束是 140 字以内、最多选 6 张照片、超过 6 张不能再选。140 字和 6 张这两个数字就是接口的校验参数和字段上限,写实体类时直接照着来。
  • 每条动态下方两类信息:相对时间(10 分钟前、1 小时前,超过一天显示具体年月日,且要做取整)和距离(20km,发布地到本地的距离)。注意距离字段意味着发布动态时要记录位置,这又回到 geo 索引。
  • 计数项:浏览量、点赞数、评论数、转发数。这四个数字是高频更新字段,直接对 MongoDB 主表做inc在高并发下会打满写热点——所以课程里会用 MQ 把点赞 / 评论这类操作异步化,这也是「RabbitMQ」那一章要引入的东西。
  • 评论可以回复,原型里显示共 15 条评论与添加评论输入框。

屏 4 我的页

个人中心,功能密度最高的一页。

+----------------------------------------+ | 我的 [ 设置 ] | +----------------------------------------+ | [ 头像 ] 黑马小美 北京 | | 互相关注 12 喜欢 34 粉丝 56 | | ------------------------------------ | | 我的动态 谁看过我 通用设置 | | 客服在线 钱包 安全设置 | | 黑名单 退出登录 | | ------------------------------------ | | 最近 4 人来访, 2 个缘分值很高 | | 黑马小美 单身 · 本科 缘分值 89 | +----------------------------------------+ | 交友 圈子 消息 小视频 我的 | +----------------------------------------+

要点:

  • 顶部三个关注类数字:互相关注 / 喜欢 / 粉丝。三者口径不同(互关是双向关系,喜欢是单向行为,粉丝是被关注数),后端是三份不同的数据。
  • 功能入口拆开看:我的动态(自己发的动态列表,时间倒序)、谁看过我(访客记录,原型示例最近 4 人来访,其中有 2 个缘分值很高)、通用设置、安全设置、黑名单、客服在线、钱包。
  • 谁看过我这一项值得单独说:它要求每次有人访问你的主页就写一条访客记录,是典型的“读少写多”数据。用 MySQL 存很快就会顶不住,所以课程选了 MongoDB。同类的还有动态和评论。
  • 编辑资料页:头像、昵称、性别、现居城市、生日。昵称要进行敏感词的过滤和限制,支持汉字、字母、数字、—和_;命中敏感词时提示输入内容包含敏感词(原型文案写成“铭感词”,是笔误)。
  • 头像流程不是上传完就完事:选择拍照或相册 → 剪裁 → 人脸审核。审核过程中前端显示扫描效果,结果以弹窗提示(成功即审核成功,失败给重新上传)。这里会用到百度 AI 的人脸识别接口,头像本身走阿里云 OSS。
  • 安全设置里有修改密码、手机号(原型马赛克为186****7674)、手势锁(创建后每次从后台切回前台要解锁)。手势锁是纯客户端能力,后端不用参与,别做多余设计。

从界面反推后端:功能和技术是配对的

这张表是整篇的落点。前面每一个界面元素,背后都能对上一个具体的技术方案和课程章节。

界面功能要解决的技术问题技术方案课程章节
手机号 + 验证码登录验证码怎么发、怎么存、怎么防刷阿里云短信服务 + 自动装配封装组件 + Redis 缓存验证码短信验证码
登录态保持无状态鉴权,避免服务端存 SessionJWT 签发 Token + 拦截器校验用户登录
完善资料(头像)文件存哪儿、怎么访问阿里云 OSS 对象存储用户资料
头像人脸审核内容合规百度 AI 人脸识别接口用户资料
搜附近 / 距离倒序地理位置查询与排序MongoDB geo 索引 +$near查询交友(搜附近)
今日佳人 / 缘分值匹配度计算基于用户标签与行为的打分 + 推荐服务推荐系统
圈子动态列表海量动态存储与分页MongoDB 文档存储圈子
点赞 / 评论 / 转发高频写、计数热点RabbitMQ 异步处理 + Redis 计数消息中间件
动态与视频推荐流个性化排序Spark + MLlib 协同过滤,独立推荐服务推荐系统
即时聊天长连接、离线消息集成环信 IM(第三方 SDK)即时通信
小视频播放与上传大文件存储与分发FastDFS 分布式文件系统 + SpringCache 缓存小视频
运营后台内容审核、用户管理、数据统计前后端分离 + 同一套 app / dubbo 服务后台管理

看这张表的正确方式不是“我要学 12 样东西”,而是:每个功能都逼出一个技术选型。这也是项目作为练手项目的价值——它不演示某个知识点,它展示一套完整业务是怎么被拆成技术方案的。

举个具体的判断过程。为什么附近的人用 MongoDB 而不是 MySQL?因为要按距离倒序取前 N 条,MySQL 里算球面距离等于对全表做函数运算,索引直接失效;MongoDB 自带2dsphere地理索引,$near能走索引。为什么动态用 MongoDB?因为动态字段不固定(图片数量、标签、位置、点赞数各不相同),关系型表要么拆一堆关联表要么留一堆空列,文档型天然合适。为什么点赞不能直接写主表?因为热门动态的点赞会集中打击同一行文档,用 MQ 攒批、幂等消费,再统一回写计数,写压力就摊平了。

后端工程形态

工程用 Maven 聚合工程组织,mf是父工程,下面五个顶层模块,Dubbo 相关再拆一层。这是后续所有章节的落脚点,先把结构记住。

mf ├── pom.xml # 父工程,统一依赖版本(Spring Boot 2.3.9.RELEASE) ├── mf-model # 实体类 / VO,前后端与 Dubbo 共享的数据模型 ├── mf-commons # 通用工具、常量、异常、拦截器 ├── mf-autoconfig # 自动装配组件(短信服务、人脸识别等第三方封装) ├── mf-dubbo # Dubbo 服务聚合层 │ ├── mf-dubbo-interface # 服务接口(消费者与提供者共用) │ ├── mf-dubbo-db # 提供者:MySQL 数据访问 │ └── mf-dubbo-mongo # 提供者:MongoDB 数据访问 └── mf-app-server # 消费者:面向前端的服务入口 └── src/main/java/com/mf/server ├── AppServerApplication.java # 启动类 ├── controller # 对外 REST 接口 └── service # 业务编排,调用 Dubbo 服务

各模块职责:

模块职责关键点
mf-model实体、DTO、VO被多方依赖,不能引入 Web 相关依赖
mf-commons通用能力常量、业务异常、统一响应、拦截器
mf-autoconfig第三方组件封装短信、人脸识别,配置项走@ConfigurationProperties
mf-dubbo-interfaceDubbo 接口定义只有接口,不含实现,消费者靠它远程调用
mf-dubbo-dbMySQL 服务提供者面向关系型数据的写读
mf-dubbo-mongoMongoDB 服务提供者动态、评论、访客、地理位置
mf-app-server面向 App / 后台的入口只有 controller 和 service,不直接连数据库

有两个设计点值得先记住,后面章节会反复出现:

mf-dubbo被拆成 interface / db / mongo 三块,不是为了好看。Dubbo 的提供者和消费者处在不同进程,接口定义必须能被两边同时依赖,所以接口单独成一个模块,实现各自独立。DB 和 Mongo 分开则是因为它们的数据来源、连接池、事务语义完全不同,混在一个提供者里会让依赖变得不可控。

mf-app-server里只有controller和service两个包,没有mapper。这不是还没写完,而是刻意为之——入口服务不碰数据库,所有数据访问都通过 Dubbo 走远程调用。这条约束一旦破坏,微服务拆分就名存实亡了。

三个容易搞错的认知偏差

以为 App 要自己写。客户端(Flutter + Android)和原型都由前端团队提供,课程给的是 APK 和 Android 模拟器,后端同学只需要按接口实现服务端。要装的是网易 MuMu 模拟器(兼容性较好),不是 Android Studio 那一整套。原型图也不是让你画的,它是接口契约的另一种形式——界面上每个字段、每个约束,最后都要在后端有对应实现。

以为功能简单。“左滑右滑”看起来是个动画效果,实际要处理每日限额持久化、互相喜欢时的并发写、配对后的会话创建。“发一条动态”看起来是个 insert,实际要处理图片上传、位置存储、距离计算、相对时间格式化、计数异步化。真正的工作量从来不在界面上。

以为学完就能上线。这个项目覆盖的是研发视角。一个社交产品真正上线还需要内容审核体系(动态、头像、视频、昵称全都要过审)、举报处理流程、运营活动、数据合规与用户隐私保护。项目里出现人脸审核、敏感词过滤这些点,是因为它们属于“不做就不能上架”的硬性要求,但完整的运营与合规体系不在课程范围内,也别指望它在这里。

官方文档

  • MongoDB 地理空间查询
  • 阿里云短信服务
  • 阿里云对象存储 OSS
  • 环信即时通讯云
  • Spring Boot 官方文档

总结

交友项目是个陌生人社交 App,核心命题是“在零关系的前提下让两个陌生人建立连接”,推荐、附近的人、语音匹配、测灵魂都是这个命题的不同解法。目标用户以 18—25 岁为核心,四类人群的诉求分别落在动态、标签、圈子和小压力破冰上。

产品是 C 端 App 加 B 端运营后台的双端形态,共用一套后端服务,这是后面必须拆微服务的根本原因。

六大模块(注册登录、交友、圈子、消息、小视频、我的)每一个都能对上一组具体技术:验证码对短信服务和 Redis,搜附近对 MongoDB geo,动态对 MongoDB 加 MQ,聊天对环信,小视频对 FastDFS,后台对前后端分离。这张映射表才是这个项目真正的导学价值——功能不是凭空来的,技术也不是凭空学的。

工程形态上,mf父工程下分 model、commons、autoconfig、dubbo(interface / db / mongo)、app-server 五块,app-server 只做入口编排、不碰数据库,这条边界是微服务拆分能不能立住的关键。

下一篇进入「技术架构」,看这套功能是怎么被拆成服务、用什么中间件串起来的。

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

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

立即咨询