完整的定时任务解决方案Spring集成+定时任务本身管理+DB持久化+集群

maven依赖

<dependency>

<groupId>org.quartz-scheduler</groupId>

<artifactId>quartz</artifactId>

<version>2.2.1</version>

</dependency>

<dependency>

<groupId>open-source.missing.com.oracle</groupId>

<artifactId>ojdbc6</artifactId>

<version>11.2.0.3.0</version>

</dependency>

<dependency>

<groupId>commons-dbcp</groupId>

<artifactId>commons-dbcp</artifactId>

<version>1.4</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context-support</artifactId>

<version>3.2.16.RELEASE</version>

</dependency>

执行从官网下载的gz文件中的sql语句(http://www.quartz-scheduler.org/),注意使用的jar版本和sql脚本必须保持一致。不然会出现各种奇葩问题。比如启动程序后,定时任务不执行。

quartz.properties配置

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX

org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate

org.quartz.jobStore.tablePrefix = QRTZ_

org.quartz.jobStore.dataSource = myDS

org.quartz.jobStore.isClustered=true

org.quartz.jobStore.clusterCheckinInterval = 60000   //集群模式下检测节点失败的轮询间隔,默认15秒。如果定时间隔为10秒,检测间隔为60秒,如果从节点失败到检测到过去了45秒,则检测到那一刻,会同时触发5个实例,这里一定要注意。

# org.quartz.plugins.history.LoggingJobHistoryPlugin

# org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingTriggerHistoryPlugin

# org.quartz.plugin.triggHistory.triggerFiredMessage = Trigger \{1\}.\{0\} fired job \{6\}.\{5\} at: \{4, date, HH:mm:ss MM/dd/yyyy}

# org.quartz.plugin.triggHistory.triggerCompleteMessage = Trigger \{1\}.\{0\} completed firing job \{6\}.\{5\} at \{4, date, HH:mm:ss MM/dd/yyyy\}.

org.quartz.scheduler.instanceName = MyClusteredScheduler

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool

org.quartz.threadPool.threadCount = 5

org.quartz.threadPool.threadPriority = 5

org.quartz.scheduler.instanceId=AUTO

org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin

org.quartz.plugin.shutdownhook.cleanShutdown = true

org.quartz.dataSource.myDS.driver = oracle.jdbc.OracleDriver

org.quartz.dataSource.myDS.URL = jdbc:oracle:thin:@172.23.11.49:1522:fcdb

org.quartz.dataSource.myDS.user = hs_fund

org.quartz.dataSource.myDS.password = Hundsun123

org.quartz.dataSource.myDS.maxConnections = 5

org.quartz.dataSource.myDS.validationQuery=select 1 from dual

org.quartz.dataSource.myDS.validateOnCheckout=true

spring配置文件

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

<property name="username" value="hs_fund"></property>

<property name="password" value="Hundsun123"></property>

<property name="url" value="jdbc:oracle:thin:@172.23.11.49:1522:fcdb"></property>

<property name="driverClassName" value="oracle.jdbc.OracleDriver"></property>

<property name="maxActive" value="10"></property>

<property name="maxIdle" value="10"></property>

<property name="minIdle" value="10"></property>

<property name="maxWait" value="10000"></property>

<property name="poolPreparedStatements" value="true" />

<property name="maxOpenPreparedStatements" value="50" />

</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

<property name="dataSource">

<ref bean="dataSource"/>

</property>

<property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>

<!--applicationContextSchedulerContextKey: 是org.springframework.scheduling.quartz.SchedulerFactoryBean这个类中把spring上下 文以key/value的方式存放在了quartz的上下文中了,可以用applicationContextSchedulerContextKey所定义的key得到对应的spring上下文-->

<property name="triggers">

<list>

<ref bean="cronTrigger"/>

<!-- <ref bean="simpleTrigger"/> -->

</list>

</property>

<property name="configLocation" value="classpath:quartz.properties"/>

<!--configLocation:用于指明quartz的配置文件的位置 -->

</bean>

<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">

<property name="jobDetail" ref="exampleJob"/>

<!-- run every morning at 6 AM -->

<property name="cronExpression" value="*/10 * * * * ?"/>

</bean>

<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">

<property name="jobClass" value="examples.ExampleJob"/>

<property name="durability" value="true" />

<property name="requestsRecovery" value="true" />

<property name="jobDataAsMap">

<map>

<entry key="timeout" value="5"/>

</map>

</property>

</bean>

examples.ExampleJob

/**

* @Title: ExampleJob.java

* @Package example

* @Description: TODO(用一句话描述该文件做什么)

* @author zjhua@hundsun.com

* @date 2016年3月11日 上午11:48:28

* @version V1.0

*/

package examples;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.quartz.JobExecutionContext;

import org.quartz.JobExecutionException;

import org.springframework.scheduling.quartz.QuartzJobBean;

/**

* @author zjhua

*

*/

public class ExampleJob extends QuartzJobBean {

private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");

private int timeout;

/**

* Setter called after the ExampleJob is instantiated

* with the value from the JobDetailFactoryBean (5)

*/

public void setTimeout(int timeout) {  //会自动从bean配置中注入

this.timeout = timeout;

}

protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {

String dt = sdf.format(new Date());

System.out.println(ctx.getJobDetail().getJobDataMap().get("timeout"));  //会自动从bean配置中设置进来

System.out.println(dt + "ExampleJob===========");

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println(dt + "ExampleJob定时任务结束");

}

}

//测试类

/**

* @Title: SpringTest.java

* @Package com.cyl

* @Description: TODO(用一句话描述该文件做什么)

* @author zjhua@hundsun.com

* @date 2016年3月10日 上午9:12:27

* @version V1.0

*/

package com.cyl;

import javax.sql.DataSource;

import org.quartz.JobKey;

import org.quartz.Scheduler;

import org.quartz.SchedulerException;

import org.quartz.impl.StdSchedulerFactory;

import org.quartz.impl.matchers.GroupMatcher;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.scheduling.quartz.SchedulerFactoryBean;

/**

* @author zjhua

*

*/

public class SpringTest {

public static void main(String[] args) {

ApplicationContext context = new ClassPathXmlApplicationContext(

new String[] { "services.xml" });

/*

TaskExecutorExample taskExecutor = context

.getBean(com.cyl.TaskExecutorExample.class);

taskExecutor.printMessages();

DataSource dataSource = context.getBean(DataSource.class);

JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

long begin = System.currentTimeMillis();

for (int i=0;i<2000;i++) {

int countOfActorsNamedJoe = jdbcTemplate.queryForObject("select count(*) from t1 where a = ?",Integer.class,new String[] {"1"});

System.out.print(countOfActorsNamedJoe);

}

System.out.println("");

long end = System.currentTimeMillis();

System.out.println(end-begin);

*/

SchedulerFactoryBean bean = context.getBean(SchedulerFactoryBean.class);

try {

//Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

//System.out.println(scheduler.getSchedulerName());

System.out.println(bean.getScheduler().getSchedulerName());

for(String group : bean.getScheduler().getJobGroupNames()) {

GroupMatcher<JobKey> groupMatcher = GroupMatcher.groupEquals(group);

for(JobKey jobKey : bean.getScheduler().getJobKeys(groupMatcher)) {

System.out.println("Found job identified by: " + jobKey);

}

}

try {

//Thread.sleep(60);

//System.out.println("定时任务暂停");

//bean.getScheduler().pauseAll();  //可以scheduler级别、触发器级别、任务级别,可以查询状态等各种信息

Thread.sleep(60);

//bean.getScheduler().resumeAll();

//System.out.println("定时任务重新开启");

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

//Thread.sleep(20000);

//scheduler.shutdown();

//System.out.println(scheduler.getSchedulerName() + "已关闭!");

} catch (SchedulerException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

其他需要注意的点:更改了quartz.properties或者spring配置文件,重启时,现有数据库中的quartz任务定义不会被更新,如果希望更新它们的话,需要通过quartz API进行更新,或者重建quartz表并重启应用。

其他定时任务以及触发器操作

调度器暂停

bean.getScheduler().pauseAll();

删除触发器

bean.getScheduler().unscheduleJob(new TriggerKey("cronTrigger","DEFAULT"));

删除任务

bean.getScheduler().deleteJob(new JobKey("exampleJob","DEFAULT"));

创建任务

JobDataMap jobDataMap = new JobDataMap();

jobDataMap.put("timeout", 5);

JobDetail jd = JobBuilder.newJob(examples.ExampleJob.class)

.setJobData(jobDataMap).withIdentity(new JobKey("exampleJob","DEFAULT")).requestRecovery(true).storeDurably(true).build();

创建触发器

CronTriggerImpl trigger = new CronTriggerImpl();

try {

trigger.setCronExpression("*/20 * * * * ?");

trigger.setKey(new TriggerKey("cronTrigger","DEFAULT"));

开始调度触发器

bean.getScheduler().scheduleJob(jd,trigger);

知道上述API之后,就可以在spring的配置文件中不包含任何的trigger以及jobdetail定义,而是根据数据库中的配置进行动态管理(当然,我们也是采用这种方法)。

完整的定时任务解决方案Spring集成+定时任务本身管理+DB持久化+集群的更多相关文章

  1. 使用Docker构建持续集成与自动部署的Docker集群

    为什么使用Docker " 从我个人使用的角度讲的话  部署来的更方便 只要构建过一次环境 推送到镜像仓库 迁移起来也是分分钟的事情 虚拟化让集群的管理和控制部署都更方便 hub.docke ...

  2. SpringBoot学习笔记(13)----使用Spring Session+redis实现一个简单的集群

    session集群的解决方案: 1.扩展指定server 利用Servlet容器提供的插件功能,自定义HttpSession的创建和管理策略,并通过配置的方式替换掉默认的策略.缺点:耦合Tomcat/ ...

  3. Spring Boot+redis存储session,满足集群部署、分布式系统的session共享

    本文讲述spring-boot工程中使用spring-session机制进行安全认证,并且通过redis存储session,满足集群部署.分布式系统的session共享. 原文链接:https://w ...

  4. spring boot下JedisCluster方式连接Redis集群的配置

    最近在使用springboot做项目,使用redis做缓存.在外网开发的时候redis服务器没有使用集群配置,所有就是用了RedisTemplate的方式进行连接redis服务器.但是项目代码挪到内网 ...

  5. Spring Boot使用Spring Data Redis操作Redis(单机/集群)

    说明:Spring Boot简化了Spring Data Redis的引入,只要引入spring-boot-starter-data-redis之后会自动下载相应的Spring Data Redis和 ...

  6. SpringCloud学习笔记(16)----Spring Cloud Netflix之Hystrix Dashboard+Turbine集群监控

    前言: 上一节中,我们使用Hystrix Dashboard,只能看到单个应用内的服务信息.在生产环境中,我们经常是集群状态,所以我们需要用到Turbine这一应用. 作用:汇总系统内的多个服务的数据 ...

  7. spring cloud:搭建基于consul的服务提供者集群(spring cloud hoxton sr8 / spring boot 2.3.4)

    一,搭建基于consul的服务提供者集群 1,consul集群,共3个实例: 2, 服务提供者集群:共2个实例: 3,服务消费者:一个实例即可 4,consul集群的搭建,请参考: https://w ...

  8. Quartz cron 表达式(linux 定时器,java 定时任务,spring task定时任务)

    原文地址:https://blog.csdn.net/feng27156/article/details/39293403 Quartz cron 表达式的格式十分类似于 UNIX cron 格式,但 ...

  9. Spring集成log4j日志管理

    原文地址:http://blog.csdn.net/naruto1021/article/details/7969535 在使用Spring框架的时候,我们可以很方便的配置log4j来进行日志管理. ...

随机推荐

  1. python入门学习课程推荐

    最近在学习自动化,学习过程中,越来越发现coding能力的重要性,不会coding,基本不能开展自动化测试(自动化工具只是辅助). 故:痛定思痛,先花2个星期将python基础知识学习后,再进入自动化 ...

  2. 快速入门系列--深入理解C#

    C#语言在近些年得到了长足的方法,代码风格越来越简洁美观,例如常用的泛型及其约束.可空类型.隐式类型.匿名类型和委托等,通过下面的表格可以对这部分相对简单的特性的使用有一个初步的了解. 特性 示例 泛 ...

  3. java基础复习 - 自动装箱

    Integer a = 127; // 将整形127装箱对象 Integer b = 127; // 同上 System.out.print( a==b ); // true System.out.p ...

  4. 基于Metronic的Bootstrap开发框架经验总结(8)--框架功能总体界面介绍

    在前面介绍了一系列的<基于Metronic的Bootstrap开发框架经验总结>的随笔文章,随笔主要是介绍各个知识点的内容,对框架的总体性界面没有很好的阐述,本篇随笔主要介绍这个Boots ...

  5. Js杂谈-DOM

    前言 对jQuery的依赖.导致js的原生方法的淡忘,如果是封装自己的库,那势必要用到js的许多原生方法.从Jquery强大的dom处理开始,我们开始回顾javascript那些古老而坚挺的DOM方法 ...

  6. Java多线程系列--“JUC集合”05之 ConcurrentSkipListMap

    概要 本章对Java.util.concurrent包中的ConcurrentSkipListMap类进行详细的介绍.内容包括:ConcurrentSkipListMap介绍ConcurrentSki ...

  7. 新手学习Python时常见的错误

    最近学习Python,现在把一些常见的错误总结如下: 1)忘记在 if , elif , else , for , while , class ,def 声明末尾添加 :(导致 "Synta ...

  8. Spring MVC 学习总结(三)——请求处理方法Action详解

    Spring MVC中每个控制器中可以定义多个请求处理方法,我们把这种请求处理方法简称为Action,每个请求处理方法可以有多个不同的参数,以及一个多种类型的返回结果. 一.Action参数类型 如果 ...

  9. IIS 服务器下载apk文件报404错

    文件路径什么都对,可就是提示404错误,最后问题出在了IIS的MIME上,按照下面的办法即可解决. 1.在 IIS 管理器中,右键单击要为其添加 MIME 类型的网站或网站目录,单击"属性& ...

  10. Windows Azure Cloud Service (38) 微软IaaS与PaaS比较

    <Windows Azure Platform 系列文章目录> 最近一直想总结Azure IaaS和PaaS的区别与比较,写个博文详细说明一下.建议读者在阅读之前,先熟悉微软PaaS和Ia ...