spring+mybatis+quartz叢集
1. 定義資料來源
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"init-method="init" destroy-method="close">
<!-- 基本屬性 url、user、password -->
<property name="url" value="${jdbc.url}"
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.pwd}"/>
<!-- 配置初始化大小、最小、最大 -->
<
<property name="minIdle" value="${jdbc.minPoolSize}"/>
<property name="maxActive" value="${jdbc.maxPoolSize}"/>
<!--
<property name="maxWait" value="10000"/>
<!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一個連線在池中最小生存的時間,單位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT '1' " />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 開啟PSCache,並且指定每個連線上PSCache的大小 -->
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize"value="20" />
</bean>
2. 定義schedulerFactoryBean
<bean name="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<!-- spring 管理的service注入-->
<propertyname="schedulerContextAsMap">
<map>
<entrykey="myService "value-ref="myService"/>
</map>
</property>
<property name="applicationContextSchedulerContextKey"value="applicationContext" />
<property name="quartzProperties">
<props>
<prop key="org.quartz.scheduler.instanceName">myJob</prop>
<prop key="org.quartz.scheduler.instanceId">AUTO</prop>
<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
<prop key="org.quartz.threadPool.threadCount">20</prop>
<prop key="org.quartz.threadPool.threadPriority">5</prop>
<prop key="org.quartz.jobStore.misfireThreshold">120000</prop>
<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
<prop key="org.quartz.jobStore.isClustered">true</prop>
<prop key="org.quartz.jobStore.clusterCheckinInterval">15000</prop>
<prop key="org.quartz.jobStore.maxMisfiresToHandleAtATime">1</prop>
<prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
</props>
</property>
</bean>
3. 初始化作業任務
public class QrtzJobInit {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
SchedulerFactoryBean schedulerFactoryBean;
@Autowired
QrtzJobLogic qrtzJobLogic;
public void init(){
Scheduler scheduler = schedulerFactoryBean.getScheduler();
QrtzJobPo cond = new QrtzJobPo();
cond.setJobStatus(EnumJobState.NORMAL.getKey());
try {
ResultPOListBean<QrtzJobPo> resultPOListBean = qrtzJobLogic.queryQrtzJobListByCond(cond);
if (resultPOListBean.getValue() == null || resultPOListBean.getValue().size() == 0)
return;
for (QrtzJobPo job : resultPOListBean.getValue()) {
addJob(job,scheduler);
}
if(scheduler.isShutdown())
scheduler.startDelayed(20);
logger.error("任務載入完成,size:{}",resultPOListBean.getValue().size());
} catch (Exception e) {
logger.error("異常:"+e);
}
}
private void addJob(QrtzJobPo job,Scheduler scheduler) {
try {
if (job == null) {
return;
}
if (!CronExpression.isValidExpression(job.getCronExpression())) {
logger.error("時間表達式錯誤,jobname={},jobgroup={},cronExpression={}", job.getJobName(), job.getJobGroup(),
job.getCronExpression());
return;
}
TriggerKey triggerKey = TriggerUtils.getTriggerKey(job);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (null == trigger) {
JobDetail jobDetail = JobUtils.getJob(job);
trigger = TriggerUtils.newTrigger(job);
scheduler.scheduleJob(jobDetail, trigger);
} else {
trigger =TriggerUtils.getTrigger(trigger, job);
scheduler.rescheduleJob(triggerKey, trigger);
}
} catch (SchedulerException e) {
logger.error("異常:"+e);
}
return;
}
4. 作業任務執行
public class QrtzJobFactory extends BaseJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
SchedulerContext schedulerContext = context.getScheduler().getContext();
JobDataMap map = context.getMergedJobDataMap();
Set<String> keys = map.keySet();
for (String key : keys) {
QrtzJobPo scheduleJob = (QrtzJobPo) context.getMergedJobDataMap().get(key);
logger.info("執行任務 :{} ,開始.", scheduleJob.getJobName());
executor(scheduleJob,schedulerContext);
logger.info("執行任務 :{} ,完成.", scheduleJob.getJobName());
}
Thread.sleep(60000);
} catch (InterruptedException | SchedulerException e) {
logger.error("異常:"+e);
}
}
}
executor方法說明,利用spring的反射工具實現動態執行任務
參考文章
1. http://itindex.net/detail/53315-spring-quartz-%E7%AE%A1%E7%90%86
2. http://itindex.net/detail/52939-quartz-%E9%9B%86%E7%BE%A4-spring
3. http://www.cnblogs.com/nick-huang/p/4862732.html
4. https://nkcoder.github.io/blog/20140627/quartz-tutorial-job-jobdetail/