spring boot集成Quartz實現數據庫存儲方式任務調度

在上一篇文章https://blog.csdn.net/zhou_fan_xi/article/details/104699361介紹過quartz使用RAMJobStore方式配置。接下來順着上篇文章講解將任務數據存儲在數據庫中方式。(繼續使用上一篇創建job的代碼)

JobStore介紹

JobStore是負責跟蹤調度器中所有的工作數據:作業任務、觸發器、日曆等。在配置文件(quartz.properties)中定義JobStore的形式,JobStore有兩種RAMJobStore和JDBCJobStore

RAMJobStore :配置簡單,速度快,但程序停止,數據丟失
JDBCJobStore :配置略微複雜,可以保存數據

JDBCJobStore配置方式

下載sql文件 下載

 

下載對應版本的distribution包,進入docs-dbTables中如下

找到對應數據庫的sql文件執行其中sql建表

創建配置文件

在maven項目的resource目錄下創建quartz.properties 

#
#============================================================================
# Configure Main Scheduler Properties 調度器屬性
#============================================================================
#org.quartz.scheduler.instanceName: xifanzhou
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount= 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.misfireThreshold: 60000
#============================================================================
# Configure JobStore
#============================================================================
#存儲方式使用JobStoreTX,也就是數據庫
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#使用自己的配置文件
org.quartz.jobStore.useProperties:true
#數據庫中quartz表的表名前綴
org.quartz.jobStore.tablePrefix:qrtz_
org.quartz.jobStore.dataSource:qzDS
#是否使用集羣(如果項目只部署到 一臺服務器,就不用了)
org.quartz.jobStore.isClustered = false
#============================================================================
# Configure Datasources
#============================================================================
#配置數據庫源(org.quartz.dataSource.qzDS.maxConnections: c3p0配置的是有s的,druid數據源沒有s)
org.quartz.dataSource.qzDS.connectionProvider.class:com.example.demo.job.DruidConnectionProvider
org.quartz.dataSource.qzDS.driver: com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL: jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
org.quartz.dataSource.qzDS.user: root
org.quartz.dataSource.qzDS.password: 123456
org.quartz.dataSource.qzDS.maxConnection: 10

其中org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX指定job存儲方式爲數據庫存儲

修改quartz數據源爲 Druid

說明:
quartz 需要用到數據庫連接池,Quartz 2.0 以前默認使用 DBCP。Quartz 2.0 以後 默認C3P0(包含2.0)。下面我們要將數據源修改爲 Druidps:Druid的有自帶監控系統...所以大家都在用,但是呢:配置換源很繁瑣。如以下
基本步驟:
(1)導入依賴

        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.12</version>
		</dependency>


(2)導入DruidConnectionProvider.java

package com.example.demo.job;

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

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

/**
 * @author xifanzhou
 * @Created 2020/3/9
 */
public class DruidConnectionProvider implements ConnectionProvider {
    /*
    * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    *
    * 常量配置,與quartz.properties文件的key保持一致(去掉前綴),同時提供set方法,Quartz框架自動注入值。
    *
    * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    */
    /**
     *  JDBC驅動
     */
    public String driver;
    /**
     * JDBC連接串
     */
    public String URL;
    /**
     * 數據庫用戶名
     */
    public String user;
    /**
     * 數據庫用戶密碼
     */
    public String password;
    /**
     *  數據庫最大連接數
     */
    public int maxConnection;
    /**
     * 數據庫SQL查詢每次連接返回執行到連接池,以確保它仍然是有效的。
     */
    public String validationQuery;
    private boolean validateOnCheckout;
    private int idleConnectionValidationSeconds;
    public String maxCachedStatementsPerConnection;
    private String discardIdleConnectionsSeconds;
    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;

    /**
     * 接口實現
     * @return
     * @throws SQLException
     */
    @Override
    public Connection getConnection() throws SQLException {
        return datasource.getConnection();
    }
    @Override
    public void shutdown() throws SQLException {
        datasource.close();
    }
    @Override
    public void initialize() throws SQLException{
        if (this.URL == null) {
            throw new SQLException("DBPool could not be created: DB URL cannot be null");
        }
        if (this.driver == null) {
            throw new SQLException("DBPool driver could not be created: DB driver class name cannot be null!");
        }
        if (this.maxConnection < 0) {
            throw new SQLException("DBPool maxConnectins could not be created: Max connections must be greater than zero!");
        }
        datasource = new DruidDataSource();
        try{
            datasource.setDriverClassName(this.driver);
        } catch (Exception e) {
            try {
                throw new SchedulerException("Problem setting driver class name on datasource: " + e.getMessage(), e);
            } catch (SchedulerException e1) {
            }
        }
        datasource.setUrl(this.URL);
        datasource.setUsername(this.user);
        datasource.setPassword(this.password);
        datasource.setMaxActive(this.maxConnection);
        datasource.setMinIdle(1);
        datasource.setMaxWait(0);
        datasource.setMaxPoolPreparedStatementPerConnectionSize(DEFAULT_DB_MAX_CONNECTIONS);
        if (this.validationQuery != null) {
            datasource.setValidationQuery(this.validationQuery);
            if(!this.validateOnCheckout){
                datasource.setTestOnReturn(true);
            } else{
                datasource.setTestOnBorrow(true);
            }
            datasource.setValidationQueryTimeout(this.idleConnectionValidationSeconds);
        }
    }

    /**
     * 提供get set方法
     * @return
     */
    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 getMaxConnection() {
        return maxConnection;
    }
    public void setMaxConnection(int maxConnection) {
        this.maxConnection = maxConnection;
    }
    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;
    }
    public String getDiscardIdleConnectionsSeconds() {
        return discardIdleConnectionsSeconds;
    }
    public void setDiscardIdleConnectionsSeconds(String discardIdleConnectionsSeconds) {
        this.discardIdleConnectionsSeconds = discardIdleConnectionsSeconds;
    }
}


(3)修改quartz.properties配置

 注意 org.quartz.dataSource.qzDS.connectionProvider.class 修改爲自己的DruidConnectionProvider類路徑

導入 SchedulerFactory, 交給spring管理 讓job類實現bean注入的功能 

package com.example.demo.job;

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;

/**
 * @author xifanzhou
 * @Created 2020/3/6
 */
@Component
public class SchedulerFactory extends AdaptableJobFactory {

    /**
     * spring bean 對象管理工廠
     */
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //調用父類的方法
        Object jobInstance = super.createJobInstance(bundle);
        //自動注入
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

QuartzConfiguration.java(quartz調度框架與spring框架整合的配置類,主要是要將org.quartz.Scheduler交給spring進行管理) 

package com.example.demo.config;

import com.example.demo.job.SchedulerFactory;
import org.quartz.Scheduler;
import org.quartz.ee.servlet.QuartzInitializerListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
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 java.io.IOException;
import java.util.Properties;

/**
 * @author xifanzhou
 * @Created 2020/3/6
 */
@Configuration
public class QuartzConfiguration {
    /**
     *  注入service需要配置工廠類
     */
    @Autowired
    private SchedulerFactory schedulerFactory;

    @Bean(name="SchedulerFactory")
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        // 注入service需要配置工廠類
        factory.setJobFactory(schedulerFactory);
        // 注入service需要配置工廠類

        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        //在quartz.properties中的屬性被讀取並注入後再初始化對象
        propertiesFactoryBean.afterPropertiesSet();
        Properties properties = propertiesFactoryBean.getObject();
        factory.setQuartzProperties(properties);
        return factory;
    }

    /**
     * quartz初始化監聽器
     * @return
     */
    @Bean
    public QuartzInitializerListener executorListener() {
        return new QuartzInitializerListener();
    }

    /**
     *
     * 通過SchedulerFactoryBean獲取Scheduler的實例
     * @return
     * @throws IOException
     */
    @Bean(name="scheduler")
    public Scheduler scheduler() throws IOException {
        return schedulerFactoryBean().getScheduler();
    }
}

 配置完存儲數據庫所需後 啓動系統後創建job成功查看數據庫自動生成job數據

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章