点赞模块
点赞模块主要分为两部分,点赞信息的更新和查看是否点赞,收藏和关注也是如此,首先是点赞信息的更新
点赞更新
点赞更新需要拿到对应的点赞信息和帖子信息,帖子信息用于增加点赞数,如果没有点赞信息还需要新建点赞信息,并且发一个消息通知被点赞的用户,消息我简单的使用一个数据库表来实现的,比较low,如果有点赞信息就直接拿来更新,同时根据更新前的状态来更新帖子的点赞数,点赞数用redis的自增操作来保证原子性,更新完后把点赞信息进行保存。
@Override
/**
* 帖子点赞更新
*/
public LikeArticle updateLikeArticle(LikeArticleForm likeArticleForm, String userId) throws BBSException {
LikeArticle likeArticle;
String articleId = likeArticleForm.getLikeArticleId();
// 1.在redis或数据库中查找被点赞的帖子
Article article = articleService.getArticle(articleId);
// 2.看redis中有没有帖子点赞信息
if (redisTemplate.hasKey("LikeArticle::" + articleId + '-' + userId)){
likeArticle = (LikeArticle) redisTemplate.opsForValue().get("LikeArticle::" + articleId + '-' + userId);
}
// 3.若没有则去数据库中查询点赞信息
else {
likeArticle = likeArticleRepository.findLikeArticle(articleId, userId);
}
// 4.若还是没有则新建点赞信息,并设置帖子id和点赞用户id
if (likeArticle == null){
likeArticle = new LikeArticle();
likeArticle.setLikeArticleId(articleId);
likeArticle.setLikeUserId(userId);
// 如果是新建的点赞信息,并且点赞的状态是已点赞,而且点赞的不是自己的帖子,则创建新的点赞通知消息
if (likeArticleForm.getIsLike().equals(LikeEnum.LIKE.getCode())
&& !userId.equals(article.getArticleUserId())){
Message message = new Message();
message.setArticleId(articleId);
message.setMessageType(MessageEnum.LIKE_MESSAGE.getCode());
message.setReceiverUserId(article.getArticleUserId());
message.setSenderUserId(userId);
message.setRepliedContent(article.getArticleContent());
message.setMessageContent("赞了你的帖子");
messageService.createMessage(message);
}
}
// 5.更新被点赞帖子的点赞数
// 如果点赞信息为空或者为未点赞且要更新的点赞信息为已点赞,则帖子点赞数+1
if (likeArticle.getIsLike() == null || likeArticle.getIsLike().equals(LikeEnum.NOT_LIKE.getCode())){
if (likeArticleForm.getIsLike() == LikeEnum.LIKE.getCode()){
redisTemplate.opsForHash().increment("Article::" + articleId, "articleLikeNum", 1);
}
}
// 如果点赞信息为已点赞且要更新的点赞信息为未点赞,则帖子点赞数-1
else {
if (likeArticleForm.getIsLike().equals(LikeEnum.NOT_LIKE.getCode())){
redisTemplate.opsForHash().increment("Article::" + articleId, "articleLikeNum", -1);
}
}
// 5.设置点赞状态
likeArticle.setIsLike(likeArticleForm.getIsLike());
// 6.将点赞信息存入redis
redisTemplate.opsForValue().set("LikeArticle::" + articleId + '-' + userId, likeArticle, 1, TimeUnit.HOURS);
return likeArticle;
}
查看是否点赞过
这步比较简单,直接拿出来看看,返回true或false就可以:
@Override
/**
* 查看帖子是否被点赞
*/
public Boolean isArticleLike(String articleId, String userId) {
LikeArticle likeArticle;
if (redisTemplate.hasKey("LikeArticle::" + articleId + '-' + userId)){
likeArticle = (LikeArticle) redisTemplate.opsForValue().get("LikeArticle::" + articleId + '-' + userId);
}
else {
likeArticle = likeArticleRepository.findLikeArticle(articleId, userId);
}
if (likeArticle != null){
redisTemplate.opsForValue().set("LikeArticle::" + articleId + '-' + userId, likeArticle, 1, TimeUnit.HOURS);
return likeArticle.getIsLike().equals(LikeEnum.LIKE.getCode());
}
else return false;
}
更新点赞信息到数据库
同样使用定时任务进行更新,这里只提供一个方法。
@Override
/**
* 从redis更新帖子点赞到数据库
*/
@Transactional
public void updateLikeArticleDatabase() {
// 1.找到所有有关收藏的key
Set<String> likeArticleKeys = redisTemplate.keys("LikeArticle::*");
// 2.保存数据到数据库并清除redis中数据
for (String likeArticleKey : likeArticleKeys){
LikeArticle likeArticle = (LikeArticle) redisTemplate.opsForValue().get(likeArticleKey);
likeArticle = likeArticleRepository.save(likeArticle);
// 注意redis中的数据没有主键,必须存一次数据库有了主键后再存redis
redisTemplate.opsForValue().set(likeArticleKey, likeArticle, redisTemplate.getExpire(likeArticleKey), TimeUnit.SECONDS);
// redisTemplate.delete(likeArticleKey);
}
return;
}
定时任务
使用Quartz作为定时任务的框架
pom.xml
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
Quartz配置类
@Configuration
public class QuartzConfig {
private static final String BBS_TASK_IDENTITY = "BBSTaskQuartz";
@Bean
public JobDetail quartzDetail(){
return JobBuilder.newJob(BBSTask.class).withIdentity(BBS_TASK_IDENTITY).storeDurably().build();
}
@Bean
public Trigger quartzTrigger(){
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
// .withIntervalInSeconds(10) //设置时间周期单位秒
.withIntervalInSeconds(15)//15秒执行一次
.repeatForever();
return TriggerBuilder.newTrigger().forJob(quartzDetail())
.withIdentity(BBS_TASK_IDENTITY)
.withSchedule(scheduleBuilder)
.build();
}
}
使用定时任务
新建一个叫task的包,建一个BBSTask类来进行定时任务,里面调用帖子、评论、点赞、收藏、关注等有关缓存更新到数据库的方法:
@Slf4j
public class BBSTask extends QuartzJobBean {
@Autowired
private ArticleServiceImpl articleService;
@Autowired
private CommentServiceImpl commentService;
@Autowired
private LikeServiceImpl likeService;
@Autowired
private CollectServiceImpl collectService;
@Autowired
private AttentionServiceImpl attentionService;
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) {
log.info("BBSTask-------- {}", sdf.format(new Date()));
articleService.updateArticleDatabase();
commentService.updateCommentDatabase();
likeService.updateLikeArticleDatabase();
likeService.updateLikeCommentDatabase();
collectService.updateCollectDatabase();
attentionService.updateAttentionDatabase();
}
}
Quartz了解不太多,可能有什么写的不好的,欢迎批评指正。
到这里,小程序的整个项目就说的差不多了,第一次写这样的文章不太有经验,有些地方可能说的不太清楚,详细的项目源码可以移步github:桂香驿站。
上一篇:springboot+jpa+redis+quzartz+elasticsearch实现微信论坛小程序(四)
网友评论