Java 项目实战: 交友项目 - 好友申请:查看陌生人问题

发布时间:2026/10/30 6:22:06
Java 项目实战: 交友项目 - 好友申请:查看陌生人问题 概述在用户详情页点「聊一下」第一步不是发消息而是拿到对方预设的那个问题。本文解决「这个问题存在哪、怎么查」接口GET /mf/strangerQuestions链路只有一层 Dubbo 加一条 MySQL 查询重点是把兜底逻辑和它与「回复陌生人问题」的衔接关系讲清楚。纲要业务场景详情页的「陌生人问题」卡片好友申请的前置一步数据在哪MySQLtb_question表与Question实体接口设计GET /mf/strangerQuestions?userId参数是对方 id实现链路mfController → mfService → QuestionApiDubbo→ QuestionMapper空值兜底查不到问题时的默认文案与「回复陌生人问题」的衔接回答经环信私信送达验证要点与常见误解业务场景问题卡片是好友申请的入口项目的陌生人社交流程设计成「答题过关」看到感兴趣的人先看对方主页。主页上除了资料还有一张「陌生人问题」卡片对方注册时预设的一个问题比如「你喜欢去看蔚蓝的大海还是去爬巍峨的高山」。你点「聊一下」App 先把这个问题取出来展示你在输入框里作答答完发送对方收到你的回答后可以选择「确认添加」成为好友。所以查看问题这一步有三个特征它是读操作不产生任何好友关系也不发任何消息它查的是对方的问题不是自己的它的输出是下一步「回复陌生人问题」的输入两者是同一张卡片的前后半段。┌──────────────────────────────┐ │ ← 返回 用户详情 │ ├──────────────────────────────┤ │ ┌────┐ 小妹 23岁 │ │ │头像│ 本科 · 单身 · 上海 │ │ └────┘ 缘分值 96 │ ├──────────────────────────────┤ │ TA的陌生人问题 │ │ ┌──────────────────────────┐ │ │ │ 你喜欢去看蔚蓝的大海还是 │ │ │ │ 去爬巍峨的高山 │ │ │ └──────────────────────────┘ │ │ ┌────────────────────────┐ │ │ │ 写下你的回答… │ │ │ └────────────────────────┘ │ │ [ 聊一下 ] │ └──────────────────────────────┘要点问题卡片在详情页底部「聊一下」按钮触发的是两个请求先 GET 问题用户作答后 POST 回答卡片里的问题文本完全来自服务端客户端不缓存、不拼接回答框为空时「聊一下」置灰属于客户端约束服务端仍要做内容校验。数据在哪tb_question 表陌生人问题不是存在 MongoDB也不在环信它就是 MySQL 里一张普通表。mf-model中的实体packagecom.mf.model.domain;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;//陌生人问题DataNoArgsConstructorAllArgsConstructorpublicclassQuestionextendsBasePojo{privateLongid;privateLonguserId;//问题内容privateStringtxt;}Question继承BasePojo走 MyBatis-Plus表名默认按驼峰转下划线得tb_question。一个用户一条记录user_id就是问题主人的用户 id。注册流程完善资料时写入之后用户可以在设置里改自己的问题。查询走 Dubbo 的QuestionApi实现类在mf-dubbo-dbpackagecom.mf.dubbo.api;importcom.baomidou.mybatisplus.core.conditions.query.QueryWrapper;importcom.mf.dubbo.mappers.QuestionMapper;importcom.mf.model.domain.Question;importorg.apache.dubbo.config.annotation.DubboService;importorg.springframework.beans.factory.annotation.Autowired;DubboServicepublicclassQuestionApiImplimplementsQuestionApi{AutowiredprivateQuestionMapperquestionMapper;OverridepublicQuestionfindByUserId(LonguserId){QueryWrapperQuestionqwnewQueryWrapper();qw.eq(user_id,userId);returnquestionMapper.selectOne(qw);}Overridepublicvoidsave(Questionquestion){questionMapper.insert(question);}Overridepublicvoidupdate(Questionquestion){questionMapper.updateById(question);}}user_id上一个用户只有一条记录selectOne够用如果数据出现重复比如注册重试写入两次selectOne会抛TooManyResultsException这是排查「查看问题报错」时容易忽略的一个点。接口设计项值请求地址/mf/strangerQuestions请求方式GET请求参数userId对方的用户 idquery 参数响应问题文本字符串直接作为 body 返回鉴权需要 token当前登录人由拦截器写入UserHolder接口文档地址在 YApi 的/project/19/interface/api/124。注意参数语义userId是你正在看的那个人不是登录人。登录人的 id 从 token 解出来放在UserHolder里这个接口根本用不上它。实现链路mf-app-server └── src/main/java/com/mf/server ├── controller │ └── mfController.java # GET /mf/strangerQuestions └── service └── mfService.java # 编排Dubbo 调 QuestionApi mf-dubbo ├── mf-dubbo-interface │ └── com/mf/dubbo/api/QuestionApi.java # findByUserId(Long userId) └── mf-dubbo-db └── com/mf/dubbo/api/QuestionApiImpl.java # MyBatis-Plus 查 tb_question为什么要单独一个接口问题明明是详情页的一部分为什么不让/mf/{id}/personalInfo顺带返回三个理由变更频率不同。资料昵称、头像、缘分值读多改少可以缓存问题文本用户随时能在设置里改独立接口便于客户端单独刷新这张卡片职责不同。详情接口服务的是「看人」问题接口服务的是「搭讪」后者会在聊一下的弹窗里被二次调用与详情页可以解耦演进空间。后续「回复陌生人问题」要再次读问题原文服务端重查而不是信任前端抽成独立 Service 方法后两条链路直接复用这正是mfService.strangerQuestions(Long userId)被 GET/POST 两个接口共用的原因。mfController/** * 查看陌生人问题 */GetMapping(/strangerQuestions)publicResponseEntitystrangerQuestions(LonguserId){StringquestionsmfService.strangerQuestions(userId);returnResponseEntity.ok(questions);}Spring MVC 直接把 query 参数userId绑定到形参无需注解。mfService/** * 查询用户陌生人问题 */publicStringstrangerQuestions(LonguserId){QuestionquestionquestionApi.findByUserId(userId);returnquestionnull?你喜欢java编程吗:question.getTxt();}questionApi是DubboReference注入的远程代理。Service 里值得说的就一行兜底。用户资料可能不完整注册流程允许跳过问题findByUserId返回 null 时直接给一句默认文案「你喜欢java编程吗」保证前端卡片永远有内容可渲染而不是让用户对着一个空白或报错页。整个链路的调用关系MySQL tb_questionQuestionApi(Dubbo)mfServicemfController客户端MySQL tb_questionQuestionApi(Dubbo)mfServicemfController客户端GET /mf/strangerQuestions?userId106strangerQuestions(106)findByUserId(106)select * from tb_question where user_id106Question(txt...) 或 nullQuestion / null问题文本null 时返回默认文案200 你喜欢去看蔚蓝的大海还是去爬巍峨的高山与「回复陌生人问题」的衔接查看问题只是铺垫。用户答完后App 会调POST /mf/strangerQuestions把回答交给服务端服务端把「提问人的问题 回答人的昵称/环信 id 回答内容」组装成一条 JSON 消息通过环信 IM 以系统消息fromadmin的形式私信送达提问人。也就是说问题从 MySQL 读出来回答却走环信通道送达全程不落库问题在存储层是 MySQL 的一行回答在存储层是环信服务器上的一条私信。两个接口共用同一个路径/mf/strangerQuestions靠 GET/POST 区分这是一对「读问题/答问题」的配套接口步骤接口做什么产生什么数据看问题GET /mf/strangerQuestions?userId读对方tb_question无答问题POST /mf/strangerQuestions组装 JSON 经环信送达对方环信侧一条私信确认添加POST /messages/contacts对方看到回答后加好友环信联系人 Friend 双记录后续两步分别在好友申请回复陌生人问题和好友申请测试里展开。API 速览方法路径参数返回说明GET/mf/strangerQuestionsuserId对方 id问题文本字符串查不到给默认文案POST/mf/strangerQuestionsbodyuserId、reply空 body见下一篇GET/mf/{id}/personalInfo路径参数 idTodayBest详情详情页资料与缘分值见好友申请查看用户详情验证要点双账号验证登录 A请求GET /mf/strangerQuestions?userId106应返回 B106预设的问题原文兜底验证mongosh 不适用直接用 SQLSELECT * FROM tb_question WHERE user_id106确认有记录把记录删掉再请求应返回默认文案而不是 500参数语义验证传自己的 id返回的是「自己设置的问题」可用来确认参数是「对方 id」这一语义没有搞反无副作用验证连续调用多次tb_question无写入环信控制台无消息产生。再补一个链路视角这个接口虽小但它跨了三个工程模块mf-app-serverWeb 层、mf-dubbo-interface契约、mf-dubbo-db实现任何一环没发布到位比如 Dubbo 没注册上现象都是接口 500 且日志里有No provider available。排查时先看消费端注解DubboReference的接口全限定名与提供端DubboService是否一致再去注册中心确认服务存在比盯着 Web 层代码有效率得多。常见误解澄清误解实际情况问题存在 MongoDB 或环信上存 MySQLtb_question经 Dubbo MyBatis-Plus 查询userId是当前登录人是对方的用户 id登录人 id 从 token 来本接口用不到查不到问题应该报错工程里做了兜底返回默认文案「你喜欢java编程吗」这一步会产生好友关系或消息纯读操作好友关系在「确认添加」才建立接口会顺带返回对方资料资料由/mf/{id}/personalInfo提供本接口只返回一句问题文本官方文档环信即时通讯云 REST API 回答送达用的通道下一篇展开MyBatis-Plus 条件构造器 QueryWrapper.eq的用法总结查看陌生人问题的实现薄得像一层纸Controller 收对方 idService 经 Dubbo 查一条 MySQL 记录空值给默认文案。它的价值不在代码量而在流程定位它是好友申请三步看问题 → 答问题 → 确认添加的第一步且明确了「问题在 MySQL、回答走环信」的存储分界。下一篇好友申请回复陌生人问题接着讲回答是怎么组装成 JSON、以 admin 系统消息的身份送进对方环信私信的。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询