东林在线微课堂-互动问答

1.互动问答相关

准备阶段—分析业务流程

  • 主流程

image-20240823153033439

整体来说,流程是这样的:

  • 学员在学习的过程中可以随时提问问题
  • 老师、其他学员都可以回答问题
  • 老师、学员也都可以对回答多次回复
  • 老师、学员也都可以对评论多次回复
  • 老师可以在管理端管理问题、回答、评论的状态

准备阶段—字段分析

根据原型图可以得到对应字段

image-20240824150214835

准备阶段—ER图

基本上根据页面原型图得到的字段:

image-20240823153635633

准备阶段—表结构

  • 问题表

image-20240823154007026

  • 回答/评论表

image-20240824150648355

准备阶段—Mybatis-Plus代码生成

可以生成对应的文件和实体类等信息

image-20240823145646440

准备阶段–类型枚举

image-20240823151906796

准备阶段—接口统计

理论上我们应该先设计所有接口,再继续设计接口对应的表结构。不过由于接口较多,这里我们先对接口做简单统计。然后直接设计数据库,最后边设计接口,边实现接口。

image-20240823152213586

1.用户端

问题页面:

image-20240823155633183

结合原型设计图我们可以看到这里包含4个接口:

  • 带条件过滤的分页查询
  • 新增提问
  • 修改提问
  • 删除提问

问题的回答和评论页面:

image-20240823155743166

可以看到页面中包含5个接口:

  • 根据id查询问题详情
  • 分页查询问题下的所有回答
  • 分页查询回答下的评论
  • 点赞/取消点赞某个回答或评论
  • 回答某个提问、评论他人回答

2.管理端

刚才分析的都是用户端的相关接口,这些接口部分可以与管理端共用,但管理端也有自己的特有需求。

管理端也可以分页查询问题列表,而且过滤条件、查询结果会有很大不同:

image-20240823155824265

比较明显的有两个接口:

  • 管理端分页查询问题列表:与用户端分页查询不通用,功能更复杂,查询条件更多
  • 隐藏或显示指定问题

除此以外,这里有一个问题状态字段,表示管理员是否查看了该问题以及问题中的回答。默认是未查看状态;当管理员点击查看后,状态会变化为已查看;当学员再次回答或评论,状态会再次变为未查看。

因此,需要注意的是:

  • 每当用户点击查看按钮,需要根据根据id查询问题详情,此时应标记问题状态为已查看
  • 每当学员回答或评论时,需要将问题标记为未查看

管理端也会有回答列表、评论列表。另外,回答和评论同样有隐藏功能。

问题详情和回答列表:

image-20240823155848228

还有评论列表:

image-20240823155908368

总结一下,回答和评论包含的接口有:

  • 管理端根据id查询问题详情
  • 分页查询问题下的回答
  • 分页查询回答下的评论
  • 点赞/取消点赞某个回答或评论
  • 隐藏/显示指定回答或评论
  • 回答某个提问、评论他人回答、评论(与用户端共用)

==—–用户端–问题相关接口—–==

1.新增互动问题(用户端)

1.原型图

image-20240823161022682

2.设计数据库

3.业务逻辑图

比较简单,通过前端传递给我{课程id,章id,小节id,问题标题,问题具体描述,问题是否匿名}

4.接口分析

image-20240823161128538

通过新增的问题的表单即可分析出接口的请求参数信息了,然后按照Restful的风格设计即可:

image-20240823161245433

5.具体实现

  • 1.controller层

image-20240823165642847

  • 2.service层

image-20240823165750814

  • 3.serviceimpl层

image-20240823165804291

  • 4.mapper层

6.具体难点和亮点

2.修改问题(用户端)

1.原型图

2.设计数据库

3.业务逻辑图

4.接口分析

修改与新增表单基本类似,此处不再分析。我们可以参考新增的接口,然后按照Restful的风格设计为更新即可:

image-20240823170039855

5.具体实现

  • 1.controller层

image-20240823173145619

  • 2.service层

image-20240823173150262

  • 3.serviceimpl层

image-20240823173243825

  • 4.mapper层

6.具体难点和亮点

要注意校验问题是否是自己的,校验是否有这条问题

3.分页查询问题(用户端)

1.原型图

image-20240823203525426

2.设计数据库

3.业务逻辑图

这就是一个典型的分页查询。主要分析请求参数和返回值就行了。

请求参数就是过滤条件,页面可以看到的条件有:

  • 分页条件
  • 全部回答/我的回答:也就是要不要基于用户id过滤
  • 课程id:隐含条件,因为问题列表是在某课程详情页面查看的,所以一定要以课程id为条件
  • 章节id:可选条件,当用户点击小节时传递

返回值格式,从页面可以看到属性有:

  • 是否匿名:如果提交问题是选择了匿名,则页面不能展示用户信息
  • 用户id:匿名则不显示
  • 用户头像:匿名则不显示
  • 用户名称:匿名则不显示
  • 问题标题
  • 提问时间
  • 回答数量
  • 最近一次回答的信息:
    • 回答人名称
    • 回答内容

image-20240823204307508

4.接口分析

综上,按照Restful来设计接口,信息如下:

image-20240823203613606

5.具体实现

  • 1.controller层

image-20240823212331980

  • 2.service层

image-20240823212338832

  • 3.serviceimpl层

image-20240823213318136

[for循环遍历组装数据]

image-20240823212921387

  • 4.mapper层

6.具体难点和亮点

主要就是根据问题表和问答表查询对应信息:

image-20240823204407682

测试结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"total": "2",
"pages": "1",
"list": [
{
"id": "1552212554946768897",
"title": "redis安装的时候有问题,一直报错是怎么回事?",
"answerTimes": 1,
"createTime": "2022-07-27 16:41:27",
"userId": "2",
"userName": "jack",
"userIcon": "/img-tx/0abcd1d7a66a4fad98b80c1bb48ec6ec.png",
"latestReplyContent": "是不是Redis的依赖没有安装呢?",
"latestReplyUser": "13500010005"
},
//如果问题的提问者是匿名的就不显示userName userId userIcon属性
{
"id": "1585589766919852033",
"title": "Java的IO是阻塞IO吗?",
"answerTimes": 1,
"createTime": "2022-10-27 12:31:44",
"latestReplyContent": "阻塞IO和非阻塞IO都有。java.io包下的都是阻塞IO,java.nio下的是非阻塞IO",
"latestReplyUser": "admin"
}
]
}

封装过程:

4.根据id查询问题详情(用户端)

1.原型图

image-20240823175553623

由此可以看出详情页所需要的信息相比分页时,主要多了问题详情,主要字段有:

  • 是否匿名
  • 用户id:匿名则不显示
  • 用户头像:匿名则不显示
  • 用户名称:匿名则不显示
  • 问题标题
  • 提问时间
  • 回答数量
  • 问题描述详情

2.设计数据库

3.业务逻辑图

1
2
1.根据问题id获取一条问题
2.根据1步骤信息判断是否匿名情况:不匿名才赋用户信息

4.接口分析

而请求参数则更加简单了,就是问题的id

然后,再按照Restful风格设计,接口就出来了:

image-20240823175701421

5.具体实现

  • 1.controller层

image-20240823202537651

  • 2.service层

image-20240823202543455

  • 3.serviceimpl层

image-20240823202608324

  • 4.mapper层

6.具体难点和亮点

要注意只有不匿名的情况下才能获取用户信息

5.删除问题(用户端)

1.原型图

image-20240823173457552

2.设计数据库

image-20240823175401802

3.业务逻辑图

需要注意的是,当用户删除某个问题时,也需要删除问题下的回答、评论。

整体业务流程如下:

  • 查询问题是否存在
  • 判断是否是当前用户提问的
  • 如果不是则报错
  • 如果是则删除问题
  • 然后删除问题下的回答及评论 【两个表根据问题表的主键id和评论问答表的question_id对应(1对多)】

4.接口分析

image-20240823173517366

5.具体实现

  • 1.controller层

image-20240823175150666

  • 2.service层

image-20240823175156775

  • 3.serviceimpl层

image-20240823175228561

  • 4.mapper层

6.具体难点和亮点

需要注意的是,当用户删除某个问题时,也需要删除问题下的回答、评论。

整体业务流程如下:

  • 查询问题是否存在
  • 判断是否是当前用户提问的
  • 如果不是则报错
  • 如果是则删除问题
  • 然后删除问题下的回答及评论 【两个表根据问题表的主键id和评论问答表的question_id对应(1对多)】

==—–用户端–评论相关接口—–==

1.新增回答/评论(用户端)

1.原型图

image-20240824113228150

针对回答和评论的区别:

image-20240824114211785

2.设计数据库

3.业务逻辑图

image-20240824113914047

4.接口分析

综上,按照Restful的规范设计,接口信息如下:

image-20240824113518775

5.具体实现

  • 1.controller层

image-20240825141841133

  • 2.service层

image-20240825141848556

  • 3.serviceimpl层

  • 4.mapper层

无,使用mq即可

6.具体难点和亮点

  • 问题一:回复和评论的区别

    image-20240824114211785

回复:回答哪个问题,回复什么内容,要不要被看到

评论:回答哪个问题,回复什么内容,要不要被看到 + 【上一级】是哪个回答下面,评论哪个回答,针对谁

  • 问题二:新增回答记得更新question的最近一次回答id
  • 问题三:如果评论的用户是学生(前端传递是否是学生提交),标记问题为未查看【管理端根据id查看问题详情会更改为已查看】

2.分页查询回答/评论列表(用户端)

1.原型图

在问题详情页,除了展示问题详情外,最重要的就是回答列表了,原型图如下:

image-20240825104731667

我们先来分析回答列表,需要展示的内容包括:

  • 回答id
  • 回答内容
  • 是否匿名
  • 回答人信息(如果是匿名,则无需返回)
    • id
    • 昵称
    • 头像
  • 回答时间
  • 评论数量
  • 点赞数量

请求参数就是问题的id。不过需要注意的是,一个问题下的回答比较多,所以一次只能展示一部分,更多数据会采用滚动懒加载模式。简单来说说就是分页查询,所以也要带上分页参数。

再来看一下回答下的评论列表:

image-20240825104818133

仔细观察后可以发现,需要展示的数据与回答及其相似,都包括:

  • 评论id
  • 评论内容
  • 是否匿名
  • 评论人信息(如果是匿名,则无需返回)
    • id
    • 昵称
    • 头像
  • 回答时间
  • 评论数量(无)
  • 点赞数量
  • 目标用户昵称(评论特有)

从返回结果来看:相比回答列表,评论无需展示评论下的评论数量,但是需要展示目标用户的昵称,因为评论是针对某个目标的。

从查询参数来看:查询评论需要知道回答的id,这点与查询回答列表不太一样。

2.设计数据库

3.业务逻辑图

image-20240825094145845

4.接口分析

综上,按照Restful的规范设计,接口信息如下:

image-20240825105158382

5.具体实现

  • 1.controller层

image-20240825103843615

  • 2.service层

image-20240825104011588

  • 3.serviceimpl层

image-20240825104004139

  • 4.mapper层

6.具体难点和亮点

就是拼接数据,没啥难度

==—–管理端-问题相关接口—–==

1.根据条件分页查询问题(管理端)—引入ES

1.原型图

在管理端后台存在问答管理列表页,与用户端类似都是分页查询,但是请求参数和返回值有较大差别:因此需要引入ES处理

image-20240824094210826

从请求参数来看,除了分页参数,还包含3个:

  • 问题的查看状态
  • 课程名称
  • 提问时间

从返回值来看,比用户端多了一些字段:

  • 是否匿名: 管理端不关心,全都展示
  • 提问者信息:
    • 用户id
    • 用户头像:匿名则不显示
    • 用户 名称:匿名则不显示
  • 问题标题
  • 提问时间
  • 回答数量
  • 最近一次回答的信息:
    • 回答人名称
    • 回答内容
  • 问题关联的课程名称
  • 问题关联的章、节名称
  • 问题关联课程的分类名称

2.设计数据库

3.业务逻辑图

image-20240824163306170

4.接口分析

由于请求入参和返回值与用户端有较大差异,因此我们需要设计一个新的接口:

image-20240824094304095

5.具体实现

  • 1.controller层

image-20240824094857852

  • 2.service层

image-20240824094931532

  • 3.serviceimpl层

第一部分:

image-20240824174828966

第二部分:

image-20240824174932621

第三部分:

image-20240824175054481

第四部分:

image-20240824175209034

  • 4.mapper层

6.具体难点和亮点

image-20240824112643164

  • 问题二:查询条件是课程名称,数据是课程id,怎么实现模糊查询?

    所有上线的课程数据都会存储到Elasticsearch中,方便用户检索课程。并且在tj-search模块中提供了相关的查询接口

  • 问题三:那怎么保证ES和Mysql数据一致性?

    1
    2
    3
    4
    5
    方法一:同步双写,课程上架的时候数据写入Mysql,同步也写入ES
    方法二:异步双写,课程上架的时候数据写入Mysql,发送消息给MQ,MQ通知ES更新 【项目使用】
    方法三:定时同步,对于数据库新增的时候,定时批量/全量同步到ES
    方法四:基于Logstash输入输出插件
    方法五:基于cancal数据库增量日志解析工具,伪装主从数据库进行同步
策略 优点 缺点
同步双写 - 简单易实现
- 实时性高
- 代码侵入性强
- 存在不一致的风险
- 可能影响系统性能
异步双写(MQ方式) - 解耦数据写入操作
- 通过消息队列提升性能和扩展性
- 系统复杂度增加
- 可能存在消息丢失的风险
- 引入了消息中间件的依赖
定期同步 - 实现简单
- 无需改变现有业务逻辑
- 实时性差
- 可能给数据库带来额外压力
基于Binlog实时同步 - 无代码侵入
- 实时性较好
- 业务逻辑与数据同步解耦
- 构建Binlog系统复杂
- 可能存在MQ延时风险
使用Canal监听Binlog同步数据到ES - 基于MySQL的Binlog,实现数据的实时同步
- 减少系统耦合
- 需要维护额外的Canal服务
  • 问题四:CaffeineCache本地缓存怎么做的?

2.隐藏/显示问题(管理端)

1.原型图

在管理端的互动问题列表中,管理员可以隐藏某个问题,这样就不会在用户端页面展示了:

image-20240824095044589

2.设计数据库

3.业务逻辑图

由于interaction_question表中有一个hidden字段来表示是否隐藏:

image-20240824095143762

因此,本质来说,这个接口是一个修改某字段值的接口,并不复杂。

4.接口分析

我们按照Restful的风格来设定,接口信息如下:

  • 接口地址:/admin/questions/{id}/hidden/{hidden}
  • 请求方式:PUT
  • 请求参数: 路径占位符参数
    • id:问题id
    • hidden:是否隐藏

5.具体实现

  • 1.controller层

image-20240824100132775

  • 2.service层

image-20240824100138151

  • 3.serviceimpl层

image-20240824100229780

  • 4.mapper层

6.具体难点和亮点

就是简单修改字段

3.根据id查询问题详情(管理端)

1.原型图

在管理端的问题管理页面,点击查看按钮就会进入问题详情页:

image-20240824100328128

问题详情页如下:

image-20240824100430677

2.设计数据库

3.业务逻辑图

可以看到,这里需要查询的数据还是比较多的,包含:

  • 问题标题
  • 问题描述
  • 提问者信息
    • id
    • 昵称
    • 头像
  • 课程三级分类
  • 课程名称
  • 课程负责老师
  • 课程所属章节
  • 回答数量
  • 用户端是否显示

返回值与管理端分页查询基本一致,多了一个课程负责老师信息。所以我们沿用之前的QuestionAdminVO即可。但是需要添加一个课程负责老师的字段:

4.接口分析

虽然用户端也有根据id查询问题,但是返回值与用户端存在较大差异,所以我们需要另外设计一个接口。

按照Restful风格,接口信息如下:

  • 接口地址: /admin/questions/{id}
  • 请求方式: GET
  • 请求参数: 路径占位符格式
  • 返回值:与分页查询共享VO,这里不再赘述

5.具体实现

  • 1.controller层

image-20240824110945921

  • 2.service层

image-20240824110950955

  • 3.serviceimpl层

image-20240824111243999

  • 4.mapper层

6.具体难点和亮点

问题表中有一个status字段,标记管理员是否已经查看过该问题。因此每当调用根据id查询问题接口,我们可以认为管理员查看了该问题,应该将问题status标记为已查看

image-20240824105707505

==—–管理端–评论相关接口—–==

1.分页查询问答/评论列表(管理端)

1.原型图

image-20240825105504177

可以看到,返回的数据格式包含:

  • 评论id
  • 评论内容
  • 评论人信息
    • id
    • 昵称
    • 头像
    • 类型
  • 回答时间
  • 评论数量(回答时有)
  • 点赞数量
  • 目标用户昵称(评论特有)
  • 是否被隐藏(管理端特有)

与用户端查询几乎完全一致。

2.设计数据库

3.业务逻辑图

与用户端查询几乎完全一致,为什么不使用同一个接口?

原因有两点:

  • 管理端在统计评论数量的时候,被隐藏的评论也要统计(用户端不统计隐藏回答)
  • 管理端无视匿名,所有评论都要返回用户信息;用户端匿名评论不返回用户信息。

所以在实现的时候,基本逻辑可以与用户端分页一致,但统计评论数量、处理用户信息时,需要区别对待。

4.接口分析

为了减少代码重复,大家可以对代码做改造抽取,不要重复copy代码

image-20240825105639401

5.具体实现

在用户端的代码添加一个属性判断是否是真:用户端为false,管理端为true【区别:统计数量和用户信息字段】

6.具体难点和亮点

  • 问题一:为什么不复用接口?

原因有两点:

​ ①管理端在统计评论数量的时候,被隐藏的评论也要统计(用户端不统计隐藏回答)

​ ②管理端无视匿名,所有评论都要返回用户信息;用户端匿名评论不返回用户信息。

2.隐藏/显示评论(管理端)

1.原型图

与问题类似,管理员也可以显示或隐藏某个评论或评论:

image-20240824140709151

与隐藏问题类似,同样是修改hidden字段。

2.设计数据库

3.业务逻辑图

与隐藏问题类似,同样是修改hidden字段

注意:如果隐藏的是回答,则回答下的评论也要隐藏】

4.接口分析

  • 接口地址:/admin/replies/{id}/hidden/{hidden}
  • 请求方式:PUT
  • 请求参数:路径占位符参数
    • id:回答或评论id
    • hidden:是否被隐藏

5.具体实现

  • 1.controller层

image-20240824161407864

  • 2.service层

image-20240824161414397

  • 3.serviceimpl层

image-20240824161530474

  • 4.mapper层

image-20240824161535756

6.具体难点和亮点

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 1.互动问答相关
    1. 1.1. 准备阶段—分析业务流程
    2. 1.2. 准备阶段—字段分析
    3. 1.3. 准备阶段—ER图
    4. 1.4. 准备阶段—表结构
    5. 1.5. 准备阶段—Mybatis-Plus代码生成
    6. 1.6. 准备阶段–类型枚举
    7. 1.7. 准备阶段—接口统计
      1. 1.7.1. 1.用户端
      2. 1.7.2. 2.管理端
  2. 2. ==—–用户端–问题相关接口—–==
  3. 3. 1.新增互动问题(用户端)
    1. 3.1. 1.原型图
    2. 3.2. 2.设计数据库
    3. 3.3. 3.业务逻辑图
    4. 3.4. 4.接口分析
    5. 3.5. 5.具体实现
    6. 3.6. 6.具体难点和亮点
  4. 4. 2.修改问题(用户端)
    1. 4.1. 1.原型图
    2. 4.2. 2.设计数据库
    3. 4.3. 3.业务逻辑图
    4. 4.4. 4.接口分析
    5. 4.5. 5.具体实现
    6. 4.6. 6.具体难点和亮点
  5. 5. 3.分页查询问题(用户端)
    1. 5.1. 1.原型图
    2. 5.2. 2.设计数据库
    3. 5.3. 3.业务逻辑图
    4. 5.4. 4.接口分析
    5. 5.5. 5.具体实现
    6. 5.6. 6.具体难点和亮点
  6. 6. 4.根据id查询问题详情(用户端)
    1. 6.1. 1.原型图
    2. 6.2. 2.设计数据库
    3. 6.3. 3.业务逻辑图
    4. 6.4. 4.接口分析
    5. 6.5. 5.具体实现
    6. 6.6. 6.具体难点和亮点
  7. 7. 5.删除问题(用户端)
    1. 7.1. 1.原型图
    2. 7.2. 2.设计数据库
    3. 7.3. 3.业务逻辑图
    4. 7.4. 4.接口分析
    5. 7.5. 5.具体实现
    6. 7.6. 6.具体难点和亮点
  8. 8. ==—–用户端–评论相关接口—–==
  9. 9. 1.新增回答/评论(用户端)
    1. 9.1. 1.原型图
    2. 9.2. 2.设计数据库
    3. 9.3. 3.业务逻辑图
    4. 9.4. 4.接口分析
    5. 9.5. 5.具体实现
    6. 9.6. 6.具体难点和亮点
  10. 10. 2.分页查询回答/评论列表(用户端)
    1. 10.1. 1.原型图
    2. 10.2. 2.设计数据库
    3. 10.3. 3.业务逻辑图
    4. 10.4. 4.接口分析
    5. 10.5. 5.具体实现
    6. 10.6. 6.具体难点和亮点
  11. 11. ==—–管理端-问题相关接口—–==
  12. 12. 1.根据条件分页查询问题(管理端)—引入ES
    1. 12.1. 1.原型图
    2. 12.2. 2.设计数据库
    3. 12.3. 3.业务逻辑图
    4. 12.4. 4.接口分析
    5. 12.5. 5.具体实现
    6. 12.6. 6.具体难点和亮点
  13. 13. 2.隐藏/显示问题(管理端)
    1. 13.1. 1.原型图
    2. 13.2. 2.设计数据库
    3. 13.3. 3.业务逻辑图
    4. 13.4. 4.接口分析
    5. 13.5. 5.具体实现
    6. 13.6. 6.具体难点和亮点
  14. 14. 3.根据id查询问题详情(管理端)
    1. 14.1. 1.原型图
    2. 14.2. 2.设计数据库
    3. 14.3. 3.业务逻辑图
    4. 14.4. 4.接口分析
    5. 14.5. 5.具体实现
    6. 14.6. 6.具体难点和亮点
  15. 15. ==—–管理端–评论相关接口—–==
  16. 16. 1.分页查询问答/评论列表(管理端)
    1. 16.1. 1.原型图
    2. 16.2. 2.设计数据库
    3. 16.3. 3.业务逻辑图
    4. 16.4. 4.接口分析
    5. 16.5. 5.具体实现
    6. 16.6. 6.具体难点和亮点
  17. 17. 2.隐藏/显示评论(管理端)
    1. 17.1. 1.原型图
    2. 17.2. 2.设计数据库
    3. 17.3. 3.业务逻辑图
    4. 17.4. 4.接口分析
    5. 17.5. 5.具体实现
    6. 17.6. 6.具体难点和亮点
,