springboot定时任务

文章介绍了如何利用Java的AOP(面向切面编程)和Redis来实现实时记录并更新文章阅读量。通过定义切点注解,当方法被调用时,会记录访问IP并存储到Redis中。定时任务每天凌晨2点执行,将Redis中的阅读量汇总到数据库,防止重复计数。
摘要由CSDN通过智能技术生成

文章阅读量的更新(结合redis的使用)

注解的配置(切点)

import java.lang.annotation.*;

/**
 * 这个注解加载啥地方啥地方就会进行扩展,这是个切点
 * 加强为切面
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface QuestionView {
    /**
     * 描述
     */
    String description()  default "";
}

切面:

import com.oppo.crm.csc.extension.tally.financiala.infrastructure.utils.IpUtils;
import com.oppo.crm.csc.extension.tally.financiala.infrastructure.utils.RedisUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 * 将访问该问题的 ip存入 redis 中, key为文章id,value为ip地址
 */
@Aspect
@Configuration
public class PageViewAspect {

    Logger log= LoggerFactory.getLogger(IpUtils.class);

    @Resource
    private RedisUtils redisUtil;

    /**
     * 切入点
     */
    @Pointcut("@annotation(com.oppo.crm.csc.extension.tally.financiala.application.common.anno.QuestionView)")
    public void PageViewAspect() {

    }

    /**
     * 切入处理
     * @param joinPoint
     * @return
     */
    @Around("PageViewAspect()")
    public  Object around(ProceedingJoinPoint joinPoint) {
        Object[] object = joinPoint.getArgs();
        Object articleId = object[0];
        log.info("articleId:{}", articleId);
        Object obj = null;
        try {
            String ipAddr = IpUtils.getIpAddr();
            log.info("ipAddr:{}", ipAddr);
            String key = "articleId_" + articleId;
            // 浏览量存入redis中
            Long num = redisUtil.add(key,ipAddr);
            if (num == 0) {
                log.info("该ip:{},访问的浏览量已经新增过了", ipAddr);
            }
            obj = joinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return obj;
    }
}

定时器:

import com.oppo.crm.csc.extension.tally.financiala.application.converter.UpdateQuestionTDConvert;
import com.oppo.crm.csc.extension.tally.financiala.application.dto.createquestion.PaginatedQueriesResponseDTO;
import com.oppo.crm.csc.extension.tally.financiala.application.dto.createquestion.SearchQuestionResultDTO;
import com.oppo.crm.csc.extension.tally.financiala.application.dto.createquestion.UpdateQuestionRequestDTO;
import com.oppo.crm.csc.extension.tally.financiala.application.dto.createquestion.UpdateQuestionResultDTO;
import com.oppo.crm.csc.extension.tally.financiala.application.service.QuestionService;
import com.oppo.crm.csc.extension.tally.financiala.infrastructure.utils.RedisUtils;
import com.oppo.crm.csc.extension.tally.financiala.presentation.vo.createquestion.responseparam.QuestionVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 定时任务,更新文章阅读量
 */
@Component
//@EnableScheduling
public class ArticleViewTask {

    Logger log= LoggerFactory.getLogger(ArticleViewTask.class);

    @Resource
    private RedisUtils redisUtil;

    @Resource
    QuestionService questionService;


	// 每天凌晨2点执行
    // 同一个ip地址 在访问同一个问题时候,每天只算一个阅读量
    @Scheduled(cron = "0 0 2 * * ? ")
    @Transactional
    public void createHyperLog() {
        log.info("浏览量入库开始");

        PaginatedQueriesResponseDTO paginatedQueriesResponseDTO = questionService.searchAllOnlyQuestion();
        List<QuestionVO> questionVOList = paginatedQueriesResponseDTO.getQuestionVOList();
        List<Long> list=new ArrayList<>();
        for (QuestionVO questionVO : questionVOList) {
            Long id = questionVO.getId();
            list.add(id);
        }

        list.forEach(articleId ->{
            // 获取每一篇文章在redis中的浏览量,存入到数据库中
            String key  = "articleId_"+articleId;
            Long view = redisUtil.size(key);
            if(view>0){
                // 获取到当前问题id对应的阅读量
                SearchQuestionResultDTO searchQuestionResultDTO = questionService.searchByQuestionId(articleId);
                Integer views = Integer.parseInt(String.valueOf(view))  + searchQuestionResultDTO.getViewTotal();
                 // 设置新的阅读量
                searchQuestionResultDTO.setViewTotal(views);
                UpdateQuestionRequestDTO updateQuestionRequestDTO = UpdateQuestionTDConvert.INSTANCE.convert(searchQuestionResultDTO);
                // 更新
                UpdateQuestionResultDTO updateQuestionResultDTO = questionService.updateQuestionView(updateQuestionRequestDTO);
                if (updateQuestionResultDTO.getSuccess()) {
                    log.info("数据库更新后的浏览量为:{}", views);
                    redisUtil.delete(key);
                }
            }
        });
        log.info("浏览量入库结束");
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值