前言:最近也是在写一个项目,我负责的模块涉及类似论坛的社交圈子模块,在这里做个总结吧。能帮助别人当然更好,毕竟我是一个有着高尚节操的社会主义新青年!
一、功能目的
1、 实现社交目的,用户可以给其他用户发布的动态点赞、收藏、评论、转发等功能。
2、用户之间可以互相关注
二、业务思路
1、由于类似业务所需要的场景,大部分都需要频繁访问数据库,以及考虑高并发等因素;
2、业务流程并不复杂,怎么合理的存储数据相较而言比较麻烦了。
三、给大佬们喂屎!!!【手动狗头】
1、数据库设计
(1)、动态表
(2)、用户表
(3)、用户互相关注表
(4)、评论表
2、业务代码实现
(1)、点赞功能实现
鄙人的想法:
1、需要考虑的是,点赞这种功能肯定是不能直接访问mqsql数据库中的,操作过于频繁,会导致数据库的拥堵,需要将它存储到redis缓存中。然后做一个定时任务,将数据定时批量存储到数据库中;
2、类似【知乎】等之类的社交平台,用户对你的动态或者某条评论进行点赞时,被点赞的用户也会收到“某某用户喜欢了你的某条动态”这样的业务功能。由于是个练手项目时间也比较紧张,这里只是更新了点赞数量,这个消息功能倒还没有做。但类似参考下面的【关注】业务功能,使用mq对其进行实现,也不是特别“懒”。
3、还需要注意的是,点赞之后再次点击就会取消点赞。
废话不多说了,任尔麒麟云中现,呼吸一剑开天门!(咳咳、比赛触发我的灵感)
a、controller
/**
* 点赞功能
*/
@PostMapping("/likeDynacim/{dynamicId}")
@ApiOperation("动态点赞")
public CommonResult thumbDynamic(@PathVariable Integer dynamicId, HttpServletRequest request) {
//这是对当前登录页面做一个登录判断,若是没有登录,则不能进行一键三连
Integer userId = (Integer) getUserId();
if (Objects.isNull(userId)) {
return CommonResult.failure("用户未登录!");
} else {
//调用业务层点赞方法
Boolean status = userLikeDetailService.likeDynamic(userId, dynamicId);
return CommonResult.success(status);
}
}
b、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;
/**
* 点赞动态
*/
@Override
public Boolean likeDynamic(Integer userID, Integer dynamicID) {
//1、判断该用户有没有点赞过
Boolean member = redisTemplate.opsForSet()
.isMember(RedisConstant.LIKE_DYNAMIC + ":" + dynamicID, userID);
System.out.println("member=======>" + member);
//2、判断是否点赞过
if (member) {
//3、如果存在 则取消点赞 删除这个值
redisTemplate.opsForSet().remove(RedisConstant.LIKE_DYNAMIC + ":" + dynamicID, userID);
}else {
//4、不存在则将点赞加入这个set集合中
redisTemplate.opsForSet().add(RedisConstant.LIKE_DYNAMIC + ":" + dynamicID, userID);
}
//----------------------------------------------------------------------------------------------
Set<Integer> cacheSet = redisUtil.getCacheSet(RedisConstant.LIKE_DYNAMIC);
System.out.println("cacheSet==================>"+cacheSet);
return redisTemplate.opsForSet()
.isMember(RedisConstant.LIKE_DYNAMIC + ":" + dynamicID, userID);
}
定义的存储key常量名
**
* redis key 名常量
*/
public interface RedisConstant {
/**
* 动态 点赞 key
*/
public static final String LIKE_DYNAMIC = "likeDynamic";
public static final String LIKE_DYNAMIC_KEY_NAME = "likeDynamic*";
}
redis存储的数据结构
-------------到这里了,我们点赞数据的存储就是完成了,假如用户再次点击,redis缓存中的set集合也会将该动态点赞用户的id删除掉。后面我们的任务就是开启一个定时任务定时的将redis数据存储到mysql数据库中做持久化。
/**
* 定时任务类
*/
@Component
@Slf4j
public class Task {
@Resource
private RedisTemplate redisTemplate;
@Resource
private IUserLikeDetailService userLikeDetailService;
@Resource
private RedisUtil redisUtil;
@Resource
private IDynamicService dynamicService;
/**
* 将动态的评论数量 、点赞数量等存储到数据库中
* id--->数量
*/
@Scheduled(cron = "0/3 * * * * ?")
public void initThumbs() {
redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
//1、根据键值常量获取点赞集合
Set<byte[]> likeDynamicSet = redisConnection.keys("likeDynamic*".getBytes());
//2、new 一个集合 用于分装数据
List<Dynamic> dynamics = new ArrayList<>();
//3、遍历集合分别获取对应的键值
for (byte[] b : likeDynamicSet) {
//4、用于操作redis中的key
String bKey = new String(b);
//5、通过key来获取对应的value
Set<Integer> cacheSet = redisUtil.getCacheSet(bKey);
int i = bKey.lastIndexOf(":");
// 动态id
Integer dynamicId = Integer.valueOf(bKey.substring(i + 1));
// 点赞数
int dyPraiseNum = cacheSet.size();
//6、封装数据
Dynamic dynamic = new Dynamic();
dynamic.setId(dynamicId);
dynamic.setDyPraiseNum(dyPraiseNum);
//7、将该对象添加到集合中
dynamics.add(dynamic);
}
//8、批量更新
boolean b = dynamicService.updateBatchById(dynamics);
log.info("--------------开始定时存储点赞数据------------");
return b;
}
});
}
到此为止,我们动态的点赞业务就完成了。还剩一点后面再写,今天过节,对于我这瓢泼在外的IT民工,也要对自己好一点。
今天中秋,祝工友们中秋快乐,身体健康。