Статьи

Весна и Кварц: Многозадачный Сервис Планирования

Планирование работы является настолько важным требованием для приложений. Особенно в крупных проектах работа с большим количеством рабочих мест может быть проблемой. Spring и Quartz принесли значительные выгоды для решения этой проблемы. В этой статье показано, как легко планировать несколько заданий с помощью Spring и Quartz.

Используемые технологии:

JDK 1.6.0_21
Весна 3.1.1
Кварц 1.8.5
Maven 3.0.2

ШАГ 1: СОЗДАТЬ MAVEN ПРОЕКТ
Maven проект создается как показано ниже. (Он может быть создан с помощью Maven или IDE Plug-in)

ШАГ 2: БИБЛИОТЕКИ
Spring-зависимости добавляются в pom.xml Maven.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<!-- Spring 3 dependencies -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
</dependency>

ШАГ 3: СОЗДАТЬ КЛАССЫ ЗАДАЧИ
Класс FirstTask создан.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.otv.task;
  
import org.apache.log4j.Logger;
  
/**
 * First Task
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public class FirstTask {
  
    private static Logger log = Logger.getLogger(FirstTask.class);
  
    /**
     * Execute this task
     *
     */
    public void execute() {
        log.debug("FirstTask runs successfully...");
    }
}

Класс SecondTask создан.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.otv.task;
  
import org.apache.log4j.Logger;
  
/**
 * Second Task
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public class SecondTask {
  
    private static Logger log = Logger.getLogger(SecondTask.class);
  
    /**
     * Execute this task
     *
     */
    public void execute() {
        log.debug("SecondTask runs successfully...");
    }
}

ШАГ 4: СОЗДАЙТЕ ИНТЕРФЕЙС ISchedulerService
Интерфейс ISchedulerService создан.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.otv.service;
  
/**
 * Scheduler Service Interface
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public interface ISchedulerService {
  
    /**
     * Execute First Task
     *
     * @param
     * @throws
     * @return
     */
    public void executeFirstTask();
  
    /**
     * Execute Second Task
     *
     * @param
     * @throws
     * @return
     */
    public void executeSecondTask();
}

ШАГ 5: СОЗДАНИЕ ПЛАНА Планировщика
Класс SchedulerService создается путем реализации интерфейса ISchedulerService. Этот сервис планирует задачи.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.otv.service;
  
import com.otv.task.FirstTask;
import com.otv.task.SecondTask;
  
/**
 * Scheduler Service Implementation
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public class SchedulerService implements ISchedulerService {
  
    private FirstTask  firstTask;
    private SecondTask secondTask;
  
    /**
     * Execute First Task
     *
     */
    public void executeFirstTask() {
        getFirstTask().execute();
    }
  
    /**
     * Execute Second Task
     *
     */
    public void executeSecondTask() {
        getSecondTask().execute();
    }
  
    /**
     * Get First Task
     *
     * @return FirstTask
     */
    public FirstTask getFirstTask() {
        return firstTask;
    }
  
    /**
     * Set First Task
     *
     * @param  firstTask First Task
     */
    public void setFirstTask(FirstTask firstTask) {
        this.firstTask = firstTask;
    }
  
    /**
     * Get Second Task
     *
     * @return SecondTask
     */
    public SecondTask getSecondTask() {
        return secondTask;
    }
  
    /**
     * Set Second Task
     *
     * @param  secondTask Second Task
     */
    public void setSecondTask(SecondTask secondTask) {
        this.secondTask = secondTask;
    }
}

ШАГ 6: СОЗДАЙТЕ КЛАСС ПРИЛОЖЕНИЙ
Класс приложения создан. Этот класс запускает приложение.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.otv.starter;
  
import org.springframework.context.support.ClassPathXmlApplicationContext;
  
/**
 * Application Starter Class
 *
 * @author  onlinetechvision.com
 * @since   24 Feb 2012
 * @version 1.0.0
 *
 */
public class Application {
  
    /**
     * Main method of the Application
     *
     */
    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("applicationContext.xml");
    }
}

ШАГ 7: ОПРЕДЕЛЕНИЕ КОНФИГУРАЦИЙ РАБОТЫ
Детали работы могут быть определены двумя способами в Spring. Используя MethodInvokingJobDetailFactoryBean или расширяя QuartzJobBean . В этом примере был использован метод MethodInvokingJobDetailFactoryBean. Свойства targetObject и targetMethod присваиваются методу MethodInvokingJobDetailFactoryBean .

01
02
03
04
05
06
07
08
09
10
<!-- Job Details-->
<bean id="FirstTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="SchedulerService" />
    <property name="targetMethod" value="executeFirstTask" />
</bean>
  
<bean id="SecondTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="SchedulerService" />
    <property name="targetMethod" value="executeSecondTask" />
</bean>

ШАГ 8: ОПРЕДЕЛЕНИЕ КОНФИГУРАЦИЙ ПУЛЬТА
Триггеры также могут быть определены двумя способами в Spring. Определив SimpleTriggerBean или CronTriggerBean . Когда используется SimpleTriggerBean , определяются свойства jobDetail , repeatInterval и startDelay . Когда используется CronTriggerBean, определяются свойства jobDetail и cronExpression . В этом примере интервал повторения первой задачи был установлен 5 секунд, а интервал повторения второй задачи был установлен 12 секунд .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<!-- Simple Trigger -->
<bean id="FirstSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
    <property name="jobDetail" ref="FirstTaskJobDetail" />
    <property name="repeatInterval" value="5000" />
    <property name="startDelay" value="1000" />
</bean>
  
<!-- <bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="SecondTaskJobDetail" />
        <property name="repeatInterval" value="12000" />
        <property name="startDelay" value="1000" />
    </bean> -->   
  
<!-- Cron Trigger -->
<bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
    <property name="jobDetail" ref="SecondTaskJobDetail" />
    <property name="cronExpression" value="0/12 * * * * ?" />
</bean>

ШАГ 9: ОПРЕДЕЛИТЕ ПланировщикФабрикаБИОН КОНФИГУРАЦИИ
Наконец, сведения о задании и триггеры настраиваются путем создания SchedulerFactoryBean .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="jobDetails">
       <list>
          <ref bean="FirstTaskJobDetail" />
          <ref bean="SecondTaskJobDetail" />
       </list>
    </property>
    <property name="triggers">
       <list>
          <ref bean="FirstSimpleTrigger" />
          <ref bean="SecondSimpleTrigger" />
       </list>
    </property>
</bean>

ШАГ 10: СОЗДАТЬ applicationContext.xml
Весь контент applicationContext.xml показан ниже.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  
  
    <!-- Beans Declaration -->
    <bean id="FirstTask" class="com.otv.task.FirstTask"></bean>
    <bean id="SecondTask" class="com.otv.task.SecondTask"></bean>
  
    <bean id="SchedulerService" class="com.otv.service.SchedulerService">
        <property name="firstTask" ref="FirstTask" />
        <property name="secondTask" ref="SecondTask" />
    </bean>
  
    <!-- Job Details-->
    <bean id="FirstTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="SchedulerService" />
        <property name="targetMethod" value="executeFirstTask" />
    </bean>
  
    <bean id="SecondTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="SchedulerService" />
        <property name="targetMethod" value="executeSecondTask" />
    </bean>
  
    <!-- Simple Trigger -->
    <bean id="FirstSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="FirstTaskJobDetail" />
        <property name="repeatInterval" value="5000" />
        <property name="startDelay" value="1000" />
    </bean>
<!--
    <bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="SecondTaskJobDetail" />
        <property name="repeatInterval" value="12000" />
        <property name="startDelay" value="1000" />
    </bean>
-->
    <!-- Cron Trigger -->
    <bean id="SecondSimpleTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="SecondTaskJobDetail" />
        <property name="cronExpression" value="0/12 * * * * ?" />
    </bean>
  
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="jobDetails">
           <list>
              <ref bean="FirstTaskJobDetail" />
              <ref bean="SecondTaskJobDetail" />
           </list>
        </property>
        <property name="triggers">
           <list>
              <ref bean="FirstSimpleTrigger" />
              <ref bean="SecondSimpleTrigger" />
           </list>
        </property>
    </bean>
  
</beans>

ШАГ 11: ЗАПУСК ПРОЕКТА
После запуска Application Class будут показаны следующие выходные журналы:

01
02
03
04
05
06
07
08
09
10
11
12
13
25.02.2012 00:17:18 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:23 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:24 DEBUG (SecondTask.java:22) - SecondTask runs successfully...
25.02.2012 00:17:28 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:33 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:36 DEBUG (SecondTask.java:22) - SecondTask runs successfully...
25.02.2012 00:17:38 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:43 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:48 DEBUG (SecondTask.java:22) - SecondTask runs successfully...
25.02.2012 00:17:48 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:53 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:17:58 DEBUG (FirstTask.java:23) - FirstTask runs successfully...
25.02.2012 00:18:00 DEBUG (SecondTask.java:22) - SecondTask runs successfully...

ШАГ 12: СКАЧАТЬ

OTV_SpringQuartz_MultiJobScheduling

Справка: Multi-Job Scheduling Service с использованием Spring и Quartz от нашего партнера JCG