四)Spring + Quartz
使用Quartz默认配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"> <task:executor id="threadPoolTaskExecutor" pool-size="1" /> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory">
<bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory" />
</property>
<property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
<property name="startupDelay" value="0" />
<property name="overwriteExistingJobs" value="true" />
<property name="exposeSchedulerInRepository" value="true" />
<property name="taskExecutor" ref="threadPoolTaskExecutor" />
<property name="triggers">
<list>
<ref bean="cronTrigger_1" />
</list>
</property>
</bean> <bean id="cronTrigger_1"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail_1" />
<property name="cronExpression" value="* * * * * ?" />
</bean>
<bean id="jobDetail_1"
class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="cn.zno.job.Breathe" />
</bean>
<bean id="breath" class="cn.zno.job.Breathe" />
</beans>
/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.scheduling.quartz; import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import javax.sql.DataSource; import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.RemoteScheduler;
import org.quartz.impl.SchedulerRepository;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.simpl.SimpleThreadPool;
import org.quartz.spi.JobFactory; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.scheduling.SchedulingException;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; /**
* {@link FactoryBean} that creates and configures a Quartz {@link org.quartz.Scheduler},
* manages its lifecycle as part of the Spring application context, and exposes the
* Scheduler as bean reference for dependency injection.
*
* <p>Allows registration of JobDetails, Calendars and Triggers, automatically
* starting the scheduler on initialization and shutting it down on destruction.
* In scenarios that just require static registration of jobs at startup, there
* is no need to access the Scheduler instance itself in application code.
*
* <p>For dynamic registration of jobs at runtime, use a bean reference to
* this SchedulerFactoryBean to get direct access to the Quartz Scheduler
* ({@code org.quartz.Scheduler}). This allows you to create new jobs
* and triggers, and also to control and monitor the entire Scheduler.
*
* <p>Note that Quartz instantiates a new Job for each execution, in
* contrast to Timer which uses a TimerTask instance that is shared
* between repeated executions. Just JobDetail descriptors are shared.
*
* <p>When using persistent jobs, it is strongly recommended to perform all
* operations on the Scheduler within Spring-managed (or plain JTA) transactions.
* Else, database locking will not properly work and might even break.
* (See {@link #setDataSource setDataSource} javadoc for details.)
*
* <p>The preferred way to achieve transactional execution is to demarcate
* declarative transactions at the business facade level, which will
* automatically apply to Scheduler operations performed within those scopes.
* Alternatively, you may add transactional advice for the Scheduler itself.
*
* <p>Compatible with Quartz 2.1.4 and higher, as of Spring 4.1.
*
* @author Juergen Hoeller
* @since 18.02.2004
* @see #setDataSource
* @see org.quartz.Scheduler
* @see org.quartz.SchedulerFactory
* @see org.quartz.impl.StdSchedulerFactory
* @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean
*/
public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBean<Scheduler>,
BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean, SmartLifecycle { public static final String PROP_THREAD_COUNT = "org.quartz.threadPool.threadCount"; public static final int DEFAULT_THREAD_COUNT = 10; private static final ThreadLocal<ResourceLoader> configTimeResourceLoaderHolder =
new ThreadLocal<ResourceLoader>(); private static final ThreadLocal<Executor> configTimeTaskExecutorHolder =
new ThreadLocal<Executor>(); private static final ThreadLocal<DataSource> configTimeDataSourceHolder =
new ThreadLocal<DataSource>(); private static final ThreadLocal<DataSource> configTimeNonTransactionalDataSourceHolder =
new ThreadLocal<DataSource>(); /**
* Return the ResourceLoader for the currently configured Quartz Scheduler,
* to be used by ResourceLoaderClassLoadHelper.
* <p>This instance will be set before initialization of the corresponding
* Scheduler, and reset immediately afterwards. It is thus only available
* during configuration.
* @see #setApplicationContext
* @see ResourceLoaderClassLoadHelper
*/
public static ResourceLoader getConfigTimeResourceLoader() {
return configTimeResourceLoaderHolder.get();
} /**
* Return the TaskExecutor for the currently configured Quartz Scheduler,
* to be used by LocalTaskExecutorThreadPool.
* <p>This instance will be set before initialization of the corresponding
* Scheduler, and reset immediately afterwards. It is thus only available
* during configuration.
* @see #setTaskExecutor
* @see LocalTaskExecutorThreadPool
*/
public static Executor getConfigTimeTaskExecutor() {
return configTimeTaskExecutorHolder.get();
} /**
* Return the DataSource for the currently configured Quartz Scheduler,
* to be used by LocalDataSourceJobStore.
* <p>This instance will be set before initialization of the corresponding
* Scheduler, and reset immediately afterwards. It is thus only available
* during configuration.
* @see #setDataSource
* @see LocalDataSourceJobStore
*/
public static DataSource getConfigTimeDataSource() {
return configTimeDataSourceHolder.get();
} /**
* Return the non-transactional DataSource for the currently configured
* Quartz Scheduler, to be used by LocalDataSourceJobStore.
* <p>This instance will be set before initialization of the corresponding
* Scheduler, and reset immediately afterwards. It is thus only available
* during configuration.
* @see #setNonTransactionalDataSource
* @see LocalDataSourceJobStore
*/
public static DataSource getConfigTimeNonTransactionalDataSource() {
return configTimeNonTransactionalDataSourceHolder.get();
} private Class<? extends SchedulerFactory> schedulerFactoryClass = StdSchedulerFactory.class; private String schedulerName; private Resource configLocation; private Properties quartzProperties; private Executor taskExecutor; private DataSource dataSource; private DataSource nonTransactionalDataSource; private Map<String, ?> schedulerContextMap; private ApplicationContext applicationContext; private String applicationContextSchedulerContextKey; private JobFactory jobFactory; private boolean jobFactorySet = false; private boolean autoStartup = true; private int startupDelay = 0; private int phase = Integer.MAX_VALUE; private boolean exposeSchedulerInRepository = false; private boolean waitForJobsToCompleteOnShutdown = false; private Scheduler scheduler; /**
* Set the Quartz SchedulerFactory implementation to use.
* <p>Default is {@link StdSchedulerFactory}, reading in the standard
* {@code quartz.properties} from {@code quartz.jar}.
* To use custom Quartz properties, specify the "configLocation"
* or "quartzProperties" bean property on this FactoryBean.
* @see org.quartz.impl.StdSchedulerFactory
* @see #setConfigLocation
* @see #setQuartzProperties
*/
public void setSchedulerFactoryClass(Class<? extends SchedulerFactory> schedulerFactoryClass) {
Assert.isAssignable(SchedulerFactory.class, schedulerFactoryClass);
this.schedulerFactoryClass = schedulerFactoryClass;
} /**
* Set the name of the Scheduler to create via the SchedulerFactory.
* <p>If not specified, the bean name will be used as default scheduler name.
* @see #setBeanName
* @see org.quartz.SchedulerFactory#getScheduler()
* @see org.quartz.SchedulerFactory#getScheduler(String)
*/
public void setSchedulerName(String schedulerName) {
this.schedulerName = schedulerName;
} /**
* Set the location of the Quartz properties config file, for example
* as classpath resource "classpath:quartz.properties".
* <p>Note: Can be omitted when all necessary properties are specified
* locally via this bean, or when relying on Quartz' default configuration.
* @see #setQuartzProperties
*/
public void setConfigLocation(Resource configLocation) {
this.configLocation = configLocation;
} /**
* Set Quartz properties, like "org.quartz.threadPool.class".
* <p>Can be used to override values in a Quartz properties config file,
* or to specify all necessary properties locally.
* @see #setConfigLocation
*/
public void setQuartzProperties(Properties quartzProperties) {
this.quartzProperties = quartzProperties;
} /**
* Set the Spring TaskExecutor to use as Quartz backend.
* Exposed as thread pool through the Quartz SPI.
* <p>Can be used to assign a JDK 1.5 ThreadPoolExecutor or a CommonJ
* WorkManager as Quartz backend, to avoid Quartz's manual thread creation.
* <p>By default, a Quartz SimpleThreadPool will be used, configured through
* the corresponding Quartz properties.
* @see #setQuartzProperties
* @see LocalTaskExecutorThreadPool
* @see org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
* @see org.springframework.scheduling.commonj.WorkManagerTaskExecutor
*/
public void setTaskExecutor(Executor taskExecutor) {
this.taskExecutor = taskExecutor;
} /**
* Set the default DataSource to be used by the Scheduler. If set,
* this will override corresponding settings in Quartz properties.
* <p>Note: If this is set, the Quartz settings should not define
* a job store "dataSource" to avoid meaningless double configuration.
* <p>A Spring-specific subclass of Quartz' JobStoreCMT will be used.
* It is therefore strongly recommended to perform all operations on
* the Scheduler within Spring-managed (or plain JTA) transactions.
* Else, database locking will not properly work and might even break
* (e.g. if trying to obtain a lock on Oracle without a transaction).
* <p>Supports both transactional and non-transactional DataSource access.
* With a non-XA DataSource and local Spring transactions, a single DataSource
* argument is sufficient. In case of an XA DataSource and global JTA transactions,
* SchedulerFactoryBean's "nonTransactionalDataSource" property should be set,
* passing in a non-XA DataSource that will not participate in global transactions.
* @see #setNonTransactionalDataSource
* @see #setQuartzProperties
* @see #setTransactionManager
* @see LocalDataSourceJobStore
*/
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
} /**
* Set the DataSource to be used by the Scheduler <i>for non-transactional access</i>.
* <p>This is only necessary if the default DataSource is an XA DataSource that will
* always participate in transactions: A non-XA version of that DataSource should
* be specified as "nonTransactionalDataSource" in such a scenario.
* <p>This is not relevant with a local DataSource instance and Spring transactions.
* Specifying a single default DataSource as "dataSource" is sufficient there.
* @see #setDataSource
* @see LocalDataSourceJobStore
*/
public void setNonTransactionalDataSource(DataSource nonTransactionalDataSource) {
this.nonTransactionalDataSource = nonTransactionalDataSource;
} /**
* Register objects in the Scheduler context via a given Map.
* These objects will be available to any Job that runs in this Scheduler.
* <p>Note: When using persistent Jobs whose JobDetail will be kept in the
* database, do not put Spring-managed beans or an ApplicationContext
* reference into the JobDataMap but rather into the SchedulerContext.
* @param schedulerContextAsMap Map with String keys and any objects as
* values (for example Spring-managed beans)
* @see JobDetailFactoryBean#setJobDataAsMap
*/
public void setSchedulerContextAsMap(Map<String, ?> schedulerContextAsMap) {
this.schedulerContextMap = schedulerContextAsMap;
} /**
* Set the key of an ApplicationContext reference to expose in the
* SchedulerContext, for example "applicationContext". Default is none.
* Only applicable when running in a Spring ApplicationContext.
* <p>Note: When using persistent Jobs whose JobDetail will be kept in the
* database, do not put an ApplicationContext reference into the JobDataMap
* but rather into the SchedulerContext.
* <p>In case of a QuartzJobBean, the reference will be applied to the Job
* instance as bean property. An "applicationContext" attribute will
* correspond to a "setApplicationContext" method in that scenario.
* <p>Note that BeanFactory callback interfaces like ApplicationContextAware
* are not automatically applied to Quartz Job instances, because Quartz
* itself is responsible for the lifecycle of its Jobs.
* @see JobDetailFactoryBean#setApplicationContextJobDataKey
* @see org.springframework.context.ApplicationContext
*/
public void setApplicationContextSchedulerContextKey(String applicationContextSchedulerContextKey) {
this.applicationContextSchedulerContextKey = applicationContextSchedulerContextKey;
} /**
* Set the Quartz JobFactory to use for this Scheduler.
* <p>Default is Spring's {@link AdaptableJobFactory}, which supports
* {@link java.lang.Runnable} objects as well as standard Quartz
* {@link org.quartz.Job} instances. Note that this default only applies
* to a <i>local</i> Scheduler, not to a RemoteScheduler (where setting
* a custom JobFactory is not supported by Quartz).
* <p>Specify an instance of Spring's {@link SpringBeanJobFactory} here
* (typically as an inner bean definition) to automatically populate a job's
* bean properties from the specified job data map and scheduler context.
* @see AdaptableJobFactory
* @see SpringBeanJobFactory
*/
public void setJobFactory(JobFactory jobFactory) {
this.jobFactory = jobFactory;
this.jobFactorySet = true;
} /**
* Set whether to automatically start the scheduler after initialization.
* <p>Default is "true"; set this to "false" to allow for manual startup.
*/
public void setAutoStartup(boolean autoStartup) {
this.autoStartup = autoStartup;
} /**
* Return whether this scheduler is configured for auto-startup. If "true",
* the scheduler will start after the context is refreshed and after the
* start delay, if any.
*/
@Override
public boolean isAutoStartup() {
return this.autoStartup;
} /**
* Specify the phase in which this scheduler should be started and
* stopped. The startup order proceeds from lowest to highest, and
* the shutdown order is the reverse of that. By default this value
* is Integer.MAX_VALUE meaning that this scheduler starts as late
* as possible and stops as soon as possible.
*/
public void setPhase(int phase) {
this.phase = phase;
} /**
* Return the phase in which this scheduler will be started and stopped.
*/
@Override
public int getPhase() {
return this.phase;
} /**
* Set the number of seconds to wait after initialization before
* starting the scheduler asynchronously. Default is 0, meaning
* immediate synchronous startup on initialization of this bean.
* <p>Setting this to 10 or 20 seconds makes sense if no jobs
* should be run before the entire application has started up.
*/
public void setStartupDelay(int startupDelay) {
this.startupDelay = startupDelay;
} /**
* Set whether to expose the Spring-managed {@link Scheduler} instance in the
* Quartz {@link SchedulerRepository}. Default is "false", since the Spring-managed
* Scheduler is usually exclusively intended for access within the Spring context.
* <p>Switch this flag to "true" in order to expose the Scheduler globally.
* This is not recommended unless you have an existing Spring application that
* relies on this behavior. Note that such global exposure was the accidental
* default in earlier Spring versions; this has been fixed as of Spring 2.5.6.
*/
public void setExposeSchedulerInRepository(boolean exposeSchedulerInRepository) {
this.exposeSchedulerInRepository = exposeSchedulerInRepository;
} /**
* Set whether to wait for running jobs to complete on shutdown.
* <p>Default is "false". Switch this to "true" if you prefer
* fully completed jobs at the expense of a longer shutdown phase.
* @see org.quartz.Scheduler#shutdown(boolean)
*/
public void setWaitForJobsToCompleteOnShutdown(boolean waitForJobsToCompleteOnShutdown) {
this.waitForJobsToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
} @Override
public void setBeanName(String name) {
if (this.schedulerName == null) {
this.schedulerName = name;
}
} @Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
} //---------------------------------------------------------------------
// Implementation of InitializingBean interface
//--------------------------------------------------------------------- @Override
public void afterPropertiesSet() throws Exception {
if (this.dataSource == null && this.nonTransactionalDataSource != null) {
this.dataSource = this.nonTransactionalDataSource;
} if (this.applicationContext != null && this.resourceLoader == null) {
this.resourceLoader = this.applicationContext;
} // Create SchedulerFactory instance...
SchedulerFactory schedulerFactory = BeanUtils.instantiateClass(this.schedulerFactoryClass);
initSchedulerFactory(schedulerFactory); if (this.resourceLoader != null) {
// Make given ResourceLoader available for SchedulerFactory configuration.
configTimeResourceLoaderHolder.set(this.resourceLoader);
}
if (this.taskExecutor != null) {
// Make given TaskExecutor available for SchedulerFactory configuration.
configTimeTaskExecutorHolder.set(this.taskExecutor);
}
if (this.dataSource != null) {
// Make given DataSource available for SchedulerFactory configuration.
configTimeDataSourceHolder.set(this.dataSource);
}
if (this.nonTransactionalDataSource != null) {
// Make given non-transactional DataSource available for SchedulerFactory configuration.
configTimeNonTransactionalDataSourceHolder.set(this.nonTransactionalDataSource);
} // Get Scheduler instance from SchedulerFactory.
try {
this.scheduler = createScheduler(schedulerFactory, this.schedulerName);
populateSchedulerContext(); if (!this.jobFactorySet && !(this.scheduler instanceof RemoteScheduler)) {
// Use AdaptableJobFactory as default for a local Scheduler, unless when
// explicitly given a null value through the "jobFactory" bean property.
this.jobFactory = new AdaptableJobFactory();
}
if (this.jobFactory != null) {
if (this.jobFactory instanceof SchedulerContextAware) {
((SchedulerContextAware) this.jobFactory).setSchedulerContext(this.scheduler.getContext());
}
this.scheduler.setJobFactory(this.jobFactory);
}
} finally {
if (this.resourceLoader != null) {
configTimeResourceLoaderHolder.remove();
}
if (this.taskExecutor != null) {
configTimeTaskExecutorHolder.remove();
}
if (this.dataSource != null) {
configTimeDataSourceHolder.remove();
}
if (this.nonTransactionalDataSource != null) {
configTimeNonTransactionalDataSourceHolder.remove();
}
} registerListeners();
registerJobsAndTriggers();
} /**
* Load and/or apply Quartz properties to the given SchedulerFactory.
* @param schedulerFactory the SchedulerFactory to initialize
*/
private void initSchedulerFactory(SchedulerFactory schedulerFactory) throws SchedulerException, IOException {
if (!(schedulerFactory instanceof StdSchedulerFactory)) {
if (this.configLocation != null || this.quartzProperties != null ||
this.taskExecutor != null || this.dataSource != null) {
throw new IllegalArgumentException(
"StdSchedulerFactory required for applying Quartz properties: " + schedulerFactory);
}
// Otherwise assume that no initialization is necessary...
return;
} Properties mergedProps = new Properties(); if (this.resourceLoader != null) {
mergedProps.setProperty(StdSchedulerFactory.PROP_SCHED_CLASS_LOAD_HELPER_CLASS,
ResourceLoaderClassLoadHelper.class.getName());
} if (this.taskExecutor != null) {
mergedProps.setProperty(StdSchedulerFactory.PROP_THREAD_POOL_CLASS,
LocalTaskExecutorThreadPool.class.getName());
}
else {
// Set necessary default properties here, as Quartz will not apply
// its default configuration when explicitly given properties.
mergedProps.setProperty(StdSchedulerFactory.PROP_THREAD_POOL_CLASS, SimpleThreadPool.class.getName());
mergedProps.setProperty(PROP_THREAD_COUNT, Integer.toString(DEFAULT_THREAD_COUNT));
} if (this.configLocation != null) {
if (logger.isInfoEnabled()) {
logger.info("Loading Quartz config from [" + this.configLocation + "]");
}
PropertiesLoaderUtils.fillProperties(mergedProps, this.configLocation);
} CollectionUtils.mergePropertiesIntoMap(this.quartzProperties, mergedProps); if (this.dataSource != null) {
mergedProps.put(StdSchedulerFactory.PROP_JOB_STORE_CLASS, LocalDataSourceJobStore.class.getName());
} // Make sure to set the scheduler name as configured in the Spring configuration.
if (this.schedulerName != null) {
mergedProps.put(StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME, this.schedulerName);
} ((StdSchedulerFactory) schedulerFactory).initialize(mergedProps);
} /**
* Create the Scheduler instance for the given factory and scheduler name.
* Called by {@link #afterPropertiesSet}.
* <p>The default implementation invokes SchedulerFactory's {@code getScheduler}
* method. Can be overridden for custom Scheduler creation.
* @param schedulerFactory the factory to create the Scheduler with
* @param schedulerName the name of the scheduler to create
* @return the Scheduler instance
* @throws SchedulerException if thrown by Quartz methods
* @see #afterPropertiesSet
* @see org.quartz.SchedulerFactory#getScheduler
*/
protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName)
throws SchedulerException { // Override thread context ClassLoader to work around naive Quartz ClassLoadHelper loading.
Thread currentThread = Thread.currentThread();
ClassLoader threadContextClassLoader = currentThread.getContextClassLoader();
boolean overrideClassLoader = (this.resourceLoader != null &&
!this.resourceLoader.getClassLoader().equals(threadContextClassLoader));
if (overrideClassLoader) {
currentThread.setContextClassLoader(this.resourceLoader.getClassLoader());
}
try {
SchedulerRepository repository = SchedulerRepository.getInstance();
synchronized (repository) {
Scheduler existingScheduler = (schedulerName != null ? repository.lookup(schedulerName) : null);
Scheduler newScheduler = schedulerFactory.getScheduler();
if (newScheduler == existingScheduler) {
throw new IllegalStateException("Active Scheduler of name '" + schedulerName + "' already registered " +
"in Quartz SchedulerRepository. Cannot create a new Spring-managed Scheduler of the same name!");
}
if (!this.exposeSchedulerInRepository) {
// Need to remove it in this case, since Quartz shares the Scheduler instance by default!
SchedulerRepository.getInstance().remove(newScheduler.getSchedulerName());
}
return newScheduler;
}
}
finally {
if (overrideClassLoader) {
// Reset original thread context ClassLoader.
currentThread.setContextClassLoader(threadContextClassLoader);
}
}
} /**
* Expose the specified context attributes and/or the current
* ApplicationContext in the Quartz SchedulerContext.
*/
private void populateSchedulerContext() throws SchedulerException {
// Put specified objects into Scheduler context.
if (this.schedulerContextMap != null) {
this.scheduler.getContext().putAll(this.schedulerContextMap);
} // Register ApplicationContext in Scheduler context.
if (this.applicationContextSchedulerContextKey != null) {
if (this.applicationContext == null) {
throw new IllegalStateException(
"SchedulerFactoryBean needs to be set up in an ApplicationContext " +
"to be able to handle an 'applicationContextSchedulerContextKey'");
}
this.scheduler.getContext().put(this.applicationContextSchedulerContextKey, this.applicationContext);
}
} /**
* Start the Quartz Scheduler, respecting the "startupDelay" setting.
* @param scheduler the Scheduler to start
* @param startupDelay the number of seconds to wait before starting
* the Scheduler asynchronously
*/
protected void startScheduler(final Scheduler scheduler, final int startupDelay) throws SchedulerException {
if (startupDelay <= 0) {
logger.info("Starting Quartz Scheduler now");
scheduler.start();
}
else {
if (logger.isInfoEnabled()) {
logger.info("Will start Quartz Scheduler [" + scheduler.getSchedulerName() +
"] in " + startupDelay + " seconds");
}
Thread schedulerThread = new Thread() {
@Override
public void run() {
try {
Thread.sleep(startupDelay * 1000);
}
catch (InterruptedException ex) {
// simply proceed
}
if (logger.isInfoEnabled()) {
logger.info("Starting Quartz Scheduler now, after delay of " + startupDelay + " seconds");
}
try {
scheduler.start();
}
catch (SchedulerException ex) {
throw new SchedulingException("Could not start Quartz Scheduler after delay", ex);
}
}
};
schedulerThread.setName("Quartz Scheduler [" + scheduler.getSchedulerName() + "]");
schedulerThread.setDaemon(true);
schedulerThread.start();
}
} //---------------------------------------------------------------------
// Implementation of FactoryBean interface
//--------------------------------------------------------------------- @Override
public Scheduler getScheduler() {
return this.scheduler;
} @Override
public Scheduler getObject() {
return this.scheduler;
} @Override
public Class<? extends Scheduler> getObjectType() {
return (this.scheduler != null) ? this.scheduler.getClass() : Scheduler.class;
} @Override
public boolean isSingleton() {
return true;
} //---------------------------------------------------------------------
// Implementation of SmartLifecycle interface
//--------------------------------------------------------------------- @Override
public void start() throws SchedulingException {
if (this.scheduler != null) {
try {
startScheduler(this.scheduler, this.startupDelay);
}
catch (SchedulerException ex) {
throw new SchedulingException("Could not start Quartz Scheduler", ex);
}
}
} @Override
public void stop() throws SchedulingException {
if (this.scheduler != null) {
try {
this.scheduler.standby();
}
catch (SchedulerException ex) {
throw new SchedulingException("Could not stop Quartz Scheduler", ex);
}
}
} @Override
public void stop(Runnable callback) throws SchedulingException {
stop();
callback.run();
} @Override
public boolean isRunning() throws SchedulingException {
if (this.scheduler != null) {
try {
return !this.scheduler.isInStandbyMode();
}
catch (SchedulerException ex) {
return false;
}
}
return false;
} //---------------------------------------------------------------------
// Implementation of DisposableBean interface
//--------------------------------------------------------------------- /**
* Shut down the Quartz scheduler on bean factory shutdown,
* stopping all scheduled jobs.
*/
@Override
public void destroy() throws SchedulerException {
logger.info("Shutting down Quartz Scheduler");
this.scheduler.shutdown(this.waitForJobsToCompleteOnShutdown);
} }
org.springframework.scheduling.quartz.SchedulerFactoryBean
的全部属性如下图:
详解:
applicationContextSchedulerContextKey
Register ApplicationContext in Scheduler context.
从Scheduler上下文中获取ApplicationContext, 通过其指定的key获取。
startupDelay
延迟秒
overwriteExistingJobs
重写已存在的任务(我认为会更新数据库)
dataSource
设置数据源
configLocation
设置配置文件例如:classpath:quartz/quartz.properties
exposeSchedulerInRepository
监控
taskExecutor
执行器
triggers
触发器
四)Spring + Quartz的更多相关文章
- spring quartz 配置实现定时任务 详解
一. 编写定时任务JAVA类 比如: public class QuartzJob { public QuartzJob(){ System.out.println(" ...
- Spring+Quartz 实现定时任务的配置方法
Spring+Quartz 实现定时任务的配置方法 整体介绍 一.Quartz介绍 在企业应用中,我们经常会碰到时间任务调度的需求,比如每天凌晨生成前天报表,每小时生成一次汇总数据等等.Quartz是 ...
- spring quartz分布式任务计划
spring quartz分布式任务计划 环境: 通过maven管理的spring mvc工程,且已经成功连接数据库. 数据库表结构 /*Table structure for table `qrtz ...
- 基于spring+quartz的分布式定时任务框架
问题背景 我公司是一个快速发展的创业公司,目前有200人,主要业务是旅游和酒店相关的,应用迭代更新周期比较快,因此,开发人员花费了更多的时间去更=跟上迭代的步伐,而缺乏了对整个系统的把控 没有集群之前 ...
- Spring Quartz
Spring Quartz Quartz是一个强大的企业级任务调度框架,Spring中继承并简化了Quartz,下面就看看在Spring中怎样配置Quartz: 首先我们来写一个被调度的类: pac ...
- [Spring] - Quartz定时任务 - Annotation
Spring + Quartz可以使用annoation方式: 1.AppJob类: package com.my.quartz.testquartz1; import org.springframe ...
- Spring+quartz 实现定时任务job集群配置
为什么要有集群定时任务? 因为如果多server都触发相同任务,又同时执行,那在99%的场景都是不适合的.比如银行每晚24:00都要汇总营业额.像下面3台server同时进行汇总,最终计算结果可能是真 ...
- atititt.java定时任务框架选型Spring Quartz 注解总结
atititt.java定时任务框架选型Spring Quartz 总结 1. .Spring Quartz (ati recomm) 1 2. Spring Quartz具体配置 2 2.1. 增 ...
- 解决Spring+Quartz无法自动注入bean问题
问题 我们有时需要执行一些定时任务(如数据批处理),比较常用的技术框架有Spring + Quartz中.无奈此方式有个问题:Spring Bean无法自动注入. 环境:Spring3.2.2 + Q ...
- Spring+quartz集群配置,Spring定时任务集群,quartz定时任务集群
Spring+quartz集群配置,Spring定时任务集群,quartz定时任务集群 >>>>>>>>>>>>>> ...
随机推荐
- 如何重启 Windows 10 子系统(WSL) ubuntu
如何重启 Windows 10 子系统(WSL) ubuntu WSL 子系统是基于 LxssManager 服务运行的. 只需要将 LxssManager 重启即可. 可以做成一个 bat 文件. ...
- java IDE 中安装 lombok plugin 插件,并使用 @Slf4j 注解打印日志初体验
lombok 插件介绍: IntelliJ IDEA官方插件页面:https://plugins.jetbrains.com/plugin/6317-lombok-plugin 使用lombok之后, ...
- MyEclipse下Tomcat无法部署项目 finish按钮无法点击
问题描述:MyEclipse环境下,使用Tomcat进行项目部署时,无法部署项目,finish按钮无法点击. 问题原因:Context-root丢失 解决办法:右击项目->properties- ...
- WebKit的已实施srcset图像响应属性
WebKit已经发布了一些官方新闻,终于落实srcset的属性.作为W3C的响应图像社区组的主席,我一直希望这一刻到来有一段时间了.所以,对所有参与方是个好消息,用户浏览网页时的体验是最重要的. 所有 ...
- [DP题]放苹果
放苹果(DP做法) 描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法.输入第一行是测试数据的数目t(0 < ...
- find 和 find_all 用法
soup = BeautifulSoup(requests.get(url).text, 'html.parser') soup.find('span', class_='item_hot_topic ...
- Hive-表连接
Hive只支持等值连接,即ON子句中使用等号连接,不支持非等值连接. Hive内置的数据存储类型,TextFile, SequenceFile, ORC(列式存储) 如果连接语句中有WHERE子句,会 ...
- Oracle VM VirtualBox安裝Windows 2000失败
问题: VirtualBox下安装Windows2000,设置网络后进入最后一步,复制组件……然后就是重启:再试还是重启! 解决: 在Oracle网站上查了一下资料:http://www.virt ...
- 管理Linux服务器的用户和组
管理Linux服务器的用户和组 Linux操作系统是一个多用户多任务的操作系统,允许多个用户同时登录到系统,使用系统资源. 为了使所有用户的工作顺利进行,保护每个用户的文件和进程,规范每个用户的权限, ...
- JSP自定义业务标签
自定义标签: package cn.hv.tag; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; ...