IT_Programming/Dev Libs & Framework

[펌] Spring - Quartz를 사용하여 스케쥴러 구현하기

JJun ™ 2013. 4. 5. 18:33

 


 출처: http://javastore.tistory.com/96


 

 

가끔 서버에서 주기적으로 어떠한 작업을 하고자 할때 리눅스에서는 크론탭을 사용하여 주기적으로

떠한 작업을 처리합니다.

이런 주기적 작업을 처리하기위해 Spring에서 지원해 주는 Quartz스케쥴러를 통해 크론탭과 같은 역할을

하는 스케쥴러를 작성할 수 있습니다.

이번에는 Spring 과 Quartz를 연동하여 스케줄러를 작성해 보겠습니다.

작업순서는
스프링 기본 세팅 -> Quartz 세팅 순으로 작업하겠습니다.


1. 스프링 기본 설정


1) springframework.org 로 이동하셔서 스프링 라이브러리를 다운 받습니다.

 

 

위와 같은 페이지가 뜨면 해당사항을 입력하시고 Access Download 를 클릭하셔서 다운로드 페이지로

이동합니다. (귀찮으신 분들은 하단의 파란색으로 "download page"를 선택하시면 입력하시지 않고도

다운로드 페이지로 이동하실수 있습니다.

많은 버전의 라이브러리 중 spring-framework-2.5.6.SEC02.zip 를 다운 받습니다.

다른 버전을 다운 받으셔도 상관없습니다만 버전에 따라 세팅 내용이 조금 씩 달라지므로

같은 버전의 라이브러리로 진행하는 것이 나을 것같네요~^^.


2) 이렇게 라이브러리까지 다운로드 받고 나면 Eclipse와 같은 IDE에서 Dynamic Web Project를

    선택하여 Project를 한개 생성합니다.
    (저는 SpringQuartz 라는 이름으로 생성했습니다.)


3) 프로젝트가 생성되면 프로젝트 안에 /WEB-INF/lib 디렉토리에 스프링 라이브러리를

    압축 푼 곳에 있는 dist/spring.jar 파일을 추가합니다.


* 팁 : 프로젝트를 진행하다 보면 위와같이 라이브러리 버전이 없는 jar파일을 그냥 추가하는 경우가 있는데

         나중에 라이브러리를 업데이트 해야 할일이 생기게 되면 위와같이 spring.jar 라고 되어있으면

         지금 적용되어 있는 버전이 몇 인지 알수가 없습니다. 그렇기 때문에 항상 라이브러리 추가하실때는

         추가하시는 라이브러리의 버전 번호를 파일이름 뒤에 추가하는 습관을 들이 시는게 좋습니다. 
         ex) spring-2.5.6.jar


4) 프로젝트 안에 생성된 web.xml에 Spring을 사용하기 위한 세팅을 추가해 줍니다.
  * 저는 Quartz를 사용하기 위한 최소한의 Spring 세팅을 해놓았기 때문에 세팅 내용이 단순합니다.

   만약 웹프로젝트와 함께 Quartz를 사용하신다면 웹에 맞게 설정하시고 사용하셔야 함을

   알려드립니다.^^

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"  
 xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
 </listener> 
 <context-param>  
  <param-name>contextConfigLocation</param-name>  
  <param-value>/WEB-INF/config/applicationContext*.xml</param-value>
 </context-param>
</web-app>

 

 

5) 쿼츠 라이브러리를 다운로드 받고 라이브러리를 추가해 줍니다.

    쿼츠 라이브러리 다운로드 하신다음 압축을 풀어 줍니다.

    해당 라이브러리를 프로젝트의 lib 디렉토리에 복사하여 넣어줍니다.

 

 - quartz-all-1.8.3.jar
 - 압축푼 lib 디렉터리의 log4j-1.2.14.jar
 - 압축푼 lib 디렉터리의 slf4j-api-1.5.10.jar
 - 압축푼 lib 디렉터리의 slf4j-log4j12-1.5.10.jar


를 추가 해 줍니다.


마지막으로 apache의 commons-logging-1.1.1.jar 를 다운로드 하셔서

위와 같이 프로젝트의 lib에 추가해주시면 라이브러리 추가는 끝이 납니다.

6) Quartz의 핵심적인 기능을 할 /WEB-INF/config/applicationConext.xml 을 작성합니다.
    스케쥴러의 핵심 세팅은 3가지 정도 입니다.

   

    

     하나. 실제 주기적으로 실행될 클래스 등록
    둘. 스케줄러가 동작하는 interval time 설정

    셋. 실제 동작하게 끔 설정


    이런 세가지가 있겠습니다.

스케줄러 동작방식에는 두가지가 존재 합니다.
- Simple : interval time이 간단하게 동작하는 방식으로 몇 초, 혹은 몇 분, 몇 시간 단위로

               작동하고 싶을때 사용합니다.

 

[Simple type setting]

 

 <ref bean="simpleTrigger"/>
    </list>
  </property>
  <!-- Quartz 실행시 세팅 -->
  <property name="quartzProperties">
   <props>
    <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
       <prop key="org.quartz.threadPool.threadCount">5</prop>
       <prop key="org.quartz.threadPool.threadPriority">4</prop>
       <prop key="org.quartz.jobStore.class">org.quartz.simpl.RAMJobStore</prop>
       <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
    </props>
   </property>
  </bean>
 </beans>

 

 

 

- Cron : linux 의 Cron tab 과 같은 역할을 하는 타입니다.

            즉, 몇월, 몇일 몇시에 동작하게 하고 싶으면 Cron type을 사용하시면 됩니다.

 

[Cron type setting]

 

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    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-2.5.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-2.5.xsd">


 <!-- 하나. 주기적으로 실행될 클래스 설정 -->
 <bean id="cronQuartzJob" class="org.springframework.scheduling.quartz.JobDetailBean">
  <property name="jobClass" value="net.test.quartz.CronQuartzJob"/>
 </bean>
 
 <!-- 둘. 스케줄러의 interval time 설정-->
 <!--cronexpression을 통해서 스캐줄러 주기를 설정한다. -->
 <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
  <property name="jobDetail" ref="cronQuartzJob"/>
  <property name="cronexpression" value="0/1 * * * * ?"/>
 </bean>
 
 <!-- 셋. 실제 동작하게끔 설정 -->
 <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  <property name="triggers">
   <list>
    <ref bean="cronTrigger"/>
   </list>
  </property>
  <property name="quartzProperties">
   <props>
    <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
       <prop key="org.quartz.threadPool.threadCount">5</prop>
       <prop key="org.quartz.threadPool.threadPriority">4</prop>
       <prop key="org.quartz.jobStore.class">org.quartz.simpl.RAMJobStore</prop>
       <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
   </props>
  </property>
 </bean>
</beans>

 

 

Cron type을 사용하려면 Cronexpression을 알아야 합니다.

 

* Cron expression
cron expression의 각각의 필드는 다음을 나타낸다. (왼쪽 -> 오른쪽 순)

 필드 이름 허용 값 허용된 특수 문자
 Seconds 0 ~ 59 , - * /
 Minutes 0 ~ 59 , - * /
 Hours 0 ~ 23 , - * /
 Day-of-month 1 ~ 31 , - * ? / L W
 Month 1 ~12 or JAN ~ DEC  , - * /
 Day-Of-Week 1 ~ 7 or SUN-SAT , - * ? / L #
 Year (optional) empty, 1970 ~ 2099 , - * /


Cron expression 의 특수문자

 '*' : 모든 수를 나타냄. 분의 위치에 * 설정하면 "매 분 마다" 라는 뜻.
'?' : day-of-month 와 day-of-week 필드에서만 사용가능. 특별한 값이 없음을 나타낸다.
'-' : "10-12" 과 같이 기간을 설정한다.

       시간 필드에 "10-12" 이라 입력하면 "10, 11, 12시에 동작하도록 설정" 이란 뜻.

',' : "MON,WED,FRI"와 같이 특정 시간을 설정할 때 사용한다.

      "MON,WED,FRI" 이면 " '월,수,금' 에만 동작" 이란 뜻.

'/' : 증가를 표현합니다.

       예를 들어 초 단위에 "0/15"로 세팅 되어 있다면 "0초 부터 시작하여 15초 이후에 동작" 이란 뜻.


 'L' : day-of-month 와 day-of-week 필드에만 사용하며 마지막날을 나타냅.

        만약 day-of-month 에 "L" 로 되어 있다면 이번 달의 마지막에 실행하겠다는 것을 나타냄.


 'W' : day-of-month 필드에만 사용되며, 주어진 기간에 가장 가까운 평일(월~금)을 나타낸다.

         만약 "15W" 이고 이번 달의 15일이 토요일이라면 가장가까운 14일 금요일날 실행된다. 
         또 15일이 일요일이라면 가장 가까운 평일인 16일 월요일에 실행되게 된다.

         만약 15일이 화요일이라면 화요일인 15일에 수행된다.


 "LW" : L과 W를 결합하여 사용할 수 있으며 "LW"는 "이번달 마지막 평일"을 나타냄.


 "#" : day-of-week에 사용된다. "6#3" 이면 3(3)번째 주 금요일(6) 이란 뜻이된다.

       1은 일요일 ~ 7은 토요일 

 expression Meaning
 "0 0 12 * * ?" 매일 12시에 실행
 "0 15 10 ? * *" 매일 10시 15분에 실행
 "0 15 10 * * ?" 매일 10시 15분에 실행
 "0 15 10 * * ? *" 매일 10시 15분에 실행
 "0 15 10 * * ?  2010"  2010년 동안 매일 10시 15분에 실행
 "0 * 14 * * ?" 매일 14시에서 시작해서 14:59분 에 끝남
 "0 0/5 14 * * ?" 매일 14시에 시작하여 5분 간격으로 실행되며 14:55분에 끝남
 "0 0/5 14,18 * * ?" 매일 14시에 시작하여 5분 간격으로 실행되며 14:55분에 끝나고, 매일 18시에 시작하여 5분간격으로 실행되며 18:55분에 끝난다.
 "0 0-5 14 * * ?" 매일 14시에 시작하여 14:05 분에 끝난다.

 

 

 

* 시간에 맞춰 돌아가는 스케줄러에서 다른 클래스를 사용하고 싶을 때는 다음과 같이 설정합니다.

 

<!-- 스프링 DI : 사용할 Service 객체를 생성 -->
<bean id="quartzJobService" class="net.test.quartz.service.impl.QuartzJobServiceImpl"/>

<bean id="simpleQuartzJob" class="org.springframework.scheduling.quartz.JobDetailBean">
 <property name="jobClass" value="net.test.quartz.SimpleQuartzJob"/>
 <!-- 사용하고자 하는 class의 bean id를 등록 -->
 <property name="jobDataAsMap">
  <map>
   <entry key="quartzJobService">
    <ref local="quartzJobService"/>
   </entry>
  </map>
 </property>
</bean>

 

 


* 두가지 스케줄러를 동시에 실행 시킬때

 

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
 <property name="triggers">
  <!--트리거를 두개 생성후 아래와 같이 세팅 -->
  <list>
   <ref bean="simpleTrigger"/>
   <ref bean="cronTrigger"/>
  </list>
 </property>
 <property name="quartzProperties">
  <props>
   <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
       <prop key="org.quartz.threadPool.threadCount">5</prop>
       <prop key="org.quartz.threadPool.threadPriority">4</prop>
       <prop key="org.quartz.jobStore.class">org.quartz.simpl.RAMJobStore</prop>
       <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
  </props>
 </property>
</bean>

 

 

 

 

7) 실제 작동할 Class파일 생성

 package net.test.quartz;

 

import net.test.quartz.service.QuartzJobService;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

 

public class SimpleQuartzJob extends QuartzJobBean

{
 // 실행될 클래스는 꼭 QuartzJobBean을 상속받아야 되며
 // executeInternal method를 override 하면 자동으로 이 메소드가 실행

 // Spring의 DI를 사용하여 Service객체를 setting
 // DI를 사용하지 않는다면 필요 없는 부분

 private QuartzJobService quartzJobService;
 public void setQuartzJobService(QuartzJobService quartzJobService) {
          this.quartzJobService = quartzJobService;
 }


 @Override
 protected void executeInternal(JobExecutionContext ex)throws JobExecutionException {
        quartzJobService.printLog();
 }
 
}

 

위와 같은 방식으로 Spring과 Quartz를 사용하여 스케줄러를 사용할 수 있습니다.