前情提要
当时在设计最开始的music音乐系统模块时,虽然采用了分布式架构,但大多数核心业务操作都放在了music服务里,包括音乐评论,音乐点赞等,这是合理的。考虑音乐评论的二级评论业务时,特意考虑了消息通知系统。目前大致考虑到两种情况,一种是针对音乐人,当点赞、评论音乐,音乐人收到消息提醒。一种是对用户的消息通知,比如有人点赞或评论你的音乐评论(或多级评论),你都会收到通知。
设计的话,操作实现还算简单,音乐系统设计时,就考虑到以后要进行消息系统的引入,如果代码逻辑也特意加了todo。然后经典步骤:创建交换机,队列,我选择的是direct交换机还需要设置key,最好放在常量类里,然后在config类进行创建和绑定。然后发送消息,这个消息定义为一个Bo,这里需要注意一些东西,这个定义比较重要,功能的实现总是会很简单,但是同样一个功能好的公司总会很贴合用户体验,用户体验的好坏,也是业务设计的好坏,这里参考QQ音乐。
图一
图二
分析图二,明明是4条评论怎么显示9条呢,是不是缓存问题,其实并不是,这是因为一个不太必要的bug,这是多级评论,一首音乐计算的时候QQ音乐把一级评论(就是评论歌曲的)和多级评论(就是评论评论的)都算成了评论数,他展示评论区的逻辑是直接搜一级评论,然后点击展开回复再搜二级评论,但是重点来了,他进行删除的时候并没有去把评论该评论的评论去,就会导致图一和图二的现象,实际上多级评论在一级评论删除后,并不会删除,就会变得和JVM里的垃圾一样,无法清理,没有作用。图一里我先评论了一条消息,然后测试号评论了一级评论,我再评论测试号,测试号再评论我评论的评论,画一个图吧。当我发布的一级评论删除后,id为1的评论回复的该一级评论就会显示该评论已删除,而id为1不显示已删除;回复2的评论以及2评论都未删除,这没啥过错,但可能不太合适。
然后当无法查询到账号id时,就显示该用户已注销,查不到评论分两种,自己的评论删除了,和评论你的评论删除了,如下两图所示。这种处理方法也很典型,很巧妙的实现了删除的目的即不让别人看到。
前端页面简单完成, 然后去完成后端接口,代码如下
public Result getPersonalNotices(Long account) {
List<SendUserNoticeBo> originalNotices = noticeMapper.getNoticesByAccount(account);
ArrayList<NoticeVo> notices = new ArrayList<>();
originalNotices.forEach(notice -> {
NoticeVo noticeVo = new NoticeVo();
// 1. 准备数据
Integer noticeId = notice.getId();
Integer commentId = notice.getCommentId();
Integer musicId = notice.getMusicId();
Integer doCommentId = notice.getDoCommentId();
// 2. 开始SQL查询所需要填充的数据
// 2.1 查询评论信息
UserCommentPo userInfo = userClient.getInfoByAccount(account);
CommentVo commentVo = commentMapper.queryInfoById(commentId);
CommentVo doCommentVo = commentMapper.queryInfoById(doCommentId);
MusicVo musicVo = musicMapper.queryMusicDetail(musicId);
// 3. 进行判断
if (userInfo == null) {
noticeVo.setAvatar(null);
noticeVo.setUsername("该用户已注销");
} else {
noticeVo.setAvatar(userInfo.getAvatar());
noticeVo.setUsername(userInfo.getUsername());
}
if (doCommentVo.getDie()) {
// 如果被评论的为空
noticeVo.setComment("该评论已删除");
} else {
noticeVo.setComment(commentVo.getContent());
}
if (doCommentVo.getDie()) {
noticeVo.setContent("该评论已删除");
noticeVo.setTime(doCommentVo.getCommentTime());
} else {
noticeVo.setContent(doCommentVo.getContent());
noticeVo.setTime(doCommentVo.getCommentTime());
}
// 4. 进行填充
noticeVo.setId(noticeId);
noticeVo.setAlbumCover(musicVo.getCover());
noticeVo.setMusicName(musicVo.getName());
noticeVo.setMusician(musicVo.getMusician());
// 4. 添加到集合里
notices.add(noticeVo);
});
return Result.ok(notices);
}