更新浏览次数

更新浏览次数

需求

在用户浏览文章时要实现对应文章浏览次数的增加

思路

需要在每次用户浏览博客时更新对应的浏览数即可(查看时,viewCount+1)
直接操作博客表的浏览量的话,在并发量大的情况下会怎样…

  • 1.在应用启动时把博客的浏览量存储到redis中
  • 2.更新浏览量时去更新redis中的数据
  • 3.每隔10分钟把Redis中的浏览量更新到数据库中
  • 4.读取文章浏览量时从redis读取

涉及知识

1.CommandLineRunner实现项目启动时预处理
在SpringBoot应用启动时进行一些初始化操作,需要实现CommandLineRunner接口
把对应的bean注入容器,相关初始化的代码重新到需要重新的方法中
2.redis缓存
3.定时任务

操作

1.在应用启动时把博客的浏览量存储到redis中

@Component
@Slf4j
public class ViewCountRunner implements CommandLineRunner {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private RedisCache redisCache;

    //在程序启动之后,所有Bean都初始化完,自动执行该方法
    @Override
    public void run(String... args) throws Exception {
        //查询博客信息,id viewCount
        List<Article> articles = articleMapper.selectList(null);
        Map<String, Integer> viewCountMaper = articles.stream().collect(Collectors.toMap(article -> article.getId().toString(), article -> article.getViewCount().intValue()));
        //存储到redis中
        redisCache.setCacheMap("article:viewCount",viewCountMaper);
        log.info("浏览量从mysql更新到redis中......");
    }
}

2.更新浏览量时去更新redis中的数据

ArticleController中增加方法更新阅读数

   @PutMapping("/updateViewCount/{id}")
   public ResponseResult updateViewCount(@PathVariable("id") Long id){
          return articleService.updateViewCount(id);
    }

ArticleServiceImpl中实现方法

   @Override
   public ResponseResult updateViewCount(Long id) {
     //更新redis中对应 id的浏览量+1
     redisCache.incrementCacheMapValue("article:viewCount",id.toString(),1);
     return ResponseResult.okResult();
    }

RedisCache中的方法:对redis中的某一个hash值进行递增的操作

 /**
     * 对redis中的某一个hash值进行递增的操作
     */
    public void incrementCacheMapValue(String key,String hKey,int v){
        redisTemplate.boundHashOps(key).increment(hKey, v);
    }

3.每隔10分钟把Redis中的浏览量更新到数据库中

Article中增加构造方法

    public Article(Long id, long viewCount) {
        this.id = id;
        this.viewCount = viewCount;
    }

启动类上加注解@EnableScheduling

@SpringBootApplication
@EnableScheduling
public class SanGengBlogApplication {
    public static void main(String[] args) {
        SpringApplication.run(SanGengBlogApplication.class,args);
    }
}

定时任务中的方法

@Component
public class UpdateViewCountJob {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ArticleService articleService;

    @Scheduled(cron = "0/5 * * * * ?")
    public void updateViewCount(){
        //获取redis中的浏览量
        Map<String, Integer> viewCountMap = redisCache.getCacheMap("article:viewCount");

        List<Article> articles = viewCountMap.entrySet()
                .stream()
                .map(entry -> new Article(Long.valueOf(entry.getKey()), entry.getValue().longValue()))
                .collect(Collectors.toList());
        //更新到数据库中
        articleService.updateBatchById(articles);

    }
}

4.读取文章浏览量时从redis读取

ArticleController中查看详情

 @GetMapping("/{id}")
    public ResponseResult getArticleDetail(@PathVariable("id") Long id){
        return articleService.getArticleDetail(id);
    }

ArticleServiceImpl中实现方法

  @Override
  public ResponseResult getArticleDetail(Long id) {
        //根据id查询文章
        Article article = getById(id);
        
        //从redis中获取viewCount
        Integer viewCount = redisCache.getCacheMapValue("article:viewCount", id.toString());
        article.setViewCount(viewCount.longValue());
        
        //转换成VO
        ArticleDetailVo articleDetailVo = BeanCopyUtils.copyBean(article, ArticleDetailVo.class);
        //根据分类id查询分类名
        Long categoryId = articleDetailVo.getCategoryId();
        Category category = categoryService.getById(categoryId);
        if(category!=null){
            articleDetailVo.setCategoryName(category.getName());
        }
        //封装响应返回
        return ResponseResult.okResult(articleDetailVo);
    }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值