程序员的资源宝库

网站首页 > gitee 正文

博客项目学习笔记十:缓存实现文章阅读量

sanyeah 2024-04-03 18:36:26 gitee 5 ℃ 0 评论

博客项目目录: 请戳这里

准备

需求:进入文章详情页之后,阅读量加1,并且通过缓存实现,定时将缓存中的阅读量同步到数据库
分析:首先查看缓存里有没有文章阅读信息,如果有,直接缓存加1;如果没有,则数据库里对应数据加1,然后同步到缓存。最后设置一个定时任务,每分钟从缓存将阅读量同步到数据库。

1.PostController设置文章阅读量

2.PostService定义相应的接口

public interface PostService extends IService<Post> {

    void putViewCount(PostVo vo);
}

3.Impl层进行实现

 /**
     * 设置文章阅读量
     * @param vo
     */
    @Override
    public void putViewCount(PostVo vo) {
        String key = "rank:post:" + vo.getId();
        // 1、从缓存中获取viewcount
        Integer viewCount = (Integer) redisUtil.hget(key, "post:viewCount");

        // 2、如果没有,就先从实体里面获取,再加一
        if(viewCount != null) {
            vo.setViewCount(viewCount + 1);
        }
        else {
            vo.setViewCount(vo.getViewCount() + 1);
        }

        // 3、同步到缓存里面
        redisUtil.hset(key, "post:viewCount", vo.getViewCount());
    }

4.启动项目,进行测试

可以发现,每刷新一次浏览器,阅读量加1

5.实现定时任务

步骤:

  1. 获取缓存中含有阅读量的文章id集合
  2. 根据id查找需要更新的文章
  3. 如果同步成功,清空缓存里的阅读量

代码:

@Component
public class ViewCountSyncTask {

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    PostService postService;


    @Scheduled(cron = "0/5 * * * * *") //每5秒同步
    public void task() {

        Set<String> keys = redisTemplate.keys("rank:post:*");

        //获取缓存中含有阅读量的文章id集合
        List<String> ids = new ArrayList<>();
        for (String key : keys) {
            if(redisUtil.hHasKey(key, "post:viewCount")){
                ids.add(key.substring("rank:post:".length()));
            }
        }

        if(ids.isEmpty()) return;

        // 根据id查找需要更新的文章
        List<Post> posts = postService.list(new QueryWrapper<Post>().in("id", ids));

        posts.stream().forEach((post) ->{
            Integer viewCount = (Integer) redisUtil.hget("rank:post:" + post.getId(), "post:viewCount");
            post.setViewCount(viewCount);
        });

        if(posts.isEmpty()) return;

        boolean isSucc = postService.updateBatchById(posts);

        //如果同步成功,清空缓存里的阅读量
        if(isSucc) {
            ids.stream().forEach((id) -> {
                redisUtil.hdel("rank:post:" + id, "post:viewCount");
                System.out.println(id + "---------------------->同步成功");
            });
        }
    }

}

在启动类加以下注解:

@EnableScheduling

原来的阅读量:

6.重新启动项目,进入文章,刷新浏览器

结果表明,阅读量成功从缓存同步到数据库


参考资料:

https://github.com/MarkerHub/eblog

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表