前言:续上篇,我们完成了更新某条动态的总的点赞数,这一篇我们完成关注功能
一、业务思路:
1、关注与点赞类似,不同之处在于我们需要将用户彼此关注之间的数据都需要存储起来。
2、需要注意的还是存在高并发的场景。还是需要高并发的时候进行缓存和限流。我这里选择的是mq对其进行限流。
3、当初设想的是用户关注以后,就可以把关注着和被关注的用户全部存储到中间表中。涉及到并发情况,我选择了使用mq消息队列的方式来实现。这样在高并发的情况中,我们可以对队列进行削峰限流等操作对其流量进行管控。这样既能提高业务的及时性,也可以保证数据库稳定性。
4、没有选择redis的原因是因为在做定时更新的时候涉及到批量的新增以及需要去查询数据库中该用户的关注状态,一边查一边添加,对数据库压力比较大。
二、业务实现:
1、controller层
/**
* 关注用户
*/
@PostMapping("/likeUser/{likeUserId}")
@ApiOperation("关注用户")
public CommonResult likeUser(@PathVariable Integer likeUserId, HttpServletRequest request){
Integer userId = (Integer) getUserId();
if (Objects.isNull(userId)) {
return CommonResult.failure("用户未登录!");
} else {
// System.out.println("userId =============> " + userId);
Boolean status = userLikeDetailService.likeUser(userId, likeUserId);
return CommonResult.success(status);
}
}
2、serviceImpl 业务实现层
@Service
public class UserLikeDetailServiceImpl extends ServiceImpl<UserLikeDetailMapper, UserLikeDetail> implements IUserLikeDetailService {
@Resource
private RedisTemplate redisTemplate;
@Resource
private RabbitTemplate rabbitTemplate;
@Resource
private UserLikeDetailMapper userLikeDetailMapper;
@Resource
private RedisUtil redisUtil;
@Resource
private LikeUserConsumer likeUserConsumer;
/**
* 关注方法
* @param userId 当前登录用户id
* @param likeUserId 用户关注的up主的id
* @return
*/
@Override
public Boolean likeUser(Integer userId, Integer likeUserId) {
//1、分装成一个likeUserDto对象
LikeUserDto likeUserDto = new LikeUserDto();
likeUserDto.setConcernUserID(likeUserId);
likeUserDto.setConcernPostID(userId);
//2、放入MQ消息队列中对其进行管控,延迟等操作
rabbitTemplate.convertAndSend(MqConsent.LIKE_USER_EXCHANGE,
MqConsent.LIKE_USER_KEY, likeUserDto);
//3、调用mq中的添加方法
return null;
}
上述是关注业务处理方法,也是mq生产者
以下代码,以注解的方式创建交换机、队列;并进行绑定;此时需要注意,在消费者端创建的交换机和队列的方式,要和生产者端保持一致。
/**
* 关注用户mq消费者
*/
@Component
public class LikeUserConsumer {
@Resource
private IUserLikeDetailService userLikeDetailService;
@RabbitHandler
@RabbitListener(
queues = {
MqConsent.LIKE_USER_QUEUE
}
)
public void handleLikeUser(@Payload LikeUserDto likeUserDto, Channel channel, @Headers Map headers) {
//1、判断当前用户有没有关注这个被关注者
LikeUserDto likeUser = userLikeDetailService.findLikeUser(likeUserDto);
//System.out.println("likeUser==================>"+likeUser);
//System.out.println("likeUserDto---------------------->"+likeUserDto);
//2、判断数据库有没有符合这两个条件的数据,如果为空,则说明没有关注
if(Objects.isNull(likeUser)) {
//1、将队列中的消息添加到数据库中
UserLikeDetail userLikeDetail = new UserLikeDetail();
userLikeDetail.setConcernUserId(likeUserDto.getConcernUserID());
userLikeDetail.setConcernPostId(likeUserDto.getConcernPostID());
boolean save = userLikeDetailService.save(userLikeDetail);
System.out.println("添加关注者id信息结果=====================>" + save);
long id = (long) headers.get(AmqpHeaders.DELIVERY_TAG);
try {
channel.basicAck(id,false);
} catch (IOException e) {
e.printStackTrace();
}
}else {
//1、如果存在就进行删除
Boolean aBoolean = userLikeDetailService.unLikeUser(likeUserDto);
System.out.println("--------aBoolean已取消关注---------"+aBoolean);
}
}
}
这里对业务层的消息进行消费
3、cansent MQ的常量
/**
* mq 常量
*/
public interface MqConsent {
/**
* 交换机
*/
public static final String LIKE_USER_EXCHANGE = "like-user-exchange";
/**
* 队列
*/
public static final String LIKE_USER_QUEUE = "like-user-queue";
/**
* 路由key
*/
public static final String LIKE_USER_KEY = "likeUser";
}
到此一个简单的关注点赞功能就实现了。
本文含有隐藏内容,请 开通VIP 后查看