zoukankan      html  css  js  c++  java
  • SpringBoot-Quartz

    一、新建一个springboot工程,并添加依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>name.ealenxie</groupId>
        <artifactId>SpringBoot-Quartz</artifactId>
        <version>1.0</version>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.6.RELEASE</version>
        </parent>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
            <dependency>
                <groupId>org.mariadb.jdbc</groupId>
                <artifactId>mariadb-java-client</artifactId>
                <version>2.5.2</version>
            </dependency>
            <dependency> <!--quartz依赖-->
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>2.2.3</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
            </dependency>
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz-jobs</artifactId>
                <version>2.2.3</version>
            </dependency>
            <!--日志 start-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.25</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>1.7.25</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-simple</artifactId>
                <version>1.7.25</version>
                <scope>test</scope>
            </dependency>
            <!--日志end-->
        </dependencies>
    </project>

    二、配置文件application.yml

    quartz:
      enabled: true
    server:
      port: 9090
    spring:
      application:
        name: Spring-Quartz-Scheduler                                       #Quartz调度中心
      datasource:
        url: jdbc:mariadb://localhost:3306/model
        username: root
        password: 123
        tomcat:
          initialSize: 20
          maxActive: 100
          maxIdle: 100
          minIdle: 20
          maxWait: 10000
          testWhileIdle: true
          testOnBorrow: false
          testOnReturn: false

    quartz.properties

    #ID设置为自动获取 每一个必须不同 (所有调度器实例中是唯一的)
    org.quartz.scheduler.instanceId=AUTO
    #指定调度程序的主线程是否应该是守护线程
    org.quartz.scheduler.makeSchedulerThreadDaemon=true
    #ThreadPool实现的类名
    org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
    #ThreadPool配置线程守护进程
    org.quartz.threadPool.makeThreadsDaemons=true
    #线程数量
    org.quartz.threadPool.threadCount:20
    #线程优先级
    org.quartz.threadPool.threadPriority:5
    #数据保存方式为持久化
    org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
    #StdJDBCDelegate说明支持集群
    org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    #quartz内部表的前缀
    org.quartz.jobStore.tablePrefix=QRTZ_
    #是否加入集群
    org.quartz.jobStore.isClustered=true
    #容许的最大作业延长时间
    org.quartz.jobStore.misfireThreshold=25000

    三、Quartz核心配置

    package com.ealen.config;
    
    import org.quartz.spi.JobFactory;
    import org.quartz.spi.TriggerFiredBundle;
    import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
    import org.springframework.beans.factory.config.PropertiesFactoryBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.scheduling.quartz.SchedulerFactoryBean;
    import org.springframework.scheduling.quartz.SpringBeanJobFactory;
    
    import javax.sql.DataSource;
    import java.io.IOException;
    import java.util.Properties;
    
    /**
     * Quartz的核心配置类
     */
    @Configuration
    public class ConfigureQuartz {
    
        //配置JobFactory
        @Bean
        public JobFactory jobFactory(ApplicationContext applicationContext) {
            AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
            jobFactory.setApplicationContext(applicationContext);
            return jobFactory;
        }
    
        /**
         * SchedulerFactoryBean这个类的真正作用提供了对org.quartz.Scheduler的创建与配置,并且会管理它的生命周期与Spring同步。
         * org.quartz.Scheduler: 调度器。所有的调度都是由它控制。
         *
         * @param dataSource 为SchedulerFactory配置数据源
         * @param jobFactory 为SchedulerFactory配置JobFactory
         */
        @Bean
        public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource, JobFactory jobFactory) throws IOException {
            SchedulerFactoryBean factory = new SchedulerFactoryBean();
            //可选,QuartzScheduler启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录
            factory.setOverwriteExistingJobs(true);
            factory.setAutoStartup(true); //设置自行启动
            factory.setDataSource(dataSource);
            factory.setJobFactory(jobFactory);
            factory.setQuartzProperties(quartzProperties());
            return factory;
        }
    
        //从quartz.properties文件中读取Quartz配置属性
        @Bean
        public Properties quartzProperties() throws IOException {
            PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
            propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
            propertiesFactoryBean.afterPropertiesSet();
            return propertiesFactoryBean.getObject();
        }
    
        //配置JobFactory,为quartz作业添加自动连接支持
        public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
                ApplicationContextAware {
            private AutowireCapableBeanFactory beanFactory;
    
            @Override
            public void setApplicationContext(final ApplicationContext context) {
                beanFactory = context.getAutowireCapableBeanFactory();
            }
    
            @Override
            protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
                final Object job = super.createJobInstance(bundle);
                beanFactory.autowireBean(job);
                return job;
            }
        }
    
    }

    四、Entity类

    package com.ealen.entity;
    
    import lombok.Data;
    import lombok.experimental.Accessors;
    
    import javax.persistence.*;
    import java.io.Serializable;
    
    /**
     * 这里个人示例,可自定义相关属性
     */
    @Entity
    @Table(name = "JOB_ENTITY")
    @Data
    @Accessors(chain = true)
    public class JobEntity implements Serializable {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String name;          //job名称
        private String jobGroup;      //job组名
        private String cron;          //执行的cron
        private String parameter;     //job的参数
        private String description;   //job描述信息
        private String vmParam;       //vm参数
        private String jarPath;       //job的jar路径
        private String status;        //job的执行状态,这里我设置为OPEN/CLOSE且只有该值为OPEN才会执行该Job
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getJobGroup() {
            return jobGroup;
        }
    
        public void setJobGroup(String jobGroup) {
            this.jobGroup = jobGroup;
        }
    
        public String getCron() {
            return cron;
        }
    
        public void setCron(String cron) {
            this.cron = cron;
        }
    
        public String getParameter() {
            return parameter;
        }
    
        public void setParameter(String parameter) {
            this.parameter = parameter;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        public String getVmParam() {
            return vmParam;
        }
    
        public void setVmParam(String vmParam) {
            this.vmParam = vmParam;
        }
    
        public String getJarPath() {
            return jarPath;
        }
    
        public void setJarPath(String jarPath) {
            this.jarPath = jarPath;
        }
    
        public String getStatus() {
            return status;
        }
    
        public void setStatus(String status) {
            this.status = status;
        }
    }

    五、实现job接口 

    Job可以理解为就是一个工作任务,代码中就是一个实现了org.quartz.Job或org.quartz.StatefulJob接口的java类。当Scheduler决定运行Job时,execute()方法就会被执行。
      具体可以干啥:
       1、每天定时发送系统邮件
       2、在指定的时刻发送一条短信给用户
       3、执行完A任务后希望B任务在10秒后执行
      总结就是任何java能做的任务都可以成为一个job。

    package com.ealen.job;
    
    import com.ealen.util.StringUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.quartz.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    import java.io.*;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Objects;
    /**
     * :@DisallowConcurrentExecution : 此标记用在实现Job的类上面,意思是不允许并发执行.
     * :注意org.quartz.threadPool.threadCount线程池中线程的数量至少要多个,否则@DisallowConcurrentExecution不生效
     * :假如Job的设置时间间隔为3秒,但Job执行时间是5秒,设置@DisallowConcurrentExecution以后程序会等任务执行完毕以后再去执行,否则会在3秒时再启用新的线程执行
     */
    @DisallowConcurrentExecution
    @Component
    @Slf4j
    public class DynamicJob implements Job {
    
        private static final Logger log = LoggerFactory.getLogger(DynamicJob.class);
    
        /**
         * 核心方法,Quartz Job真正的执行逻辑.
         *
         * @param executorContext executorContext JobExecutionContext中封装有Quartz运行所需要的所有信息
         * @throws JobExecutionException execute()方法只允许抛出JobExecutionException异常
         */
        @Override
        public void execute(JobExecutionContext executorContext) throws JobExecutionException {
            //JobDetail中的JobDataMap是共用的,从getMergedJobDataMap获取的JobDataMap是全新的对象
            JobDataMap map = executorContext.getMergedJobDataMap();
            String jarPath = map.getString("jarPath");
            String parameter = map.getString("parameter");
            String vmParam = map.getString("vmParam");
            log.info("Running Job name : {} ", map.getString("name"));
            log.info("Running Job description : {}", map.getString("jobDescription"));
            log.info("Running Job group: {} ", map.getString("jobGroup"));
            log.info(String.format("Running Job cron : %s", map.getString("cronExpression")));
            log.info("Running Job jar path : {} ", jarPath);
            log.info("Running Job parameter : {} ", parameter);
            log.info("Running Job vmParam : {} ", vmParam);
            long startTime = System.currentTimeMillis();
            if (!StringUtils.isEmpty(jarPath)) {
                File jar = new File(jarPath);
                if (jar.exists()) {
                    ProcessBuilder processBuilder = new ProcessBuilder();
                    processBuilder.directory(jar.getParentFile());
                    List<String> commands = new ArrayList<>();
                    commands.add("java");
                    if (!StringUtils.isEmpty(vmParam)) commands.add(vmParam);
                    commands.add("-jar");
                    commands.add(jarPath);
                    if (!StringUtils.isEmpty(parameter)) commands.add(parameter);
                    processBuilder.command(commands);
                    log.info("Running Job details as follows >>>>>>>>>>>>>>>>>>>>: ");
                    log.info("Running Job commands : {}  ", StringUtil.getListString(commands));
                    try {
                        Process process = processBuilder.start();
                        logProcess(process.getInputStream(), process.getErrorStream());
                    } catch (IOException e) {
                        throw new JobExecutionException(e);
                    }
                } else throw new JobExecutionException("Job Jar not found >>  " + jarPath);
            }
            long endTime = System.currentTimeMillis();
            log.info(">>>>>>>>>>>>> Running Job has been completed , cost time : {}ms
     ", (endTime - startTime));
        }
    
        //记录Job执行内容
        private void logProcess(InputStream inputStream, InputStream errorStream) throws IOException {
            String inputLine;
            String errorLine;
            BufferedReader inputReader = new BufferedReader(new InputStreamReader(inputStream));
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream));
            while (Objects.nonNull(inputLine = inputReader.readLine())) log.info(inputLine);
            while (Objects.nonNull(errorLine = errorReader.readLine())) log.error(errorLine);
        }
    
    }

    六、定义dao接口

    package com.ealen.dao;
    
    import com.ealen.entity.JobEntity;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    
    public interface JobEntityRepository extends JpaRepository<JobEntity, Long> {
    
        JobEntity getById(Integer id);
    
    }

    七、service 服务层

    package com.ealen.service;
    
    import com.ealen.dao.JobEntityRepository;
    import com.ealen.entity.JobEntity;
    import com.ealen.job.DynamicJob;
    import org.quartz.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    
    @Service
    public class DynamicJobService {
    
        @Autowired
        private JobEntityRepository repository;
    
        //通过Id获取Job
        public JobEntity getJobEntityById(Integer id) {
            return repository.getById(id);
        }
    
        //从数据库中加载获取到所有Job
        public List<JobEntity> loadJobs() {
            return repository.findAll();
        }
    
        //获取JobDataMap.(Job参数对象)
        public JobDataMap getJobDataMap(JobEntity job) {
            JobDataMap map = new JobDataMap();
            map.put("name", job.getName());
            map.put("jobGroup", job.getJobGroup());
            map.put("cronExpression", job.getCron());
            map.put("parameter", job.getParameter());
            map.put("jobDescription", job.getDescription());
            map.put("vmParam", job.getVmParam());
            map.put("jarPath", job.getJarPath());
            map.put("status", job.getStatus());
            return map;
        }
    
        //获取JobDetail,JobDetail是任务的定义,而Job是任务的执行逻辑,JobDetail里会引用一个Job Class来定义
        public JobDetail getJobDetail(JobKey jobKey, String description, JobDataMap map) {
            return JobBuilder.newJob(DynamicJob.class)
                    .withIdentity(jobKey)
                    .withDescription(description)
                    .setJobData(map)
                    .storeDurably()
                    .build();
        }
    
        //获取Trigger (Job的触发器,执行规则)
        public Trigger getTrigger(JobEntity job) {
            return TriggerBuilder.newTrigger()
                    .withIdentity(job.getName(), job.getJobGroup())
                    .withSchedule(CronScheduleBuilder.cronSchedule(job.getCron()))
                    .build();
        }
    
        //获取JobKey,包含Name和Group
        public JobKey getJobKey(JobEntity job) {
            return JobKey.jobKey(job.getName(), job.getJobGroup());
        }
    }
    八、自定义工具类
    package com.ealen.util;
    
    import java.util.List;
    import java.util.Map;
    
    /**
     * 自定义枚举单例对象 StringUtil
     */
    public enum StringUtil {
        getStringUtil;
    
        //是否为空
        public boolean isEmpty(String str) {
            return (str == null) || (str.length() == 0) || (str.equals(""));
        }
    
        //去空格
        public String trim(String str) {
            return str == null ? null : str.trim();
        }
    
        //获取Map参数值
        public String getMapString(Map<String, String> map) {
            String result = "";
            for (Map.Entry entry : map.entrySet()) {
                result += entry.getValue() + " ";
            }
            return result;
        }
    
        //获取List参数值
        public static String getListString(List<String> list) {
            StringBuilder result = new StringBuilder();
            for (String s : list) {
                result.append(s).append(" ");
            }
            return result.toString();
        }
    
    }

    九、Dto

    package com.ealen.web.dto;
    
    import lombok.Data;
    
    import javax.validation.constraints.NotEmpty;
    import javax.validation.constraints.NotNull;
    
    
    @Data
    public class ModifyCronDTO {
        @NotNull(message = "the job id cannot be null")
        private Integer id;
    
        @NotEmpty(message = "the cron cannot be empty")
        private String cron;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getCron() {
            return cron;
        }
    
        public void setCron(String cron) {
            this.cron = cron;
        }
    }

    十、Controller控制器

    package com.ealen.web;
    
    import com.ealen.dao.JobEntityRepository;
    import com.ealen.entity.JobEntity;
    import com.ealen.job.DynamicJob;
    import com.ealen.service.DynamicJobService;
    import com.ealen.web.dto.ModifyCronDTO;
    import lombok.extern.slf4j.Slf4j;
    import org.quartz.*;
    import org.quartz.impl.matchers.GroupMatcher;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.quartz.SchedulerFactoryBean;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;
    
    import javax.annotation.PostConstruct;
    import javax.validation.constraints.NotNull;
    import java.util.Objects;
    import java.util.Set;
    
    
    @RestController
    @Slf4j
    public class JobController {
    
        private static final Logger log = LoggerFactory.getLogger(JobController.class);
    
        @Autowired
        private SchedulerFactoryBean schedulerFactoryBean;
    
        @Autowired
        private DynamicJobService jobService;
    
        @Autowired
        private JobEntityRepository repository;
    
        //初始化启动所有的Job
        @PostConstruct
        public void initialize() {
            try {
                reStartAllJobs();
                log.info("init success");
            } catch (SchedulerException e) {
                log.error("printStackTrace ", e);
            }
        }
    
        //根据ID重启某个Job
        @RequestMapping("/refresh/{id}")
        public String refresh(@PathVariable @NotNull Integer id) throws SchedulerException {
            String result;
            JobEntity entity = jobService.getJobEntityById(id);
            if (Objects.isNull(entity)) return "error: id is not exist ";
            synchronized (log) {
                JobKey jobKey = jobService.getJobKey(entity);
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                scheduler.pauseJob(jobKey);
                scheduler.unscheduleJob(TriggerKey.triggerKey(jobKey.getName(), jobKey.getGroup()));
                scheduler.deleteJob(jobKey);
                JobDataMap map = jobService.getJobDataMap(entity);
                JobDetail jobDetail = jobService.getJobDetail(jobKey, entity.getDescription(), map);
                if (entity.getStatus().equals("OPEN")) {
                    scheduler.scheduleJob(jobDetail, jobService.getTrigger(entity));
                    result = "Refresh Job : " + entity.getName() + "	 jarPath: " + entity.getJarPath() + " success !";
                } else {
                    result = "Refresh Job : " + entity.getName() + "	 jarPath: " + entity.getJarPath() + " failed ! , " +
                            "Because the Job status is " + entity.getStatus();
                }
            }
            return result;
        }
    
    
        //重启数据库中所有的Job
        @RequestMapping("/refresh/all")
        public String refreshAll() {
            String result;
            try {
                reStartAllJobs();
                result = "success";
            } catch (SchedulerException e) {
                result = "exception : " + e.getMessage();
            }
            return "refresh all jobs : " + result;
        }
    
        /**
         * 重新启动所有的job
         */
        private void reStartAllJobs() throws SchedulerException {
            synchronized (log) {                                                         //只允许一个线程进入操作
                Scheduler scheduler = schedulerFactoryBean.getScheduler();
                Set<JobKey> set = scheduler.getJobKeys(GroupMatcher.anyGroup());
                scheduler.pauseJobs(GroupMatcher.anyGroup());                               //暂停所有JOB
                for (JobKey jobKey : set) {                                                 //删除从数据库中注册的所有JOB
                    scheduler.unscheduleJob(TriggerKey.triggerKey(jobKey.getName(), jobKey.getGroup()));
                    scheduler.deleteJob(jobKey);
                }
                for (JobEntity job : jobService.loadJobs()) {                               //从数据库中注册的所有JOB
                    log.info("Job register name : {} , group : {} , cron : {}", job.getName(), job.getJobGroup(), job.getCron());
                    JobDataMap map = jobService.getJobDataMap(job);
                    JobKey jobKey = jobService.getJobKey(job);
                    JobDetail jobDetail = jobService.getJobDetail(jobKey, job.getDescription(), map);
                    if (job.getStatus().equals("OPEN")) scheduler.scheduleJob(jobDetail, jobService.getTrigger(job));
                    else
                        log.info("Job jump name : {} , Because {} status is {}", job.getName(), job.getName(), job.getStatus());
                }
            }
        }
    
        //修改某个Job执行的Cron
        @PostMapping("/modifyJob")
        public String modifyJob(@RequestBody @Validated ModifyCronDTO dto) {
            if (!CronExpression.isValidExpression(dto.getCron())) return "cron is invalid !";
            synchronized (log) {
                JobEntity job = jobService.getJobEntityById(dto.getId());
                if (job.getStatus().equals("OPEN")) {
                    try {
                        JobKey jobKey = jobService.getJobKey(job);
                        TriggerKey triggerKey = new TriggerKey(jobKey.getName(), jobKey.getGroup());
                        Scheduler scheduler = schedulerFactoryBean.getScheduler();
                        CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
                        String oldCron = cronTrigger.getCronExpression();
                        if (!oldCron.equalsIgnoreCase(dto.getCron())) {
                            job.setCron(dto.getCron());
                            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(dto.getCron());
                            CronTrigger trigger = TriggerBuilder.newTrigger()
                                    .withIdentity(jobKey.getName(), jobKey.getGroup())
                                    .withSchedule(cronScheduleBuilder)
                                    .usingJobData(jobService.getJobDataMap(job))
                                    .build();
                            scheduler.rescheduleJob(triggerKey, trigger);
                            repository.save(job);
                        }
                    } catch (Exception e) {
                        log.error("printStackTrace", e);
                    }
                } else {
                    log.info("Job jump name : {} , Because {} status is {}", job.getName(), job.getName(), job.getStatus());
                    return "modify failure , because the job is closed";
                }
            }
            return "modify success";
        }
    
    
    }

    十一、SQL

    job_entity.sql  任务

    SET FOREIGN_KEY_CHECKS=0;
    DROP TABLE IF EXISTS `job_entity`;
    CREATE TABLE `job_entity` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) DEFAULT NULL,
      `job_group` varchar(255) DEFAULT NULL,
      `cron` varchar(255) DEFAULT NULL,
      `parameter` varchar(255) NOT NULL,
      `description` varchar(255) DEFAULT NULL,
      `vm_param` varchar(255) DEFAULT NULL,
      `jar_path` varchar(255) DEFAULT NULL,
      `status` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
    INSERT INTO `job_entity` VALUES ('1',  'first', 'helloworld', '0/2 * * * * ? ', '1', '第一个', '', null, 'OPEN');
    INSERT INTO `job_entity` VALUES ('2',  'second', 'helloworld', '0/5 * * * * ? ', '2', '第二个', null, null, 'OPEN');
    INSERT INTO `job_entity` VALUES ('4',  'third', 'helloworld', '0/15 * * * * ? ', '3', '第三个', null, null, 'OPEN');
    INSERT INTO `job_entity` VALUES ('5',  'four', 'helloworld', '0 0/1 * * * ? *', '4', '第四个', null, null, 'CLOSE');
    INSERT INTO `job_entity` VALUES ('6',  'OLAY Job', 'Nomal', '0 0/2 * * * ?', '', '第五个', null, 'C:\EalenXie\Download\JDE-Order-1.0-SNAPSHOT.jar', 'CLOSE');

    quartz_innodb.sql

    -- in your Quartz properties file, you'll need to set org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    -- 你需要在你的quartz.properties文件中设置org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    -- StdJDBCDelegate说明支持集群,所有的任务信息都会保存到数据库中,可以控制事物,还有就是如果应用服务器关闭或者重启,任务信息都不会丢失,并且可以恢复因服务器关闭或者重启而导致执行失败的任务
    -- This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM
    -- 这是来自quartz的脚本,在MySQL数据库中创建以下的表,修改为使用INNODB而不是MYISAM
    -- 你需要在数据库中执行以下的sql脚本
    DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
    DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
    DROP TABLE IF EXISTS QRTZ_LOCKS;
    DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
    DROP TABLE IF EXISTS QRTZ_CALENDARS;
    
    -- 存储每一个已配置的Job的详细信息
    CREATE TABLE QRTZ_JOB_DETAILS(
    SCHED_NAME VARCHAR(120) NOT NULL,
    JOB_NAME VARCHAR(200) NOT NULL,
    JOB_GROUP VARCHAR(200) NOT NULL,
    DESCRIPTION VARCHAR(250) NULL,
    JOB_CLASS_NAME VARCHAR(250) NOT NULL,
    IS_DURABLE VARCHAR(1) NOT NULL,
    IS_NONCONCURRENT VARCHAR(1) NOT NULL,
    IS_UPDATE_DATA VARCHAR(1) NOT NULL,
    REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
    JOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
    ENGINE=InnoDB;
    
    -- 存储已配置的Trigger的信息
    CREATE TABLE QRTZ_TRIGGERS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    JOB_NAME VARCHAR(200) NOT NULL,
    JOB_GROUP VARCHAR(200) NOT NULL,
    DESCRIPTION VARCHAR(250) NULL,
    NEXT_FIRE_TIME BIGINT(13) NULL,
    PREV_FIRE_TIME BIGINT(13) NULL,
    PRIORITY INTEGER NULL,
    TRIGGER_STATE VARCHAR(16) NOT NULL,
    TRIGGER_TYPE VARCHAR(8) NOT NULL,
    START_TIME BIGINT(13) NOT NULL,
    END_TIME BIGINT(13) NULL,
    CALENDAR_NAME VARCHAR(200) NULL,
    MISFIRE_INSTR SMALLINT(2) NULL,
    JOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
    REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
    ENGINE=InnoDB;
    
    -- 存储已配置的Simple Trigger的信息
    CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    REPEAT_COUNT BIGINT(7) NOT NULL,
    REPEAT_INTERVAL BIGINT(12) NOT NULL,
    TIMES_TRIGGERED BIGINT(10) NOT NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
    ENGINE=InnoDB;
    
    -- 存储Cron Trigger,包括Cron表达式和时区信息
    CREATE TABLE QRTZ_CRON_TRIGGERS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    CRON_EXPRESSION VARCHAR(120) NOT NULL,
    TIME_ZONE_ID VARCHAR(80),
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
    ENGINE=InnoDB;
    
    CREATE TABLE QRTZ_SIMPROP_TRIGGERS
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        TRIGGER_NAME VARCHAR(200) NOT NULL,
        TRIGGER_GROUP VARCHAR(200) NOT NULL,
        STR_PROP_1 VARCHAR(512) NULL,
        STR_PROP_2 VARCHAR(512) NULL,
        STR_PROP_3 VARCHAR(512) NULL,
        INT_PROP_1 INT NULL,
        INT_PROP_2 INT NULL,
        LONG_PROP_1 BIGINT NULL,
        LONG_PROP_2 BIGINT NULL,
        DEC_PROP_1 NUMERIC(13,4) NULL,
        DEC_PROP_2 NUMERIC(13,4) NULL,
        BOOL_PROP_1 VARCHAR(1) NULL,
        BOOL_PROP_2 VARCHAR(1) NULL,
        PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
        FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
    ENGINE=InnoDB;
    
    -- Trigger作为Blob类型存储(用于Quartz用户用JDBC创建他们自己定制的Trigger类型,JobStore并不知道如何存储实例的时候)
    CREATE TABLE QRTZ_BLOB_TRIGGERS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    BLOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
    ENGINE=InnoDB;
    
    -- 以Blob类型存储Quartz的Calendar日历信息,quartz可配置一个日历来指定一个时间范围
    CREATE TABLE QRTZ_CALENDARS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    CALENDAR_NAME VARCHAR(200) NOT NULL,
    CALENDAR BLOB NOT NULL,
    PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
    ENGINE=InnoDB;
    
    -- 存储已暂停的Trigger组的信息
    CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
    ENGINE=InnoDB;
    
    -- 存储与已触发的Trigger相关的状态信息,以及相联Job的执行信息
    CREATE TABLE QRTZ_FIRED_TRIGGERS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    ENTRY_ID VARCHAR(95) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    INSTANCE_NAME VARCHAR(200) NOT NULL,
    FIRED_TIME BIGINT(13) NOT NULL,
    SCHED_TIME BIGINT(13) NOT NULL,
    PRIORITY INTEGER NOT NULL,
    STATE VARCHAR(16) NOT NULL,
    JOB_NAME VARCHAR(200) NULL,
    JOB_GROUP VARCHAR(200) NULL,
    IS_NONCONCURRENT VARCHAR(1) NULL,
    REQUESTS_RECOVERY VARCHAR(1) NULL,
    PRIMARY KEY (SCHED_NAME,ENTRY_ID))
    ENGINE=InnoDB;
    
    -- 存储少量的有关 Scheduler的状态信息,和别的 Scheduler 实例(假如是用于一个集群中)
    CREATE TABLE QRTZ_SCHEDULER_STATE (
    SCHED_NAME VARCHAR(120) NOT NULL,
    INSTANCE_NAME VARCHAR(200) NOT NULL,
    LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
    CHECKIN_INTERVAL BIGINT(13) NOT NULL,
    PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
    ENGINE=InnoDB;
    -- 存储程序的非观锁的信息(假如使用了悲观锁)
    CREATE TABLE QRTZ_LOCKS (
    SCHED_NAME VARCHAR(120) NOT NULL,
    LOCK_NAME VARCHAR(40) NOT NULL,
    PRIMARY KEY (SCHED_NAME,LOCK_NAME))
    ENGINE=InnoDB;
    
    CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
    CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
    
    CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
    CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
    CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
    CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
    CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
    CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
    CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
    CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
    CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
    CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
    CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
    CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
    
    CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
    CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
    CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
    CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
    CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
    CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
    
    commit;

    项目结构图:

    测试

     数据库 显示:

     0 0/3 * * * ?             解释 :三分钟执行

    0/15 * * * * ?          解释 :十五秒执行

    表达式 生成地址: http://cron.qqe2.com/

    GitHub地址:https://github.com/nongzihong/SpringBoot-Quartz

  • 相关阅读:
    php的错误处理机制
    php的自动加载函数spl_autoload_register和__autoload
    mysql日志配置
    01,易语言网页填表
    mac 的全文搜索
    react native 热更新
    码云的使用教程
    autolayout实现水平三等分
    mac命令行快捷键
    什么是延展性(Malleability,可鍛性)
  • 原文地址:https://www.cnblogs.com/nongzihong/p/12666100.html
Copyright © 2011-2022 走看看