`
kissroom112
  • 浏览: 31198 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

spring quartz 集群模式

阅读更多
本文是基于quartz-1.6.6版本

当我们用到集群模式部署项目的时候就要考虑到定时任务的集群问题,
这里有四种解决方案:
第一:自己通过代码实现(比如通过不同机器的jvm参数配置或者自己建立任务表去控制执行)
第二:确保一台机器启动quartz
第三:将quartz单独抽取部署单实例
第四:用quartz自身提供的解决方案

本文采用方案四。

quartz集群各节点之间是通过同一个数据库实例的同一套表来感知彼此的。

第一步:创建quartz所需的表
sql文件位于:quartz-1.6.6\docs\dbTables,选择自己的数据库类型对应的sql文件进行创建。

第二步:配置quartz.properties文件,quartz-1.6.6.zip\src\testrig\quartz.properties是个比较完整的demo文件,可以拿来直接修改,修改过后放到自己项目的类目目录下即可。
这里贴出我的项目的该配置文件,项目用的是oracle数据库、weblogic服务器。具体配置项的不再做过多解释

#============================================================================
# Configure Main Scheduler Properties  
#============================================================================

org.quartz.scheduler.instanceName = KpiScheduler
org.quartz.scheduler.instanceId = AUTO

#============================================================================
# Configure ThreadPool  
#============================================================================

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 50
#org.quartz.threadPool.threadPriority = 5

#============================================================================
# Configure JobStore  
#============================================================================

org.quartz.jobStore.misfireThreshold = 60000

org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.WebLogicDelegate
org.quartz.jobStore.useProperties=false
#org.quartz.jobStore.dataSource=dataSource
org.quartz.jobStore.tablePrefix=QRTZ_
#?true????? Scheduler ?????????????
#true为集群模式,集群模式下,此处一定注意配置为true
org.quartz.jobStore.isClustered=true

#============================================================================
# Other Example Delegates
#============================================================================
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.CloudscapeDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v6Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v7Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DriverDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.HSQLDBDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.MSSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PointbaseDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.WebLogicDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate

#============================================================================
# Configure Datasources  
#============================================================================

#org.quartz.dataSource.myDS.driver = org.postgresql.Driver
#org.quartz.dataSource.myDS.URL = jdbc:postgresql://localhost:5432/postgres
#org.quartz.dataSource.myDS.user = quartz
#org.quartz.dataSource.myDS.password = quartz
#org.quartz.dataSource.myDS.driver = org.postgresql.Driver
#org.quartz.dataSource.myDS.URL = jdbc:postgresql://localhost:5432/postgres
#org.quartz.dataSource.myDS.user = quartz
#org.quartz.dataSource.myDS.password = quartz
#org.quartz.dataSource.myDS.maxConnections = 5
#org.quartz.dataSource.myDS.validationQuery=

#============================================================================
# Configure Plugins 
#============================================================================

#org.quartz.plugin.shutdownHook.class = org.quartz.plugins.management.ShutdownHookPlugin
#org.quartz.plugin.shutdownHook.cleanShutdown = true


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



第三步:配置spring的bean

<!-- 由于需要支持集群环境 spring自带的org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean不支持集群,所以用自己写的(后面会贴出org.xxx.xxx.quartz.MethodInvokingJobDetailFactoryBean.java的内容) -->
	<bean id="jobGetLoginMemberNum"
		class="org.xxx.xxx.quartz.MethodInvokingJobDetailFactoryBean">
		<property name="targetObject" ref="imsService" />
		<property name="targetMethod" value="getLoginMemberNum" />
		<!-- 为 true 当Quartz服务被中止后,再次启动或集群中其他机器接手任务时会尝试恢复执行之前未完成的所有任务 -->
		<property name="shouldRecover" value="false" />
		<!-- 是否允许任务并发执行。当值为false时,表示必须等到前一个线程处理完毕后才再启一个新的线 默认为true -->
		<property name="concurrent" value="true"/>
	</bean>
	<bean id="cronTriggerGetLoginMemberNum"
		class="org.springframework.scheduling.quartz.CronTriggerBean">
		<property name="jobDetail" ref="jobGetLoginMemberNum" />
		<!-- 每小时第45分钟执行 -->
		<property name="cronExpression">
			<value>0 45 0/1 * * ? *</value>
		</property>
	</bean>

<bean
		class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<!-- 集群环境需要数据源 -->
		<property name="dataSource" ref="dataSource"/>
		<!-- 集群环境配置  如果不需要可以给注释了 -->
		<property name="configLocation"	value="classpath:quartz.properties" />
		<!-- 事件触发器 -->
		<property name="triggers">
			<list>
				<ref local="cronTriggerGetLoginMemberNum" /><!-- 登录人数 -->
			</list>
		</property>
		<property name="applicationContextSchedulerContextKey"
			value="applicationContext " />
	</bean>


至此,大功告成!

org.xxx.xxx.quartz.MethodInvokingJobDetailFactoryBean.java
package org.xxx.xxx.quartz;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.StatefulJob;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.MethodInvoker;

/**
 * This is a cluster safe Quartz/Spring FactoryBean implementation, which produces a JobDetail implementation that can invoke any no-arg method on any Class.
 * <p>
 * Use this Class instead of the MethodInvokingJobDetailBeanFactory Class provided by Spring when deploying to a web environment like Tomcat.
 * <p>
 * <b>Implementation</b><br>
 * Instead of associating a MethodInvoker with a JobDetail or a Trigger object, like Spring's MethodInvokingJobDetailFactoryBean does, I made the [Stateful]MethodInvokingJob, which is not persisted in the database, create the MethodInvoker when the [Stateful]MethodInvokingJob is created and executed.
 * <p>
 * A method can be invoked one of several ways:
 * <ul>
 * <li>The name of the Class to invoke (targetClass) and the static method to invoke (targetMethod) can be specified.
 * <li>The Object to invoke (targetObject) and the static or instance method to invoke (targetMethod) can be specified (the targetObject must be Serializable when concurrent=="false").
 * <li>The Class and static Method to invoke can be specified in one property (staticMethod). example: staticMethod = "example.ExampleClass.someStaticMethod"
 * <br><b>Note:</b>  An Object[] of method arguments can be specified (arguments), but the Objects must be Serializable if concurrent=="false".
 * </ul>  
 * <p>
 * I wrote MethodInvokingJobDetailFactoryBean, because Spring's MethodInvokingJobDetailFactoryBean does not produce Serializable
 * JobDetail objects, and as a result cannot be deployed into a clustered environment like Tomcat (as is documented within the Class).
 * <p>
 * <b>Example</b>
 * <code>
 * <ul>
 * 	&lt;bean id="<i>exampleTrigger</i>" class="org.springframework.scheduling.quartz.CronTriggerBean"&gt;
 * <ul>
	<i>&lt;!-- Execute example.ExampleImpl.fooBar() at 2am every day --&gt;</i><br>
	&lt;property name="<a href="http://www.opensymphony.com/quartz/api/org/quartz/CronTrigger.html">cronExpression</a>" value="0 0 2 * * ?" /&gt;<br>
	&lt;property name="jobDetail"&gt;
	<ul>
	&lt;bean class="frameworkx.springframework.scheduling.quartz.<b>MethodInvokingJobDetailFactoryBean</b>"&gt;
	<ul>
	&lt;property name="concurrent" value="<i>false</i>"/&gt;<br>
	&lt;property name="targetClass" value="<i>example.ExampleImpl</i>" /&gt;<br>
	&lt;property name="targetMethod" value="<i>fooBar</i>" /&gt;
	</ul>
	&lt;/bean&gt;
	</ul>
	&lt;/property&gt;
	</ul>
	&lt;/bean&gt;
	<p>
	&lt;bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"&gt;
	<ul>
	&lt;property name="triggers"&gt;
	<ul>
	&lt;list&gt;
	<ul>
	&lt;ref bean="<i>exampleTrigger</i>" /&gt;
	</ul>
	&lt;/list&gt;
	</ul>
	&lt;/property&gt;
	</ul>
	&lt;/bean&gt;
	</ul>
 * </code>
 * In this example we created a MethodInvokingJobDetailFactoryBean, which will produce a JobDetail Object with the jobClass property set to StatefulMethodInvokingJob.class (concurrent=="false"; Set to MethodInvokingJob.class when concurrent=="true"), which will in turn invoke the static <code>fooBar</code>() method of the "<code>example.ExampleImpl</code>" Class. The Scheduler is the heart of the whole operation; without it, nothing will happen.
 * <p>
 * For more information on <code>cronExpression</code> syntax visit <a href="http://www.opensymphony.com/quartz/api/org/quartz/CronTrigger.html">http://www.opensymphony.com/quartz/api/org/quartz/CronTrigger.html</a>
 * 
 * @author Stephen M. Wick
 *
 * @see #afterPropertiesSet()
 */
public class MethodInvokingJobDetailFactoryBean implements FactoryBean, BeanNameAware, InitializingBean
{
	private Log logger = LogFactory.getLog(getClass());

	/**
	 * The JobDetail produced by the <code>afterPropertiesSet</code> method of this Class will be assigned to the Group specified by this property.  Default: Scheduler.DEFAULT_GROUP 
	 * @see #afterPropertiesSet()
	 * @see Scheduler#DEFAULT_GROUP
	 */
	private String group = Scheduler.DEFAULT_GROUP;

	/**
	 * Indicates whether or not the Bean Method should be invoked by more than one Scheduler at the specified time (like when deployed to a cluster, and/or when there are multiple Spring ApplicationContexts in a single JVM<i> - Tomcat 5.5 creates 2 or more instances of the DispatcherServlet (a pool), which in turn creates a separate Spring ApplicationContext for each instance of the servlet</i>) 
	 * <p>
	 * Used by <code>afterPropertiesSet</code> to set the JobDetail.jobClass to MethodInvokingJob.class or StatefulMethodInvokingJob.class when true or false, respectively.  Default: true 
	 * @see #afterPropertiesSet()
	 */
	private boolean concurrent = true;
	
	/** Used to set the JobDetail.durable property.  Default: false
	 * <p>Durability - if a job is non-durable, it is automatically deleted from the scheduler once there are no longer any active triggers associated with it.
	 * @see <a href="http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html">http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html</a> 
	 * @see #afterPropertiesSet() 
	 */
	private boolean durable = false;
	
	/**
	 * Used by <code>afterPropertiesSet</code> to set the JobDetail.volatile property.  Default: false
	 * <p>Volatility - if a job is volatile, it is not persisted between re-starts of the Quartz scheduler.
	 * <p>I set the default to false to be the same as the default for a Quartz Trigger.  An exception is thrown 
	 * when the Trigger is non-volatile and the Job is volatile.  If you want volatility, then you must set this property, and the Trigger's volatility property, to true.
	 * @see <a href="http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html">http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html</a>
	 * @see #afterPropertiesSet() 
	 */
	private boolean volatility = false;
	
	/** 
	 * Used by <code>afterPropertiesSet</code> to set the JobDetail.requestsRecovery property.  Default: false<BR>
	 * <p>RequestsRecovery - if a job "requests recovery", and it is executing during the time of a 'hard shutdown' of the scheduler (i.e. the process it is running within crashes, or the machine is shut off), then it is re-executed when the scheduler is started again. In this case, the JobExecutionContext.isRecovering() method will return true. 
	 * @see <a href="http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html">http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html</a> 
	 * @see #afterPropertiesSet() 
	 */
	private boolean shouldRecover = false;
	
	/**
	 * A list of names of JobListeners to associate with the JobDetail object created by this FactoryBean.
	 *
	 * @see #afterPropertiesSet() 
	 **/
	private String[] jobListenerNames;
	
	/** The name assigned to this bean in the Spring ApplicationContext.
	 * Used by <code>afterPropertiesSet</code> to set the JobDetail.name property.
	 * @see afterPropertiesSet()
	 * @see JobDetail#setName(String)
	 **/
	private String beanName;
	
	/**
	 * The JobDetail produced by the <code>afterPropertiesSet</code> method, and returned by the <code>getObject</code> method of the Spring FactoryBean interface.
	 * @see #afterPropertiesSet()
	 * @see #getObject()
	 * @see FactoryBean
	 **/
	private JobDetail jobDetail;
	
	/**
	 * The name of the Class to invoke.
	 **/
	private String targetClass;

	/**
	 * The Object to invoke.
	 * <p>
	 * {@link #targetClass} or targetObject must be set, but not both.
	 * <p>
	 * This object must be Serializable when {@link #concurrent} is set to false.
	 */
	private Object targetObject;
	
	/**
	 * The instance method to invoke on the Class or Object identified by the targetClass or targetObject property, respectfully.
	 * <p>
	 * targetMethod or {@link #staticMethod} should be set, but not both. 
	 **/
	private String targetMethod;
	
	/**
	 * The static method to invoke on the Class or Object identified by the targetClass or targetObject property, respectfully.
	 * <p>
	 * {@link #targetMethod} or staticMethod should be set, but not both. 
	 */
	private String staticMethod;

	/**
	 * Method arguments provided to the {@link #targetMethod} or {@link #staticMethod} specified.
	 * <p>
	 * All arguments must be Serializable when {@link #concurrent} is set to false.
	 * <p>
	 * I strongly urge you not to provide arguments until Quartz 1.6.1 has been released if you are using a JDBCJobStore with
	 * Microsoft SQL Server. There is a bug in version 1.6.0 that prevents Quartz from Serializing the Objects in the JobDataMap
	 * to the database.  The workaround is to set the property "org.opensymphony.quaryz.useProperties = true" in your quartz.properties file,
	 * which tells Quartz not to serialize Objects in the JobDataMap, but to instead expect all String compliant values.
	 */
	private Object[] arguments;

	/**
	 * Get the targetClass property.
	 * @see #targetClass
	 * @return targetClass
	 */
	public String getTargetClass()
	{
		return targetClass;
	}

	/**
	 * Set the targetClass property.
	 * @see #targetClass
	 */
	public void setTargetClass(String targetClass)
	{
		this.targetClass = targetClass;
	}

	/**
	 * Get the targetMethod property.
	 * @see #targetMethod
	 * @return targetMethod
	 */
	public String getTargetMethod()
	{
		return targetMethod;
	}

	/**
	 * Set the targetMethod property.
	 * @see #targetMethod
	 */
	public void setTargetMethod(String targetMethod)
	{
		this.targetMethod = targetMethod;
	}

	/**
	 * @return jobDetail - The JobDetail that is created by the afterPropertiesSet method of this FactoryBean
	 * @see #jobDetail
	 * @see #afterPropertiesSet()
	 * @see FactoryBean#getObject()
	 */
	public Object getObject() throws Exception
	{
		return jobDetail;
	}

	/**
	 * @return JobDetail.class
	 * @see FactoryBean#getObjectType()
	 */
	public Class getObjectType()
	{
		return JobDetail.class;
	}

	/**
	 * @return true
	 * @see FactoryBean#isSingleton()
	 */
	public boolean isSingleton()
	{
		return true;
	}

	/**
	 * Set the beanName property.
	 * @see #beanName
	 * @see BeanNameAware#setBeanName(String)
	 */
	public void setBeanName(String beanName)
	{
		this.beanName = beanName;
	}

	/**
	 * Invoked by the Spring container after all properties have been set.
	 * <p>
	 * Sets the <code>jobDetail</code> property to a new instance of JobDetail
	 * <ul>
	 * <li>jobDetail.name is set to <code>beanName</code><br>
	 * <li>jobDetail.group is set to <code>group</code><br>
	 * <li>jobDetail.jobClass is set to MethodInvokingJob.class or StatefulMethodInvokingJob.class depending on whether the <code>concurrent</code> property is set to true or false, respectively.<br>
	 * <li>jobDetail.durability is set to <code>durable</code>
	 * <li>jobDetail.volatility is set to <code>volatility</code>
	 * <li>jobDetail.requestsRecovery is set to <code>shouldRecover</code>
	 * <li>jobDetail.jobDataMap["targetClass"] is set to <code>targetClass</code>
	 * <li>jobDetail.jobDataMap["targetMethod"] is set to <code>targetMethod</code>
	 * <li>Each JobListener name in <code>jobListenerNames</code> is added to the <code>jobDetail</code> object.
	 * </ul>
	 * <p>
	 * Logging occurs at the DEBUG and INFO levels; 4 lines at the DEBUG level, and 1 line at the INFO level.
	 * <ul>
	 * <li>DEBUG: start
	 * <li>DEBUG: Creating JobDetail <code>{beanName}</code>
	 * <li>DEBUG: Registering JobListener names with JobDetail object <code>{beanName}</code>
	 * <li>INFO: Created JobDetail: <code>{jobDetail}</code>; targetClass: <code>{targetClass}</code>; targetMethod: <code>{targetMethod}</code>;
	 * <li>DEBUG: end
	 * </ul>
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 * @see JobDetail
	 * @see #jobDetail
	 * @see #beanName
	 * @see #group
	 * @see MethodInvokingJob
	 * @see StatefulMethodInvokingJob
	 * @see #durable
	 * @see #volatility
	 * @see #shouldRecover
	 * @see #targetClass
	 * @see #targetMethod
	 * @see #jobListenerNames 
	 */
	public void afterPropertiesSet() throws Exception
	{
		try
		{
			logger.debug("start");
			
			logger.debug("Creating JobDetail "+beanName);
			jobDetail = new JobDetail();
			jobDetail.setName(beanName);
			jobDetail.setGroup(group);
			jobDetail.setJobClass(concurrent ? MethodInvokingJob.class : StatefulMethodInvokingJob.class);
			jobDetail.setDurability(durable);
			jobDetail.setVolatility(volatility);
			jobDetail.setRequestsRecovery(shouldRecover);
			if(targetClass!=null)
				jobDetail.getJobDataMap().put("targetClass", targetClass);
			if(targetObject!=null)
				jobDetail.getJobDataMap().put("targetObject", targetObject);
			if(targetMethod!=null)
				jobDetail.getJobDataMap().put("targetMethod", targetMethod);
			if(staticMethod!=null)
				jobDetail.getJobDataMap().put("staticMethod", staticMethod);
			if(arguments!=null)
				jobDetail.getJobDataMap().put("arguments", arguments);
			
			logger.debug("Registering JobListener names with JobDetail object "+beanName);
			if (this.jobListenerNames != null) {
				for (int i = 0; i < this.jobListenerNames.length; i++) {
					this.jobDetail.addJobListener(this.jobListenerNames[i]);
				}
			}
			logger.info("Created JobDetail: "+jobDetail+"; targetClass: "+targetClass+"; targetObject: "+targetObject+"; targetMethod: "+targetMethod+"; staticMethod: "+staticMethod+"; arguments: "+arguments+";");
		}
		finally
		{
			logger.debug("end");
		}
	}

	/**
	 * Setter for the concurrent property.
	 * 
	 * @param concurrent
	 * @see #concurrent
	 */
	public void setConcurrent(boolean concurrent)
	{
		this.concurrent = concurrent;
	}

	/**
	 * setter for the durable property.
	 * 
	 * @param durable
	 * 
	 * @see #durable
	 */
	public void setDurable(boolean durable)
	{
		this.durable = durable;
	}

	/**
	 * setter for the group property.
	 * 
	 * @param group
	 * 
	 * @see #group
	 */
	public void setGroup(String group)
	{
		this.group = group;
	}

	/**
	 * setter for the {@link #jobListenerNames} property.
	 * 
	 * @param jobListenerNames
	 * @see #jobListenerNames
	 */
	public void setJobListenerNames(String[] jobListenerNames)
	{
		this.jobListenerNames = jobListenerNames;
	}

	/**
	 * setter for the {@link #shouldRecover} property.
	 * 
	 * @param shouldRecover
	 * @see #shouldRecover
	 */
	public void setShouldRecover(boolean shouldRecover)
	{
		this.shouldRecover = shouldRecover;
	}

	/**
	 * setter for the {@link #volatility} property.
	 * 
	 * @param volatility
	 * @see #volatility
	 */
	public void setVolatility(boolean volatility)
	{
		this.volatility = volatility;
	}

	/**
	 * This is a cluster safe Job designed to invoke a method on any bean defined within the same Spring
	 * ApplicationContext.
	 * <p>
	 * The only entries this Job expects in the JobDataMap are "targetClass" and "targetMethod".<br>
	 * - It uses the value of the <code>targetClass</code> entry to get the desired bean from the Spring ApplicationContext.<br>
	 * - It uses the value of the <code>targetMethod</code> entry to determine which method of the Bean (identified by targetClass) to invoke.
	 * <p>
	 * It uses the static ApplicationContext in the MethodInvokingJobDetailFactoryBean,
	 * which is ApplicationContextAware, to get the Bean with which to invoke the method.
	 * <p>
	 * All Exceptions thrown from the execute method are caught and wrapped in a JobExecutionException.
	 * 
	 * @see MethodInvokingJobDetailFactoryBean#applicationContext
	 * @see #execute(JobExecutionContext)
	 * 
	 * @author Stephen M. Wick
	 */
	public static class MethodInvokingJob implements Job
	{
		protected Log logger = LogFactory.getLog(getClass());
		
		/**
		 * When invoked by a Quartz scheduler, <code>execute</code> invokes a method on a Class or Object in the JobExecutionContext provided.
		 * <p>
		 * <b>Implementation</b><br>
		 * The Class is identified by the "targetClass" entry in the JobDataMap of the JobExecutionContext provided.  If targetClass is specified, then targetMethod must be a static method.<br>
		 * The Object is identified by the 'targetObject" entry in the JobDataMap of the JobExecutionContext provided.  If targetObject is provided, then targetClass will be overwritten.  This Object must be Serializable when <code>concurrent</code> is set to false.<br>
		 * The method is identified by the "targetMethod" entry in the JobDataMap of the JobExecutionContext provided.<br>
		 * The "staticMethod" entry in the JobDataMap of the JobExecutionContext can be used to specify a Class and Method in one entry (ie: "example.ExampleClass.someStaticMethod")<br>
		 * The method arguments (an array of Objects) are identified by the "arguments" entry in the JobDataMap of the JobExecutionContext.  All arguments must be Serializable when <code>concurrent</code> is set to false.
		 * <p>
		 * Logging is provided at the DEBUG and INFO levels; 8 lines at the DEBUG level, and 1 line at the INFO level.
		 * @see Job#execute(JobExecutionContext)
		 */
		public void execute(JobExecutionContext context) throws JobExecutionException
		{
			try
			{
				logger.debug("start");
				String targetClass = context.getMergedJobDataMap().getString("targetClass");
				logger.debug("targetClass is "+targetClass);
				Class targetClassClass = null;
				if(targetClass!=null)
				{
					targetClassClass = Class.forName(targetClass); // Could throw ClassNotFoundException
				}
				Object targetObject = context.getMergedJobDataMap().get("targetObject");
				logger.debug("targetObject is "+targetObject);
				String targetMethod = context.getMergedJobDataMap().getString("targetMethod");
				logger.debug("targetMethod is "+targetMethod);
				String staticMethod = context.getMergedJobDataMap().getString("staticMethod");
				logger.debug("staticMethod is "+staticMethod);
				Object[] arguments = (Object[])context.getMergedJobDataMap().get("arguments");
				logger.debug("arguments are "+arguments);
				
				logger.debug("creating MethodInvoker");
				MethodInvoker methodInvoker = new MethodInvoker();
				methodInvoker.setTargetClass(targetClassClass);
				methodInvoker.setTargetObject(targetObject);
				methodInvoker.setTargetMethod(targetMethod);
				methodInvoker.setStaticMethod(staticMethod);
				methodInvoker.setArguments(arguments);
				methodInvoker.prepare();
				logger.info("Invoking: "+methodInvoker.getPreparedMethod().toGenericString());
				methodInvoker.invoke();
			}
			catch(Exception e)
			{
				throw new JobExecutionException(e);
			}
			finally
			{
				logger.debug("end");
			}
		}
	}

	public static class StatefulMethodInvokingJob extends MethodInvokingJob implements StatefulJob
	{
		// No additional functionality; just needs to implement StatefulJob.
	}

	public Object[] getArguments()
	{
		return arguments;
	}

	public void setArguments(Object[] arguments)
	{
		this.arguments = arguments;
	}

	public String getStaticMethod()
	{
		return staticMethod;
	}

	public void setStaticMethod(String staticMethod)
	{
		this.staticMethod = staticMethod;
	}

	public void setTargetObject(Object targetObject)
	{
		this.targetObject = targetObject;
	}
}

分享到:
评论

相关推荐

    spring quartz集群配置

    总结,Spring Quartz集群配置涉及到多个步骤,包括选择合适的Job Store、配置Spring集成、定义定时任务以及优化集群设置。正确配置后,我们可以获得高可用和可扩展的定时任务调度系统,满足大规模分布式系统的需求。

    spring集成quartz集群配置

    在IT行业中,Spring框架是Java应用开发中的基石,而Quartz则是广泛...通过上述步骤,你已经掌握了Spring集成Quartz集群配置的基本概念。在实践中,根据具体需求调整配置,可以实现高效、稳定且可扩展的任务调度系统。

    Spring+Quartz 集群

    5. **集群配置**:为了实现高可用的Quartz集群,你需要配置多个节点共享同一个数据库存储的作业和触发器信息。Quartz支持多种持久化策略,如JDBC、RAMJobStore等,选择数据库存储能保证在集群中的任务状态一致性。 ...

    spring + quartz 集群配置

    java + quartz实现定时任务,实现集群配置,在集群环境下多节点运行定时Quartz定任务,就会存在重复处理任务的现象,为解决这一问题,下面我将介绍使用 Quartz 的 TASK ( 12 张表)实例化到数据库,基于数据库自动...

    spring boot quartz集群实现

    一个基于springboot的quartz集群dome。 向http://localhost:9090/job/addjob注入3个参数 类名:(及时定时任务的类如:com.ybjdw.site.job.NewJob) 组名:随意 定时启动方法:如“0/3 * * * * ?”(每3秒启动一次...

    quartz整合springbatch动态集群定时实现mysql参考

    在这个“quartz_springbatch_dynamic”项目中,我们将看到如何将这两个强大的工具结合起来,以实现动态集群环境中的定时任务执行,并使用MySQL作为数据存储。 Quartz是一个开源的作业调度框架,允许开发者创建、...

    Spring Quartz Job 集群 终极解决方案

    需要把app部署在多台服务器上,但只能让其中一台服务器的job执行,一台服务器挂了,另一台还能继续执行job,通过网上查找资料,都是java工程的方式,不好部署并测试,经过二天辛苦整合,终于整理成一个单spring web...

    quartz+spring分布式集群调度

    3. **监控和管理**: 实现对Quartz集群的监控,如任务状态、运行时性能等,以便及时发现和解决问题。 总结,Quartz+Spring的分布式集群调度方案能够帮助开发者构建稳定且可扩展的定时任务系统。通过合理配置和实践,...

    Quartz2.2.1和Spring3.1.1集群

    3. **集群配置**:在`org.quartz.properties`文件中,需要设置`org.quartz.jobStore.isClustered=true`来启用集群模式,并配置数据库连接信息,以便所有节点能够访问。 4. **监听器**:使用`SchedulerListener`和`...

    quartz+spring分布式集群

    - 考虑使用监控工具(如Prometheus+Grafana)监控Quartz集群的运行状态,以便及时发现和解决问题。 通过以上知识点的学习和实践,开发者可以熟练掌握在Spring环境中使用Quartz实现分布式集群的作业调度,提升系统...

    Springboot集成quartz集群

    本文章是关于springboot集成quartz集群的步骤,LZ亲测。

    spring+quartz定时集群支持

    至于数据库,Quartz集群需要一个共享的数据库存储job和trigger的信息,这就是`dbTables`文件所涉及的内容。Quartz会在数据库中创建一系列的表,用于存储任务元数据,如job信息、trigger信息等。这些表的设计和初始化...

    Quartz集群+spring data

    至于博文链接中的内容,虽然无法直接查看,但通常会包含如何在实际项目中设置Quartz集群和Spring Data集成的详细步骤,包括配置示例、代码示例以及可能遇到的问题和解决方案。 在使用过程中,可能会遇到如任务并发...

    SSH框架+Quartz集群

    集成Quartz集群需要配置Quartz的集群模式,包括共享的数据存储(如数据库)、集群节点间的通信机制(如JDBC Job Store)以及对Job和Trigger的一致性处理。在实际应用中,可能会使用如ZooKeeper这样的分布式协调服务...

    完美解决多应用服务器负载均衡环境下spring quartz同一定时任务重复执行问题

    3. **集群设置**:在`quartz.properties`中,启用集群模式,设置`org.quartz.scheduler.instanceName`为唯一的服务器标识,`org.quartz.scheduler.instanceId`设为`AUTO`,这样Quartz会自动获取当前服务器的唯一ID。...

    Spring+Quartz集群部署案例

    最近项目中使用了spring+Quartz定时任务、但是项目最近要集群部署、多个APP下如何利用Quartz 协调处理任务。 大家可以思考一下、现在有 A、B、C三个应用同时作为集群服务器对外统一提供服务、每个应用下各有一个...

    Spring Quartz1.8.x

    6. **并发和集群**:Quartz支持多线程和多服务器环境,Spring Quartz也继承了这一特性。通过集群配置,可以在多台服务器上共享任务调度,提高系统的可用性和可靠性。 7. **监控和管理**:Spring Quartz提供了Web...

Global site tag (gtag.js) - Google Analytics