文章目录
功能需求
-
1.对帖子、评论、回复可以进行点赞操作
- 无需刷新整个网页,采用异步请求
- 由于点赞频繁,且数据单一且动态变化
- 用关系型数据库存io操作性能较低,改用redis存储
- 数据单一,只有点赞一个属性字段需要更改,且针对不同类型不同id点赞的类型动态变化,
- 因此,设计mysql表比较浪费,以及为了操作一个变化的赞字段,要将很多相关帖子用户信息字段都查询到,也比较浪费,
- 使用redis设计不同的key比较方便
-
2.redis储存点赞数据后,刷新页面后,要能够在页面显示这些点赞信息
- 因此,需要更新之前开发的controller和模板页面相关处理
1. dao层设计redis的key生成工具
- 由于针对不同的帖子、评论、回复等实体要定义不同的key,可以封装成一个工具类,方便生成key
public class RedisLikeUtil {
// redis字符串拼接符:
private static final String SPLIT = ":";
// redis定义点赞的key的前缀
private static final String PREFIX_ENTITY_LIKE = "like:entity";
/**
* 某个实体的赞的key
* like:entity:entityType:entityId -> set(userId)
* @param entityType 实体类型
* @param entityId 实体id
* @return 针对特定实体的赞的key
*/
public static String getEntityLikeKey(int entityType, int entityId) {
return PREFIX_ENTITY_LIKE + SPLIT + entityType + SPLIT + entityId;
}
}
2. Service层处理点赞业务
添加赞或删除赞
- 添加赞或删除赞,根据当前用户点赞的状态来定
- value不是简单的使用String类型,而是用集合set类型,
- 集合中装每个访问用户的id,方便查询指定用户的点赞状态
isMember(key, userId)
remove(key, userId)
add(key, userId)
/**
* 添加赞或删除赞,根据当前用户点赞的状态来定
* @param userId 当前访问用户id
* @param entityType 访问的实体类型
* @param entityId 访问的实体id
*/
public void addLike(int userId, int entityType, int entityId) {
String key = RedisLikeUtil.getEntityLikeKey(entityType, entityId);
Boolean isMember = redisTemplate.opsForSet().isMember(key, userId);
if(isMember) {
redisTemplate.opsForSet().remove(key, userId);
} else {
redisTemplate.opsForSet().add(key, userId);
}
}
查询指定实体的点赞状态
- **用数字来表示点赞的状态,方便扩展,**今后可能还会有点彩等其他状态
/**
* 查询指定实体的点赞状态
* @param userId
* @param entityType
* @param entityId
* @return 用数字来表示点赞的状态,方便扩展
*/
public int findEntityLikeStatus(int userId, int entityType, int entityId) {
String key = RedisLikeUtil.getEntityLikeKey(entityType, entityId);
return redisTemplate.opsForSet().isMember(key, userId) ? LIKE_STATUS_YES : LIKE_STATUS_NO;
}
/**
* 点赞状态:位赞
*/
int LIKE_STATUS_NO = 0;
/**
* 点赞状态:已赞
*/
int LIKE_STATUS_YES = 1;
}
查询指定实体的点赞数量
- 注意返回类型是long类型
size(key)
/**
* 查询指定实体的点赞数量
* @param entityType
* @param entityId
* @return 注意返回类型是long类型
*/
public long findEntityLikeCount(int entityType, int entityId) {
return redisTemplate.opsForSet().size(RedisLikeUtil.getEntityLikeKey(entityType, entityId));
}