目录
这个项目的整体结构来源于牛客网,主要使用了Springboot、Mybatis、MySQL、Redis、Kafka、等工具。主要实现了用户的注册、登录、发帖、点赞、系统通知、按热度排序、搜索等功能。另外引入了redis数据库来提升网站的整体性能,实现了用户凭证的存取、点赞关注的功能。基于 Kafka 实现了系统通知:当用户获得点赞、评论后得到通知。利用定时任务定期计算帖子的分数,并在页面上展现热帖排行榜。
首先是IOC,到底什么是IOC呢?IOC(Inversion Of Control)叫做控制反转。它主要还是一种设计思想,它可以将原本手动创建实例的过程交给 spring 来处理。目的就是简化开发。因此,IOC还提供了IOC容器来存放这些实例。
IOC的主要实现就是DI依赖注入,Spring帮助了我们生产对象、管理对象、管理对象与对象之间的依赖关系。降低了代码的耦合度、方便开发。
其中依赖注入也有几种方式
1、通过构造函数创建
2、通过set方法创建
3、用p命名空间
4、使用注解的方式:@Autowired/@Resource
AOP(Aspect Oriented Programming)称为面向切面编程。
AOP是一种编程思想,它可以将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装起来,减少系统的重复代码,降低了模块之间的耦合度,具有可扩展性和可维护性
AOP的实现原理是动态代理,分别有两种:JDK动态代理和CGLIB动态代理
现在实现AOP的方式主要有两种,一个是Spring AOP,另一个是 AspectJ AOP,其中Spring AOP已经集成了AspectJ,两者的区别:AspectJ功能更加强大性能更好,但SpringAOP更简单,
Redis支持5种基本数据类型:字符串(String),列表(List),集合(set),哈希结构(hash),有序集合(sorted set);还有两种数据结构:HyperLogLog 和 BitMap。
(UV:网站的独立访客)(DAU:日活跃用户)
HyperLogLogs 基数统计用来解决什么问题?
这个结构可以非常省内存的去统计各种计数,比如注册 IP 数、每日访问 IP 数的页面实时UV、在线用户数,共同好友数等。
Bitmap 即位图数据结构,都是操作二进制位来进行记录,只有0 和 1 两个状态。
用来解决什么问题?
比如:统计用户信息,活跃,不活跃! 登录,未登录! 打卡,不打卡! 两个状态的,都可以使用 Bitmaps!
如果存储一年的打卡状态需要多少内存呢? 365 天 = 365 bit 1字节 = 8bit 46 个字节左右!
添加评论有三种方式:① 回帖,② 回复评论,③ 回复某人的评论。
① 在 discuss-detail 页面点击最下方的回帖,映射到 CommentController 层的 /add/{discussPostId}。传入了 entityType = 1 和 entityId = post.id 。
② 在评论下方回复,与①映射相同,传入entityType = 2 和 entityId = comment.id。
③ 对某人的评论回复,与①映射相同,传入entityType = 2 和 entityId = comment.id 和 targetId。
对传入的 comment 进一步设置userId,Status,CreateTime。然后调用commentService.addComment(comment) 方法插入数据库。
commentService.addComment 使用了事务注解。该方法对 comment 的 content 进行转义HTML标记和过滤敏感词。然后使用 commentMapper.insertComment 插入评论。然后通过 commentMapper.selectCountByEntity 查询帖子的评论数量,再使用 discussPostService.updateCommentCount 方法将评论数量插入帖子详情表。
点赞
前提:在 util 的 RedisKeyUtil 工具类中写 getEntityLikeKey 方法,传入 entityType, entityId 返回某个实体(帖子或回复)的赞的key值 。
分为两种:① 给帖子点赞 ② 给回复点赞。
① 在帖子详情页面对帖子内容点赞,按钮通过 discuss.js 将 entityType=0 , 帖子id:entityId 和 entityUserId 通过 /like 映射传递给 LikeController 层中的 like 方法。
like 方法通过调用 likeService 层的 like 进行点赞功能,然后再依次调用 findEntityLikeCount,findEntityLikeStatus 方法查询该帖子的点赞数量,查询当前登录用户的点赞状态。
likeService 层的 like 方法首先判断是否已经点过赞了,如果没有,就在Redis中该帖子key对应的set中加入点赞者的userId,并且对该帖子用户的赞的总数加一。如果已经赞过则移除UserId,并且对该帖子用户的赞的总数减一。(此处使用了事务,因为需要同时进行两个业务)
触发 Topic 为 TOPIC_LIKE 的事件: 构建Event,设置当前登录用户id,被点赞对象的type,被点赞对象的id,被点赞对象所在的帖子id(因为被点赞的对象可能是帖子或者回复),被点赞对象的用户id。然后调用 eventProducer 将 Event 发布到指定 Topic。
将点赞的数量和状态装入map,通过json字符串返回。在浏览器中显示。
② 在帖子详情页面对回复点赞,按钮通过 discuss.js 将 entityType=1 和 回复id:entityId 和 entityUserId 通过 /like 映射传递给 LikeController 层中的 like 方法。
注: 另外在 HomeController 层中 /index 映射的方法中,增加向浏览器返回帖子赞的数量的功能。在 DiscussPostController 层中 /detail/{discussPostId} 映射的方法中,增加向浏览器返回帖子和回复列表的赞数量和状态的功能。