☀️Terry

- - 草木逢春,雨过天晴🌈。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

任务需求:

  银行日终定时跑批,开始思路是使用最简单的方式Timer任务调度线程去跑,但是有个问题,Timer调度的话,不能够精准的时间,因为牵扯到集群的问题,所以最后考虑到了quartz集群

Quartz版本:

  2.3.1

Quartz 核心元素:

Quartz任务调度的核心元素为:Scheduler——任务调度器、Trigger——触发器、Job——任务。其中trigger和job是任务调度的元数据,scheduler是实际执行调度的控制器。

  Trigger是用于定义调度时间的元素,即按照什么时间规则去执行任务。Quartz中主要提供了四种类型的trigger:SimpleTrigger,CronTirgger,DateIntervalTrigger,和NthIncludedDayTrigger。这四种trigger可以满足企业应用中的绝大部分需求。

  Job用于表示被调度的任务。主要有两种类型的job:无状态的(stateless)和有状态的(stateful)。对于同一个trigger来说,有状态的job不能被并行执行,只有上一次触发的任务被执行完之后,才能触发下一次执行。Job主要有两种属性:volatility和durability,其中volatility表示任务是否被持久化到数据库存储,而durability表示在没有trigger关联的时候任务是否被保留。两者都是在值为true的时候任务被持久化或保留。一个job可以被多个trigger关联,但是一个trigger只能关联一个job。

  Scheduler由scheduler工厂创建:

 

DirectSchedulerFactory或者StdSchedulerFactory。看很多资料都是基于这两个去做的,本文是直接从工厂接口SchedulerFactory去做。

Scheduler主要有三种:

RemoteMBeanScheduler,RemoteScheduler和StdScheduler。也是基于接口去直接做不适用他们的3个实现。

正文:

结构:

 

工厂:QuartzJobFactory

package cn.lsr.quartz.factory;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;

/**
 * @Description: quartz工厂
 * @Package: lsr-microservice
 * @author: Hacker_lsr@126.com
 **/
@Component
public class QuartzJobFactory extends AdaptableJobFactory {
    /**
     * 这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴.
     */
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        //进行注入,这属于Spring的技术,不清楚的可以查看Spring的API.
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

定时任务管理器:QuartzConfigManager

package cn.lsr.quartz.manager;

import cn.lsr.quartz.factory.QuartzJobFactory;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.IOException;

/**
 * @Description: 分布式任务定时管理配置
 * @Package: lsr-microservice
 * @author: Hacker_lsr@126.com
 **/
@Component
public class QuartzConfigManager {
    /**
     * 默认数据源--若不使用,使用的是配置文件的数据源
     */
    @Autowired
    DataSource dataSource;
    // 配置文件路径
    static final String QUARTZ_CONFIG = "/quartz.properties";
    /**
     * 工厂
     * @param myJobFactory
     * @return
     * @throws Exception
     */
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(QuartzJobFactory myJobFactory) throws Exception {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        //如果使用自定义的数据源就可以配置,如果是使用quartz扩展的不需要设置。
        //schedulerFactoryBean.setDataSource(dataSource);
        //使job实例支持spring 容器管理
        //用于Quartz集群,启动时更新已存在的Job
        schedulerFactoryBean.setOverwriteExistingJobs(true);
        schedulerFactoryBean.setJobFactory(myJobFactory);
        schedulerFactoryBean.setConfigLocation(new ClassPathResource(QUARTZ_CONFIG));
        //可以手动加载quartz配置
        //schedulerFactoryBean.setQuartzProperties(PropertiesUtils.readProperties(QUARTZ_CONFIG));
        // 集群需要通过QuartzJobBean注入,需要设置上下文
        schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContext");
        // 延迟10s启动quartz
        schedulerFactoryBean.setStartupDelay(10);
        return schedulerFactoryBean;
    }
    /**
     * 调度器
     * @param schedulerFactoryBean
     * @return
     * @throws IOException
     * @throws SchedulerException
     */
    @Bean
    public Scheduler scheduler(SchedulerFactoryBean schedulerFactoryBean) throws IOException, SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        scheduler.start();
        return scheduler;
    }

}

quartz数据源扩展为德鲁伊的:DruidConnectionProvider

package cn.lsr.quartz.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.quartz.utils.ConnectionProvider;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * @Description: quartz数据源扩展
 * @Package: lsr-microservice
 * @author: Hacker_lsr@126.com
 **/

public class DruidConnectionProvider implements ConnectionProvider {
    //JDBC驱动
    public String driver;
    //JDBC连接串
    public String URL;
    //数据库用户名
    public String user;
    //数据库用户密码
    public String password;
    //数据库最大连接数
    public int maxConnections;

    // 数据库SQL查询每次连接返回执行到连接池,以确保它仍然是有效的。
    public String validationQuery;

    private boolean validateOnCheckout;

    private int idleConnectionValidationSeconds;

    public String maxCachedStatementsPerConnection;

    public static final int DEFAULT_DB_MAX_CONNECTIONS = 10;

    public static final int DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION = 120;

    // Druid连接池
    private DruidDataSource datasource;

    @Override
    public Connection getConnection() throws SQLException {
        return datasource.getConnection();
    }

    @Override
    public void shutdown() throws SQLException {
        datasource.close();
    }

    @Override
    public void initialize() throws SQLException {
        if (URL == null) {
            throw new SQLException("DBPool could not be created: DB URL cannot be null");
        }
        if (driver == null) {
            throw new SQLException("DBPool driver could not be created: DB driver class name cannot be null!");
        }
        if (this.maxConnections < 0) {
            throw new SQLException(
                    "DBPool maxConnectins could not be created: Max connections must be greater than zero!");
        }
        datasource = new DruidDataSource();
        try {
            datasource.setDriverClassName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
        datasource.setUrl(this.URL);
        datasource.setUsername(this.user);
        datasource.setPassword(this.password);
        datasource.setMaxActive(this.maxConnections);
        datasource.setMinIdle(1);
        datasource.setMaxWait(0);
        datasource.setMaxPoolPreparedStatementPerConnectionSize(this.maxConnections);
        if (this.validationQuery != null) {
            datasource.setValidationQuery(this.validationQuery);
            if (!this.validateOnCheckout){
                datasource.setTestOnReturn(true);
            }else{
                datasource.setTestOnBorrow(true);
            }
            datasource.setValidationQueryTimeout(this.idleConnectionValidationSeconds);
        }
    }
    /*
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *
     * 提供get set方法
     *
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getURL() {
        return URL;
    }

    public void setURL(String URL) {
        this.URL = URL;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getMaxConnections() {
        return maxConnections;
    }

    public void setMaxConnections(int maxConnections) {
        this.maxConnections = maxConnections;
    }

    public String getMaxCachedStatementsPerConnection() {
        return maxCachedStatementsPerConnection;
    }

    public void setMaxCachedStatementsPerConnection(String maxCachedStatementsPerConnection) {
        this.maxCachedStatementsPerConnection = maxCachedStatementsPerConnection;
    }

    public String getValidationQuery() {
        return validationQuery;
    }

    public void setValidationQuery(String validationQuery) {
        this.validationQuery = validationQuery;
    }

    public boolean isValidateOnCheckout() {
        return validateOnCheckout;
    }

    public void setValidateOnCheckout(boolean validateOnCheckout) {
        this.validateOnCheckout = validateOnCheckout;
    }

    public int getIdleConnectionValidationSeconds() {
        return idleConnectionValidationSeconds;
    }

    public void setIdleConnectionValidationSeconds(int idleConnectionValidationSeconds) {
        this.idleConnectionValidationSeconds = idleConnectionValidationSeconds;
    }

    public DruidDataSource getDatasource() {
        return datasource;
    }

    public void setDatasource(DruidDataSource datasource) {
        this.datasource = datasource;
    }

}

job任务接口:JobTaskService

package cn.lsr.quartz.service;

import cn.lsr.quartz.entity.JobInfo;
import org.quartz.SchedulerException;

import java.util.List;

/**
 * @Description: job任务接口
 * @Package: lsr-microservice
 * @author: Hacker_lsr@126.com
 **/
public interface JobTaskService {
    /**
     * 查询所有的job
     * @return
     */
    List<JobInfo> list();

    /**
     * 新增job
     * @param info
     */
    void addJob(JobInfo info);

    /**
     * 修改job
     * @param info
     */
    void edit(JobInfo info);

    /**
     * 删除job
     * @param jobName
     * @param jobGroup
     */
    void delete(String jobName, String jobGroup);

    /**
     * 暂停job
     * @param jobName
     * @param jobGroup
     */
    void pause(String jobName, String jobGroup);

    /**
     * 重启job
     * @param jobName
     * @param jobGroup
     */
    void resume(String jobName, String jobGroup);

    /**
     * 检查job
     * @param jobName
     * @param jobGroup
     * @return
     * @throws SchedulerException
     */
    boolean checkExists(String jobName, String jobGroup)throws SchedulerException;
}

job接口实现:JobTaskServiceImp

package cn.lsr.quartz.service.imp;

import cn.lsr.quartz.entity.JobInfo;
import cn.lsr.quartz.service.JobTaskService;
import org.apache.commons.lang3.time.DateFormatUtils;
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.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

/**
 * @Description: job任务实现
 * @Package: lsr-microservice
 * @author: Hacker_lsr@126.com
 **/
@Service
public class JobTaskServiceImp implements JobTaskService {
    private Logger logger = LoggerFactory.getLogger(JobTaskServiceImp.class);

    @Autowired(required = false)
    private Scheduler scheduler;

    /**
     * 所有任务列表
     */
    @Override
    public List<JobInfo> list() {
        List<JobInfo> list = new ArrayList<>();

        try {
            for (String groupJob : scheduler.getJobGroupNames()) {
                for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.<JobKey>groupEquals(groupJob))) {
                    List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                    for (Trigger trigger : triggers) {
                        Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                        JobDetail jobDetail = scheduler.getJobDetail(jobKey);

                        String cronExpression = "", createTime = "";

                        if (trigger instanceof CronTrigger) {
                            CronTrigger cronTrigger = (CronTrigger) trigger;
                            cronExpression = cronTrigger.getCronExpression();
                            createTime = cronTrigger.getDescription();
                        }
                        JobInfo info = new JobInfo();
                        info.setJobName(jobKey.getName());
                        info.setJobGroup(jobKey.getGroup());
                        info.setJobDescription(jobDetail.getDescription());
                        //获取参数 TODO
                        jobDetail.getJobDataMap().toString();
                        info.setJobStatus(triggerState.name());
                        info.setCronExpression(cronExpression);
                        info.setCreateTime(createTime);
                        list.add(info);
                    }
                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 保存定时任务
     *
     * @param info
     */
    @SuppressWarnings("unchecked")
    @Override
    public void addJob(JobInfo info) {
        String jobName = info.getJobName(),
                jobGroup = info.getJobGroup(),
                cronExpression = info.getCronExpression(),
                jobDescription = info.getJobDescription(),
                createTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        try {
            if (checkExists(jobName, jobGroup)) {
                logger.info("add job fail, job already exist, jobGroup:{}, jobName:{}", jobGroup, jobName);
            }
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
            JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
            CronScheduleBuilder schedBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withDescription(createTime).withSchedule(schedBuilder).build();
            Class<? extends Job> clazz = (Class<? extends Job>) Class.forName(jobName);
            JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(jobKey).withDescription(jobDescription).build();
            //可以传参   TODO
            jobDetail.getJobDataMap().put("data", jobDescription);
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException | ClassNotFoundException e) {
            logger.error("类名不存在或执行表达式错误,exception:{}", e.getMessage());
        }
    }

    /**
     * 修改定时任务
     *
     * @param info
     */
    @Override
    public void edit(JobInfo info) {
        String jobName = info.getJobName(),
                jobGroup = info.getJobGroup(),
                cronExpression = info.getCronExpression(),
                jobDescription = info.getJobDescription(),
                createTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        try {
            if (!checkExists(jobName, jobGroup)) {
                logger.info("edit job fail, job is not exist, jobGroup:{}, jobName:{}", jobGroup, jobName);
            }
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
            JobKey jobKey = new JobKey(jobName, jobGroup);
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();
            CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).withDescription(createTime).withSchedule(cronScheduleBuilder).build();
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            //可以传参   TODO
            jobDetail.getJobDataMap().put("data", jobDescription);
            jobDetail.getJobBuilder().withDescription(jobDescription);
            HashSet<Trigger> triggerSet = new HashSet<>();
            triggerSet.add(cronTrigger);

            scheduler.scheduleJob(jobDetail, triggerSet, true);
        } catch (SchedulerException e) {
            logger.error("类名不存在或执行表达式错误,exception:{}", e.getMessage());
        }
    }

    /**
     * 删除定时任务
     *
     * @param jobName
     * @param jobGroup
     */
    @Override
    public void delete(String jobName, String jobGroup) {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
        try {
            if (checkExists(jobName, jobGroup)) {
                scheduler.pauseTrigger(triggerKey);
                scheduler.unscheduleJob(triggerKey);
                logger.info("delete job, triggerKey:{},jobGroup:{}, jobName:{}", triggerKey, jobGroup, jobName);
            }
        } catch (SchedulerException e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 暂停定时任务
     *
     * @param jobName
     * @param jobGroup
     */
    @Override
    public void pause(String jobName, String jobGroup) {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
        try {
            if (checkExists(jobName, jobGroup)) {
                scheduler.pauseTrigger(triggerKey);
                logger.info("pause job success, triggerKey:{},jobGroup:{}, jobName:{}", triggerKey, jobGroup, jobName);
            }
        } catch (SchedulerException e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 重新开始任务
     *
     * @param jobName
     * @param jobGroup
     */
    @Override
    public void resume(String jobName, String jobGroup) {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);

        try {
            if (checkExists(jobName, jobGroup)) {
                scheduler.resumeTrigger(triggerKey);
                logger.info("resume job success,triggerKey:{},jobGroup:{}, jobName:{}", triggerKey, jobGroup, jobName);
            }
        } catch (SchedulerException e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 验证是否存在
     *
     * @param jobName
     * @param jobGroup
     * @throws SchedulerException
     */
    @Override
    public boolean checkExists(String jobName, String jobGroup) throws SchedulerException {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
        return scheduler.checkExists(triggerKey);
    }
}

job入口:JobExecute

package cn.lsr.user.job;

import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @Description: job执行入口
 * @Package: lsr-microservice
 * @author: Hacker_lsr@126.com
 **/
@Component
@DisallowConcurrentExecution
public class JobExecute implements Job {
    private Logger logger = LoggerFactory.getLogger(JobExecute.class);
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //获取参数
        String s = (String) jobExecutionContext.getJobDetail().getJobDataMap().get("data");
        logger.info("开始执行任务===================,参数:{}",s);
    }
}

job实体:JobInfo

package cn.lsr.quartz.entity;

import java.io.Serializable;

/**
 * @Description: job配置类
 * @Package: lsr-microservice
 * @author: Hacker_lsr@126.com
 **/
public class JobInfo implements Serializable {
    /**任务名称*/
    private String jobName;

    /**任务分组*/
    private String jobGroup;

    /**任务描述*/
    private String jobDescription;

    /**任务状态*/
    private String jobStatus;

    /**任务表达式*/
    private String cronExpression;

    /**创建时间*/
    private String createTime;

    public String getJobName() {
        return jobName;
    }

    public void setJobName(String jobName) {
        this.jobName = jobName;
    }

    public String getJobGroup() {
        return jobGroup;
    }

    public void setJobGroup(String jobGroup) {
        this.jobGroup = jobGroup;
    }

    public String getJobDescription() {
        return jobDescription;
    }

    public void setJobDescription(String jobDescription) {
        this.jobDescription = jobDescription;
    }

    public String getJobStatus() {
        return jobStatus;
    }

    public void setJobStatus(String jobStatus) {
        this.jobStatus = jobStatus;
    }

    public String getCronExpression() {
        return cronExpression;
    }

    public void setCronExpression(String cronExpression) {
        this.cronExpression = cronExpression;
    }

    public String getCreateTime() {
        return createTime;
    }

    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }
}

sql:

CREATE TABLE `quartz_jobconfig` (
  `jobName` varchar(190) NOT NULL COMMENT '任务类路径',
  `jobGroup` varchar(190)  DEFAULT NULL COMMENT '分组',
  `jobDescription` varchar(500)   COMMENT '任务描述',
  `jobStatus` varchar(32)   DEFAULT NULL COMMENT 'job状态 (查询显示会用到的参数)',
  `jobcron` varchar(32)   DEFAULT NULL COMMENT 'cron表达式',
  `createTime` varchar(32)   NOT NULL DEFAULT '' COMMENT '创建时间',
  PRIMARY KEY (`jobName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC;

配置文件:quartz.properties

#quartz集群配置
# ===========================================================================
# Configure Main Scheduler Properties 调度器属性
# ===========================================================================
#调度标识名 集群中每一个实例都必须使用相同的名称
org.quartz.scheduler.instanceName=DefaultQuartzScheduler
#ID设置为自动获取 每一个必须不同
org.quartz.scheduler.instanceid=AUTO
#禁用quartz软件更新
org.quartz.scheduler.skipUpdateCheck=true
#============================================================================
# Configure ThreadPool
#============================================================================
#线程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#指定线程数,至少为1(无默认值)(一般设置为1-100直接的整数合适)
org.quartz.threadPool.threadCount = 25
#设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
# 信息保存时间 默认值60秒
org.quartz.jobStore.misfireThreshold = 60000
#数据保存方式为数据库持久化
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#数据库代理类,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#JobDataMaps是否都为String类型
org.quartz.jobStore.useProperties = false
#数据库别名 随便取
org.quartz.jobStore.dataSource = myDS
#表的前缀,默认QRTZ_
org.quartz.jobStore.tablePrefix = QRTZ_
#是否加入集群
org.quartz.jobStore.isClustered = true
#调度实例失效的检查时间间隔
org.quartz.jobStore.clusterCheckinInterval = 20000
#============================================================================
# Configure Datasources
#============================================================================
#自定义连接池
org.quartz.dataSource.myDS.connectionProvider.class=cn.lsr.quartz.config.DruidConnectionProvider
#数据库引擎
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
#数据库连接
org.quartz.dataSource.myDS.URL = jdbc:mysql://127.0.0.1:3306/lsr-microservice?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
#数据库用户
org.quartz.dataSource.myDS.user = root
#数据库密码
org.quartz.dataSource.myDS.password = lishirui
#允许最大连接
org.quartz.dataSource.myDS.maxConnections = 5
#验证查询sql,可以不设置
org.quartz.dataSource.myDS.validationQuery=select 0 from dual
#注:如果嫌需要额外配置quart数据源很烦,也可以共用你项目配置的数据库链接,这样每次更换数据库连接,就不需要额外在修改。

测试:

 /**
     * 测试
     */
    @GetMapping("/job/test")
    @ResponseBody
    public void test(){
        JobInfo jobInfo = new JobInfo();
        jobInfo.setJobName("cn.lsr.user.job.JobExecute");  //配置job入口的准确路径去执行exe..方法
        jobInfo.setJobGroup("test");
        jobInfo.setJobDescription("lishirui");
        jobInfo.setCronExpression("0 */1 * * * ? ");
        jobTaskService.addJob(jobInfo);
    }

 结果:

 

 

 

 

 

posted on 2020-04-03 14:47  ☀️Terry  阅读(585)  评论(0编辑  收藏  举报