当前位置:网站首页>10、Redis实现点赞(Set)和获取总点赞数
10、Redis实现点赞(Set)和获取总点赞数
2022-07-31 02:36:00 【A snicker】
实现点赞

不用写数据访问层,直接在Service层写即可。
1、创建RedisKeyUtil工具类生成key:
public class RedisKeyUtil {
private static final String SPLIT = ":";
private static final String PREFIX_ENTITY_LIKE = "like:entity";
// 某个实体的赞
// like:entity:entityType:entityId -> set(userId)
public static String getEntityLikeKey(int entityType, int entityId) {
return PREFIX_ENTITY_LIKE + SPLIT + entityType + SPLIT + entityId;
}
}
2、LikeService
@Service
public class LikeService {
@Autowired
private RedisTemplate redisTemplate;
// 点赞,查看该用户userId是否在集合里,没在集合里,加进去,即点赞;在集合里,取消点赞,remove掉
public void like(int userId, int entityType, int entityId) {
String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
boolean isMember = redisTemplate.opsForSet().isMember(entityLikeKey, userId);
if (isMember) {
redisTemplate.opsForSet().remove(entityLikeKey, userId);// 取消点赞
} else {
redisTemplate.opsForSet().add(entityLikeKey, userId);
}
}
// 查询某实体点赞的数量,看集合里有多少个userId
public long findEntityLikeCount(int entityType, int entityId) {
String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
return redisTemplate.opsForSet().size(entityLikeKey);
}
// 查询某人对某实体的点赞状态,看某userId是否在集合里,返回1点赞了,返回0没点赞(点踩可以返回-1)
public int findEntityLikeStatus(int userId, int entityType, int entityId) {
String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
return redisTemplate.opsForSet().isMember(entityLikeKey, userId) ? 1 : 0;
}
}
3、LikeController
@Controller
public class LikeController {
@Autowired
private LikeService likeService;
@Autowired
private HostHolder hostHolder;
@RequestMapping(path = "/like", method = RequestMethod.POST)
@ResponseBody
public String like(int entityType, int entityId) {
User user = hostHolder.getUser();
// 点赞
likeService.like(user.getId(), entityType, entityId);
// 重新计算数量
long likeCount = likeService.findEntityLikeCount(entityType, entityId);
// 重新计算状态
int likeStatus = likeService.findEntityLikeStatus(user.getId(), entityType, entityId);
Map<String, Object> map = new HashMap<>();
map.put("likeCount", likeCount);
map.put("likeStatus", likeStatus);
return CommunityUtil.getJSONString(0, null, map);
}
}
4、异步请求,discuss.js
function like(btn, entityType, entityId) {
$.post(
CONTEXT_PATH + "/like",
{
"entityType":entityType,"entityId":entityId},
function(data) {
data = $.parseJSON(data);
if(data.code == 0) {
$(btn).children("i").text(data.likeCount);
$(btn).children("b").text(data.likeStatus==1?'已赞':"赞");
} else {
alert(data.msg);
}
}
);
}
获取总点赞数
1、改key拼接工具类RedisKeyUtil
private static final String PREFIX_USER_LIKE = "like:user";
// 某个用户的被点赞总数, value是Object->强转成Integer->intValue()转成int型
// like:user:userId -> int
public static String getUserLikeKey(int userId){
return PREFIX_USER_LIKE + SPLIT + userId;
}
2、LikeService,编程式事务
保证事务性,一次点赞两处增加,编程式事务
public void like(int userId, int entityType, int entityId, int entityUserId) {
// 保证事务性,一次点赞两个增加,编程式事务
redisTemplate.execute(new SessionCallback() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
String entityLikeKey = RedisKeyUtil.getEntityLikeKey(entityType, entityId);
String userLikeKey = RedisKeyUtil.getUserLikeKey(entityUserId);
// 查询要在事务之前,不能放在事务里面,否则事务提交之后才执行。
boolean isMember = operations.opsForSet().isMember(entityLikeKey, userId);
operations.multi();
if (isMember) {
operations.opsForSet().remove(entityLikeKey, userId);// 取消点赞
operations.opsForValue().decrement(userLikeKey);// 减少实体的被点赞数
}else{
operations.opsForSet().add(entityLikeKey, userId);// 点赞
operations.opsForValue().increment(userLikeKey);// 增加实体的被点赞数
}
return operations.exec();
}
});
}
查询某个用户获得的赞的总数
// 查询某个用户获得的赞的总数
public int findUserLikeCount(int userId) {
String userLikeKey = RedisKeyUtil.getUserLikeKey(userId);
Integer count = (Integer) redisTemplate.opsForValue().get(userLikeKey);
return count == null ? 0 : count.intValue();
}
边栏推荐
- To write good test cases, you must first learn test design
- Intranet Infiltration - Privilege Escalation
- The real CTO is a technical person who understands products
- SQL注入 Less47(报错注入) 和Less49(时间盲注)
- [1154]如何将字符串转换为datetime
- Crypto Life, a day in the life of a Web3 project partner
- Refuse to work overtime, a productivity tool set developed by programmers
- STP选举(步骤+案列)详解
- 软件积累 -- 截图软件ScreenToGif
- 系统需求多变如何设计
猜你喜欢

知识蒸馏7:知识蒸馏代码详解

Nacos

软件积累 -- 截图软件ScreenToGif

There is a problem with the multiplayer-hlap package and the solution cannot be upgraded

基于opencv实现人脸检测

AI在医疗影像设备全流程应用

Inter-vlan routing + static routing + NAT (PAT + static NAT) comprehensive experiment

MPPT太阳能充放电控制器数据采集-通过网关采集电池电压容量电量SOC,wifi传输

Intel's software and hardware optimization empowers Neusoft to accelerate the arrival of the era of smart medical care
![LeetCode 1161 The largest element in the layer and the LeetCode road of [BFS binary tree] HERODING](/img/56/fcc8ee6f592abf0a374fc950a3362f.png)
LeetCode 1161 The largest element in the layer and the LeetCode road of [BFS binary tree] HERODING
随机推荐
Classic linked list OJ strong training problem - fast and slow double pointer efficient solution
力扣刷题之爬楼梯(7/30)
multiplayer-hlap 包有问题,无法升级的解决方案
Linux下redis7的安装,启动与停止
[1154]如何将字符串转换为datetime
Unity界面总体介绍
The effective square of the test (one question of the day 7/29)
mysql view
vlan间路由+静态路由+NAT(PAT+静态NAT)综合实验
The application of AI in the whole process of medical imaging equipment
Teach you how to configure Jenkins automated email notifications
C language applet -- common classic practice questions
Drools basic introduction, introductory case, basic syntax
系统需求多变如何设计
STP选举(步骤+案列)详解
跨专业考研难度大?“上岸”成功率低?这份实用攻略请收下!
Intel's software and hardware optimization empowers Neusoft to accelerate the arrival of the era of smart medical care
Verify the integer input
STM32CUBEMX开发GD32F303(11)----ADC在DMA模式下扫描多个通道
软件积累 -- 截图软件ScreenToGif