完整的定时任务解决方案Spring集成+定时任务本身管理+DB持久化+集群
完整的定时任务解决方案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持久化+集群的更多相关文章
- 使用Docker构建持续集成与自动部署的Docker集群
为什么使用Docker " 从我个人使用的角度讲的话 部署来的更方便 只要构建过一次环境 推送到镜像仓库 迁移起来也是分分钟的事情 虚拟化让集群的管理和控制部署都更方便 hub.docke ...
- SpringBoot学习笔记(13)----使用Spring Session+redis实现一个简单的集群
session集群的解决方案: 1.扩展指定server 利用Servlet容器提供的插件功能,自定义HttpSession的创建和管理策略,并通过配置的方式替换掉默认的策略.缺点:耦合Tomcat/ ...
- Spring Boot+redis存储session,满足集群部署、分布式系统的session共享
本文讲述spring-boot工程中使用spring-session机制进行安全认证,并且通过redis存储session,满足集群部署.分布式系统的session共享. 原文链接:https://w ...
- spring boot下JedisCluster方式连接Redis集群的配置
最近在使用springboot做项目,使用redis做缓存.在外网开发的时候redis服务器没有使用集群配置,所有就是用了RedisTemplate的方式进行连接redis服务器.但是项目代码挪到内网 ...
- Spring Boot使用Spring Data Redis操作Redis(单机/集群)
说明:Spring Boot简化了Spring Data Redis的引入,只要引入spring-boot-starter-data-redis之后会自动下载相应的Spring Data Redis和 ...
- SpringCloud学习笔记(16)----Spring Cloud Netflix之Hystrix Dashboard+Turbine集群监控
前言: 上一节中,我们使用Hystrix Dashboard,只能看到单个应用内的服务信息.在生产环境中,我们经常是集群状态,所以我们需要用到Turbine这一应用. 作用:汇总系统内的多个服务的数据 ...
- spring cloud:搭建基于consul的服务提供者集群(spring cloud hoxton sr8 / spring boot 2.3.4)
一,搭建基于consul的服务提供者集群 1,consul集群,共3个实例: 2, 服务提供者集群:共2个实例: 3,服务消费者:一个实例即可 4,consul集群的搭建,请参考: https://w ...
- Quartz cron 表达式(linux 定时器,java 定时任务,spring task定时任务)
原文地址:https://blog.csdn.net/feng27156/article/details/39293403 Quartz cron 表达式的格式十分类似于 UNIX cron 格式,但 ...
- Spring集成log4j日志管理
原文地址:http://blog.csdn.net/naruto1021/article/details/7969535 在使用Spring框架的时候,我们可以很方便的配置log4j来进行日志管理. ...
随机推荐
- CSS3_02之2D、3D动画
1.转换属性:transform:取值:transform-function(转换函数): 2.转换原点:默认元素的中心处:更改转换原点:transform-origin:取值:数字/百分比/关键字: ...
- 让AngularJS的$http 服务像jQuery.ajax()一样工作
让AngularJS的$http 服务像jQuery.ajax()一样工作 $http的post . 请求默认的content-Type=application/json . 提交的是json对象的字 ...
- scrollview 中嵌套多个listview的最好解决办法
在scrollview中嵌套多个listview的显示问题. 只需要调用如下的方法传入listview和adapter数据即可. /** * 动态设置ListView组建的高度 */ public s ...
- struts2DMI(动态方法调用)
struts2动态方法调用共有三种方式: 1.通过action元素的method属性指定访问该action时运行的方法 <package name="action" exte ...
- javascript学习目录
类型系统 [1]基本数据类型 [2]引用类型中的对象Object [3]引用类型中的数组Array [4]引用类型中的时间Date [5]函数Function [6]正则表达式RegExp [7]包装 ...
- Hadoop阅读笔记(三)——深入MapReduce排序和单表连接
继上篇了解了使用MapReduce计算平均数以及去重后,我们再来一探MapReduce在排序以及单表关联上的处理方法.在MapReduce系列的第一篇就有说过,MapReduce不仅是一种分布式的计算 ...
- log4net 中错误 System.Web.HttpException (0x80004005): 文件不存在
用日志组件,Global 中配置的输出最后一个错误信息,总是出现下面的错误信息: 2014-04-01 14:35:41,757 级别:ERROR 信息:[Exception]:System.Web. ...
- Android中BroadcastReceiver广播
BroadCastReceiver 简介 广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是通过调用 Context.sendBroadca ...
- C# 通过反射来动态创建泛型类型
C# 通过反射来动态创建泛型类型与创建普通类型的区别在于:泛型参数的处理 创建泛型类型存在三种情况: 第一种:知道泛型类型,但需要动态指定泛型参数: 第二种:知道泛型参数,但需要动态创建指定参数的泛型 ...
- JS魔法堂:彻底理解0.1 + 0.2 === 0.30000000000000004的背后
Brief 一天有个朋友问我“JS中计算0.7 * 180怎么会等于125.99999999998,坑也太多了吧!”那时我猜测是二进制表示数值时发生round-off error所导致,但并不清楚具体 ...