利用Quartz把数据库数据定时更新同步到Redis

利用Quartz把数据库数据定时更新同步到Redis

  • Job :表示一个工作,要执行的具体内容,此接口只有一个方法
      void execute(JobExecutionContext context)
      public class quartzJob implements Job{
       	@Override
         	 public void execute(JobExecutionContext jobExecutionContext) throws 	JobExecutionException {
             .......
          }
      }
  • JobDetail :表示一个具体的可执行的调度程序,job是这个可执行程调读程序所要执行的内容,另外JobDeail还包含了这个任务调读的方案和策略(执行job的调度程序,用于定义任务的实例)
  • jobBuilder:用于定义/构建JobDetail实例
·      // 3.创建JobDetail
      JobDetail jobDetail = JobBuilder.newJob(quartzJob.class)
              .withDescription("this is a ram job") //job的描述
              .withIdentity("ramJob", "ramGroup") //job 的name和group
              .build();

newJob 是JobBuilder静态导入的方法
在这里插入图片描述

  //jobDetail信息
  JobDetail 'group1.myJob':  jobClass: 'emergency.prewarning.biz.quartz.entity.quartz.entity.min5RunTask concurrentExectionDisallowed: true persistJobDataAfterExecution: false isDurable: false requestsRecovers: false
  • Trigger :触发器 代表一个调度参数的配置,什么时候去调,编写一个触发器,当进行delete,update时触发
  • TriggerBuilder:用于定义/构建Trigger触发器
      // 4.创建Trigger触发器
      Trigger trigger = TriggerBuilder
          .newTrigger()
          .withIdentity("ramTrigger", "ramTriggerGroup")
          .startAt(new Date()) // 默认当前时间启动
          .withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")) // 两秒执行一次
          .build();
- CronScheduleBuilder.cronSchedule(cron):传入cron表达式规定任务执行时间
      // 表达式调度构建器(即任务执行的时间)
  CronScheduleBuilder scheduleBuilder =CronScheduleBuilder.cronSchedule(cronExpression);
  • Scheduler:代表一个调度容器,一个调度容器中可以注册多个JobDetail和Trigger。当Trigger与JobDetail组合 ,就可以被Scheduler容器调度了(与调度程序交互的主要API)
//创建方式1:scheduler
  Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); 
  //创建方式2:scheduler
  SchedulerFactory sfact = new StdSchedulerFactory();
  Scheduler scheduler = sfact.getScheduler();
  scheduler.scheduleJob(jobDetail, trigger);

依赖

   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--postgresql-->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.2.8</version>
        </dependency>

        <!-- mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.2</version>
        </dependency>

        <!--Excel-->
        <dependency>
            <groupId>org.jeecgframework</groupId>
            <artifactId>autopoi-web</artifactId>
            <version>1.0.3</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-codec</groupId>
                    <artifactId>commons-codec</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--quartz-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>

        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--redis要依赖此包-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.20</version>
        </dependency>

对象序列化

private static final long serialVersionUID = 1L;

JAVA序列化的机制是通过判断类的serialVersionUID来验证的版本一致的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID于本地相应实体类的serialVersionUID进行比较。如果相同说明是一致的,可以进行反序列化,否则会出现反序列化版本一致的异常,即是InvalidClassException3。

Mybatis-plus自动生成mysql的UUId

1.修改entity的代码如上,生成getter and setter

2.修改数据库的数据类型为varchar(36)

/**
 * @Description: 定时任务在线管理
 * @Author: jeecg-boot
 * @Date: 2019-01-02
 * @Version: V1.0
 */
@Data
@TableName("sys_quartz_job")
public class QuartzJob implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * id
     */
    @TableId(type = IdType.UUID)
    private String id;
    /**
     * 创建人
     */
    private String createBy;
    /**
     * 创建时间
     */
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") //出参时间格式
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") //传入参数时间格式
    private java.util.Date createTime;
    /**
     * 删除状态
     */
    private Integer delFlag;
    /**
     * 修改人
     */
    private String updateBy;
    /**
     * 修改时间
     */
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private java.util.Date updateTime;
    /**
     * 任务类名
     */
    @Excel(name = "任务类名", width = 40)
    private String jobClassName;
    /**
     * cron表达式
     */
    @Excel(name = "cron表达式", width = 30)
    private String cronExpression;
    /**
     * 参数
     */
    @Excel(name = "参数", width = 15)
    private String parameter;
    /**
     * 描述
     */
    @Excel(name = "描述", width = 40)
    private String description;
    /**
     * 状态 0正常 -1停止
     */
    @Excel(name = "状态", width = 15)
    private Integer status;

}
@Excel
		<dependency>
            <groupId>org.jeecgframework</groupId>
            <artifactId>autopoi-web</artifactId>
            <version>1.0.3</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-codec</groupId>
                    <artifactId>commons-codec</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    

定时任务在线管理

/**
 * @Description: 定时任务在线管理
 */
@Slf4j
@Service
public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob> implements IQuartzJobService {
    @Resource
    private QuartzJobMapper quartzJobMapper;
    @Autowired
    private Scheduler scheduler;

    /**
     * Job工作任务,反射进行实例化,同new对象
     * @param classname
     * @return
     * @throws Exception
     */
    private static Job getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (Job) class1.newInstance();
    }

    /**
     * 数据库查找工作任务名
     * @param jobClassName
     * @return
     */
    @Override
    public List<QuartzJob> findByJobClassName(String jobClassName) {
        return quartzJobMapper.findByJobClassName(jobClassName);
    }

    /**
     * 保存&启动定时任务
     */
    @Override
    public boolean saveAndScheduleJob(QuartzJob quartzJob) {
        if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
            // 定时器添加
            this.schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
        }
        // DB设置修改
        quartzJob.setDelFlag(CommonConstant.DEL_FLAG_0);
        return this.save(quartzJob);
    }

    /**
     * 恢复定时任务
     */
    @Override
    public boolean resumeJob(QuartzJob quartzJob) {
        schedulerDelete(quartzJob.getJobClassName().trim());
        schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
        quartzJob.setStatus(CommonConstant.STATUS_NORMAL);
        return this.updateById(quartzJob);
    }

    /**
     * 编辑&启停定时任务
     *
     * @throws SchedulerException
     */
    @Override
    public boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException {
        if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
            schedulerDelete(quartzJob.getJobClassName().trim());
            schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
        } else {
            scheduler.pauseJob(JobKey.jobKey(quartzJob.getJobClassName().trim()));
        }
        return this.updateById(quartzJob);
    }

    /**
     * 删除&停止删除定时任务
     */
    @Override
    public boolean deleteAndStopJob(QuartzJob job) {
        schedulerDelete(job.getJobClassName().trim());
        boolean ok = this.removeById(job.getId());
        return ok;
    }

    /**
     * 添加定时任务
     *
     * @param jobClassName
     * @param cronExpression
     * @param parameter
     */
    private void schedulerAdd(String jobClassName, String cronExpression, String parameter) {
        try {
            // 启动调度器
            scheduler.start();

            // 构建job信息
            JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName).usingJobData("parameter", parameter).build();

            // 表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

            // 按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName).withSchedule(scheduleBuilder).build();

            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            throw new JeecgBootException("创建定时任务失败", e);
        } catch (RuntimeException e) {
            throw new JeecgBootException(e.getMessage(), e);
        } catch (Exception e) {
            throw new JeecgBootException("后台找不到该类名:" + jobClassName, e);
        }
    }

    /**
     * 删除定时任务
     *
     * @param jobClassName
     */
    public void schedulerDelete(String jobClassName) {
        try {
            scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName));//停止触发器
            scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName));//删除触发器
            scheduler.deleteJob(JobKey.jobKey(jobClassName));//删除任务
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new JeecgBootException("删除定时任务失败");
        }
    }

线程任务服务

0 /30 * * * ? 和 0 0/30 * * *?区别

  • 0 /30 * * * ? 代表从项目启动后开始计算 例: 17:24启动项目 那么会在17:54开始执行
  • 0 0/30 * * *? 代表本地时间开始计算 例: 17:24启动项目 那么会在17:30开始执行
@Service
public class CustomMultiThreadingService {
    @Resource
    private IQuartzJobService quartzJobService;

    /**
     * @Description:30min数据同步
     */
    public void min30RunTask() {
        QuartzJob quartzJob = new QuartzJob();
        quartzJob.setStatus(0);            //设置为正常
        quartzJob.setCreateBy("1");        //创建人
        quartzJob.setCronExpression("0 /30 * * *  ?"); //cron表达式
        quartzJob.setId("1"); 

      quartzJob.setJobClassName("emergency.prewarning.biz.quartz.entity.Min30RunTaskQuartz");//job任务路径
            quartzJob.setParameter("Min30RunTaskQuartz");
            quartzJobService.resumeJob(quartzJob); //恢复定时任务
        }
    
    }

Job工作任务

@Slf4j
@DisallowConcurrentExecution //禁止并发执行
public class min5RunTask implements Job {

    @Resource
    private QuartzCommonService quartzCommonService;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        quartzCommonService.min5RunTask();
    }
}

判断数据库中是否有该表

@Slf4j
@Service
public class QuartzCommonServiceimpl implements QuartzCommonService {

    @Resource
    private SelectTableNameMapper selectTableNameMapper;

    @Resource
    private RedisUtil redisUtil;

    private int ret = 0;

    @Override
    public void min5RunTask() {
        System.out.println("*************2分钟同步一次开始**************");
        ret = selectTableName("fruits");
        if (ret > 0) {
            //判断redis是否有该表
            List<Map<String, Object>> fruits = selectTableNameMapper.queryFruits();
            if (fruits.size() > 0) {
                redisUtil.del("fruits"); //先删除redis中该表数据
                redisUtil.set("fruits", fruits); //再把该表存入redis中
            }
        }
        System.out.println("*************2分钟同步一次结束**************");
    }

    public int selectTableName(String tableName) {
        return selectTableNameMapper.queryTable(tableName);
    }
}

ApplicationRunner

开发过程中,容器启动的时候需要去执行一些工程

@Component 普通的pojo实例化到spring容器中,相当于配置文件中的组件

@Component
public class QuartzController implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 30min数据同步redis
        customMultiThreadingService.min30RunTask();
        // 10min数据同步redis
        customMultiThreadingService.min10RunTask();
        // 5min数据同步redis
        customMultiThreadingService.min5RunTask();
        // 10s数据同步redis
        customMultiThreadingService.s10RunTask();
    }
}

Quartz默认提供12张表

  • qrtz_blob_triggers : 以Blob 类型存储的触发器。
  • qrtz_calendars :存放日历信息, quartz可配置一个日历来指定一个时间范围。
  • qrtz_cron_triggers :存放cron类型的触发器。
  • qrtz_fired_triggers :存放已触发的触发器
  • qrtz_job_details :存放一个jobDetail信息
  • qrtz_job_listeners :job监听器。
  • qrtz_locks :存储程序的悲观锁的信息(假如使用了悲观锁)。
  • qrtz_paused_trigger_graps :存放暂停掉的触发器
  • qrtz_scheduler_state:调度器状态。
  • qrtz_simple_triggers:简单触发器的信息
  • qrtz_trigger_listeners:触发器监听器。
  • qrtz_triggers:触发器的基本信息。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值