美文网首页
spring+quartz+mysql集群

spring+quartz+mysql集群

作者: 那脸憔悴 | 来源:发表于2017-03-28 13:08 被阅读0次
    Quartz 中集群如何工作

    一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。
    意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。
    Quartz 应用是通过数据库表来感知到另一应用的。每个节点直接与数据库通信,若离开数据库将对其他节点一无所知。

    创建Quartz数据库表

    因为Quartz 集群依赖于数据库,所以必须首先创建Quartz数据库表。
    Quartz 包括了所有被支持的数据库平台的 SQL 脚本。在 quartz目录/docs/dbTables 目录下找到那些 SQL 脚本。
    这里使用tables_mysql_innodb.sql。

    配置文件
    1. 配置jdbc.properties文件
    #MySQL配置database.driver=com.mysql.jdbc.Driver
    database.url=jdbc:mysql://localhost:3306
    database.databaseName=quartz
    database.param=useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&rewriteBatchedStatements=true
    database.username=root
    database.password=0123456789
    #c3p0配置
    c3p0.initialPoolSize=10
    c3p0.minPoolSize=10
    c3p0.maxPoolSize=10
    c3p0.acquireIncrement=5
    c3p0.maxIdleTime=0
    c3p0.idleConnectionTestPeriod=1800
    c3p0.preferredTestQuery=select 1 from dual
    c3p0.testConnectionOnCheckout=false
    c3p0.testConnectionOnCheckin=true
    c3p0.maxStatementsPerConnection=0
    c3p0.numHelperThreads=32
    
    1. 配置spring的spring-dataSource.xml文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
                               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
                               http://www.springframework.org/schema/context
                               http://www.springframework.org/schema/context/spring-context-3.0.xsd">
        <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
                <list>
                    <value>classpath:config/jdbc.properties</value>
                </list>
            </property>
        </bean>
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
            <property name="driverClass" value="${database.driver}" />
           <property name="jdbcUrl" value="${database.url}/${database.databaseName}?${database.param}" />
           <property name="user" value="${database.username}" />
           <property name="password" value="${database.password}" />
            <property name="initialPoolSize" value="${c3p0.initialPoolSize}" />
            <property name="minPoolSize" value="${c3p0.minPoolSize}" />
           <property name="maxPoolSize" value="${c3p0.maxPoolSize}" />
            <property name="acquireIncrement" value="${c3p0.acquireIncrement}" />
            <property name="maxIdleTime" value="${c3p0.maxIdleTime}" />
            <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}" />
            <property name="preferredTestQuery" value="${c3p0.preferredTestQuery}" />
            <property name="testConnectionOnCheckout" value="${c3p0.testConnectionOnCheckout}" />
            <property name="testConnectionOnCheckin" value="${c3p0.testConnectionOnCheckin}" />
            <property name="maxStatementsPerConnection" value="${c3p0.maxStatementsPerConnection}" />
            <property name="numHelperThreads" value="${c3p0.numHelperThreads}" />
        </bean>
    </beans>
    
    1. 配置quartz.properties文件
    #============================================================================   
    # Configure Main Scheduler Properties     
    #============================================================================
    org.quartz.scheduler.instanceName = DefaultQuartzScheduler   
    #可为任何值,用在 JDBC JobStore 中来唯一标识实例,但是所有集群节点中必须相同。
    org.quartz.scheduler.instanceId = AUTO  
    #AUTO即可,基于主机名和时间戳来产生实例 ID
    #============================================================================   
    # Configure ThreadPool     
    #============================================================================
    org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool 
    org.quartz.threadPool.threadCount = 10 
    org.quartz.threadPool.threadPriority = 5 
    org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true 
    #============================================================================   
    # Configure JobStore     
    #============================================================================
    org.quartz.jobStore.misfireThreshold = 60000 
    org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 
    #属性为 JobStoreTX,将任务持久化到数据中。    
    #因为集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用Quartz 集群。    
    #这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储;你不能在集群中使用 RAMJobStore。  
    org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate 
    org.quartz.jobStore.tablePrefix = qrtz_ 
    org.quartz.jobStore.maxMisfiresToHandleAtATime=10 
    org.quartz.jobStore.isClustered = true  
    #你就告诉了Scheduler 实例要它参与到一个集群当中。这一属性会贯穿于调度框架的始终,用于修改集群环境中操作的默认行为。 
    org.quartz.jobStore.clusterCheckinInterval = 20000 
    #属性定义了Scheduler 实例检入到数据库中的频率(单位:毫秒)。默认值是 15000 (即15 秒)。
    
    1. 配置quartz的spring-quartz.xml文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
                               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
                               http://www.springframework.org/schema/context
                               http://www.springframework.org/schema/context/spring-context-3.0.xsd">
        <bean id="simpleService" class="com.hao.service.SimpleService" />  
        <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>
            <property name="dataSource" ref="dataSource" />
            <property name="configLocation" value="classpath:config/quartz.properties"/>
            <property name="triggers"> 
            <list>   
                <ref bean="trigger1"/> 
                <ref bean="trigger2"/>
            </list> 
         </property>
        </bean> 
        <bean id="jobDetail1" class="com.hao.MethodInvokingJobDetailFactoryBean"> 
        <property name="concurrent" value="true" /> 
            <property name="targetObject" ref="simpleService"/> 
            <property name="targetMethod" value="testMethod1"/> 
        <property name="shouldRecover" value="true"/> 
        </bean> 
        <bean id="trigger1" class="org.springframework.scheduling.quartz.CronTriggerBean"> 
            <property name="jobDetail" ref="jobDetail1"/>
            <!-- 每分钟执行1次 -->
            <property name="cronExpression" value="0 0/1 * * * ?"/> 
        </bean>    
        <bean id="jobDetail2" class="com.hao.MethodInvokingJobDetailFactoryBean"> 
        <property name="concurrent" value="true" /> 
            <property name="targetObject" ref="simpleService"/> 
            <property name="targetMethod" value="testMethod2"/>
        <property name="shouldRecover" value="true"/> 
        </bean> 
        <bean id="trigger2" class="org.springframework.scheduling.quartz.CronTriggerBean"> 
            <property name="jobDetail" ref="jobDetail2"/> 
            <property name="cronExpression" value="0 0/1 * * * ?"/> 
        </bean>   
    </beans>
    
    创建Job测试服务类
    package com.hao.service;
    import java.io.Serializable;
    public class SimpleService implements Serializable {
        private static final long serialVersionUID = 1L;
        public void testMethod1() {
            //这里执行定时调度业务  
            System.out.println("testMethod1.......1");
        }
        public void testMethod2() {
            System.err.println("testMethod2.......2");
        }
    }
    

    因为Job需要持久化到数据库中,SimpleService必须实现Serializable接口。

    运行Quartz集群
    package com.hao;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    public class Test {
        public static void main(String[] args) {
            new ClassPathXmlApplicationContext(new String[]{"classpath:config/spring/spring-dataSource.xml","classpath:config/spring/spring-quartz.xml"});  
        }
    }
    

    MethodInvokingJobDetailFactoryBean.java

    package com.hao;
    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;\n }\n\n   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+mysql集群

          本文链接:https://www.haomeiwen.com/subject/rhrjottx.html