目录

一、干了什么?

二、SpringBoot 如何执行定时任务

1.适用情景

2.动态——基于接口(SchedulingConfigurer)实现定时任务

step1:把任务执行周期存储到数据库

step2:添加pom.xml配置信息(这个之前项目配过就不用了)

step3:配置数据源(配过的就不用再配了)

step4:创建定时器


一、干了什么?

六月初了,马上要到项目答辩。

现在进行功能的进一步完善。因为做的是信息办数据整理系统,所以信息系统的数据需要及时备份。

目前的计划是定时备份。这里我负责的是创建定时任务。然后调用数据库备份方法。

因为是springboot框架,最终使用的是动态基于接口的方法。下面讲一下是怎么做的。

二、SpringBoot 如何执行定时任务

1.适用情景

一天一次,一周一次,一月一次,一年一次,做日报,周报,月报,年报的统计,以及信息提醒,等,spring boot 提供了三种实现定时任务实现方式。

  • 一、静态——基于注解(@Scheduled)
  • 二、动态——基于接口(SchedulingConfigurer)
  • 三、基于注解设定多线程定时任务

几种方法分析:

序号

方式

优点

缺点

1

静态——基于注解(@Scheduled)

@Scheduled 注解很方便,默认为单线程

①开启多个任务时,任务的执行时机会受上一个任务执行时间的影响

②修改定时时间时需要重启项目

2

动态——基于接口(SchedulingConfigurer)

①不需要重启项目就能够生效

②把cron表达式持久化到数据库

①如果在数据库修改时格式出现错误,则定时任务会停止,即使重新修改正确;此时只能重新启动项目才能恢复


3

基于注解设定多线程定时任务

①多个任务之间的多线程可以配置线程池解决

②单任务多线程可以使用@Async解决,可以直接指定线程池@Async("taskExecutor")

@Async参考

2.动态——基于接口(SchedulingConfigurer)实现定时任务

step1:把任务执行周期存储到数据库

代码如下(创建cron表,插入第一条任务执行周期为5ms):

DROP TABLE IF EXISTS cron;
CREATE TABLE cron  (
  cron_id VARCHAR(30) NOT NULL PRIMARY KEY,
  cron VARCHAR(30) NOT NULL  
);
 
INSERT INTO cron VALUES ('1', '0/5 * * * * ?');

step2:添加pom.xml配置信息(这个之前项目配过就不用了)

代码如下:

<dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
</dependency>

<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
</dependency>

step3:配置数据源(配过的就不用再配了)

代码如下:

spring.datasource.dynamic.datasource.student.url=jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.dynamic.datasource.student.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.dynamic.datasource.student.username=root
spring.datasource.dynamic.datasource.student.password=xxx

step4:创建定时器

4.1 创建Cron类、CronMapper类和CronMapper.xml

Cron类

package com.example.server.domain;

import lombok.Data;

@Data
public class Cron {
    int cronid;
    String cron;
}

CronMapper类

package com.example.server.mapper;


import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface CronMapper {

    String getCron();
}

CronMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.server.mapper.CronMapper" >
    <resultMap id="BaseResultMap" type="com.example.server.domain.Cron" >
        <!--
          WARNING - @mbggenerated
          This element is automatically generated by MyBatis Generator, do not modify.
        -->
        <!--        首先需申明数据库表和domain之间的对应关系-->
        <id column="cron_id" property="cronid" jdbcType="INTEGER" />
        <result column="cron" property="cron" jdbcType="VARCHAR" />
    </resultMap>

    <sql id="Base_Column_List">
        cron_id,cron
    </sql>
    <resultMap id="cronResult" type="java.lang.String">
        <result column="cron" property="cron" jdbcType="VARCHAR" />
    </resultMap>

    <select id="getCron" resultMap="cronResult">
        select cron from cron
    </select>


</mapper>

4.2 在controller层创建类

package com.example.server.controller;


import com.example.server.mapper.CronMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

/**
 * 动态定时任务配置类
 */
@Configuration //标记配置类,兼备Component的效果
@EnableScheduling //开启定时任务
public class SimpleScheduleConfig implements SchedulingConfigurer{

    @Autowired
    CronMapper cronMapper;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar){
        Thread thread = new Thread(){
            @Override
            public void run() {
                super.run();
               
                System.out.println("定时发送线程启动:" + LocalDateTime.now().toLocalTime());
            }
        };

        taskRegistrar.addTriggerTask(
                thread,
                triggerContext -> {
                    //从数据库获取执行周期
                    String cron = cronMapper.getCron();
                    //非空校验
                    if(StringUtils.isEmpty(cron)){
                        //TODO
                    }
                    //返回执行周期
                    //在这里进行备份方法调用
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                }
        );

    }
}

4.2 开启定时任务

添加注释 @EnableScheduling //开启定时任务

package com.example.server;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling //开启定时任务
public class ServerApplication {

    public static void main(String[] args) {
        //SpringApplication.run(ServerApplication.class, args);
        SpringApplication.run(ServerApplication.class, args);
    }

}

完成啦!