如何利用spring定时器实现分时统计排行

spring定时器入门

配置

  • 在启动类上贴上注解@EnableScheduling 开启定时事务,默认是不开启的

定时器使用模板套路

  • 自建一个job包,统一存放这些定时器类
  • cron表达式自动生成链接:https://cron.qqe2.com/
@Component
public class StrategyRankStatisJob {
    /**
     * Cron表达式是一个字符串.字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式:
     * (1) Seconds Minutes   Hours DayofMonth Month    DayofWeek  Year
     * 秒       分       时      几号      月       周几       年
     * (2) Seconds Minutes   Hours DayofMonth Month    DayofWeek   spring支持
     * 秒       分       时      几号      月       周几
     */

    //    定时任务标签, cron:任务计划表达式
    @Scheduled(cron = "0/10 * * * * ?")
    public void doWork() {
			//这里进行定时要执行的操作
    }

    
}

实现分时统计排行榜

分析与效果图

  • 要实现一个排行榜,如果数据库表数据过多,查询后再排序得出的排行榜数据,这样的查询效果会特别低!!!
  • 如果使用分时统计的方式 大大提高了查询效率
  • 分时统计:从对应的表查询出数据,将这些数据存放在分时统计表中,类似于一个临时表,以后想要拿排行榜的数据,直接从这个表拿即可,查询效率将会特别得快!
  • 使用定时器的方式,设置每隔一段时间,分时统计表将会从所需的数据库表中获得数据存放进来,这样即可保证页面的排行榜数据是实时的(定时更新过的)
    在这里插入图片描述
  • 效果图
  • 主题推荐模块,直接显示后端传过来的排行榜数据
  • 黑体的是攻略主题 , 灰色部分的是此主题对应的目的地名集合
    在这里插入图片描述

准备工作

数据库表结构

  • 攻略明细数据表(分时统计表从这里拿所需的数据)
    在这里插入图片描述

  • 分时统计表

  • 必须要有statis_time字段,用于表示统计录入时间,便于作为用户查询条件拿到最新的数据!
    在这里插入图片描述

实体类

  • 攻略明细实体类,画红线才是此演示所需属性
    在这里插入图片描述
  • 分时统计表对应的实体类
  • 因为此演示中,分时统计表中的目的地名会有多个值,对应实体类destNames和destIds, 会显示成类似于1,2,3,4,所以定义了一个pareseXXX()方法,将这些字符串分割成集合,便于后续封装数据操作
@Getter
@Setter
@ToString
@TableName("strategy_theme_rank")
public class StrategyThemeRank extends BaseDomain {
    private Long themeId;
    private String themeName;
    private String destNames;
    private String destIds;
    private Long count;
    private Date statisTime;

    public List<Long> parseDestIds(){
        List<Long> ids = new ArrayList<>();
        if(StringUtils.hasLength(destIds)){
            String[] split = destIds.split(",");
            if(split != null && split.length > 0){
                for (int i = 0;i <split.length; i++) {
                    ids.add(Long.parseLong(split[i]));
                }
            }
        }
        return ids;
    }
    public List<String> parseDestNames(){
        List<String> names = new ArrayList<>();
        if(StringUtils.hasLength(destNames)){
            String[] split = destNames.split(",");
            if(split != null && split.length > 0){
                for (int i = 0;i <split.length; i++) {
                    names.add(split[i]);
                }
            }
        }
        return names;
    }
}

vo类

  • 真正要返回给前端的数据
  • 实现流程就是,先从攻略明细表拿到所需的数据放进分时统计表中,在此表再将数据封装进vo里返回给前端
  • 所以前端是直接从分时统计表拿数据,这些数据封装成vo数据
  • ps: 有些情况可以无需用到vo类封装数据,直接拿分时统计表对应的数据就可以返回给页面了!(具体看需求)
    在这里插入图片描述

分时统计 实现流程

控制器层

  • 注入分时统计表的业务层对象
    在这里插入图片描述

  • 控制器接口直接调用此业务层对象方法,将数据封装成vo数据返回给前端即可!
    在这里插入图片描述

业务层实现方法

  • 通过条件statis_time(分时统计表最新的数据)最大值的数据,并用count(热门量)倒序分组,获取分时统计表内的数据,即可拿到排行榜的数据
  • 将数据封装成vo类型数据给前端即可
    在这里插入图片描述

定时器操作

  • 引入攻略明细表分时统计表的业务层对象
  • 将前端页面所需的攻略主题排行榜数据,从攻略明细表拿到后装进分时统计表
  • 因为是排行榜的数据,所以需要对攻略明细表 根据对数据的需要对相关字段进行分组和聚合函数操作,按热度量进行倒序排序,并拿前10名数据(即最热门的前10名数据),
  • 通过cron表达式,设置每隔多久会进行一次操作(更新排行榜数据)
@Component
public class StrategyThemeRankStatisJob {
    @Autowired
    private IStrategyService strategyService;
    @Autowired
    private IStrategyThemeRankService strategyThemeRankService;

    @Scheduled(cron = "0/10 * * * * ?")
    public void doWork() {
        strategyThemeRankService.remove(new QueryWrapper<>());
        /**
         * select theme_id,theme_name,GROUP_CONCAT(dest_name) name,GROUP_CONCAT(dest_id) ids,count(id) count
         * from strategy group by theme_id,theme_name
         * order by count desc limit 10
         */
        Date date = new Date();
        List<StrategyThemeRank> rankList = new ArrayList<>();

        QueryWrapper<Strategy> wrapper = new QueryWrapper<>();
        wrapper.select("theme_id, theme_name, GROUP_CONCAT(DISTINCT dest_name) name,GROUP_CONCAT(dest_id) ids,count(id) count")
                .groupBy("theme_id")
                .orderByDesc("count")
                .last("limit 10");
        List<Map<String, Object>> maps = strategyService.listMaps(wrapper);

        for (Map<String,Object> map : maps){
            StrategyThemeRank rank = new StrategyThemeRank();
            rank.setStatisTime(date);
            rank.setCount(Long.parseLong(map.get("count").toString()));
            rank.setDestIds(map.get("ids").toString());
            rank.setDestNames(map.get("name").toString());
            rank.setThemeId(Long.parseLong(map.get("theme_id").toString()));
            rank.setThemeName(map.get("theme_name").toString());
            rankList.add(rank);
        }

        strategyThemeRankService.saveBatch(rankList);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值