캠핑과 개발


가끔 서버에서 주기적으로 어떠한 작업을 하고자 할때 리눅스에서는 크론탭을 사용하여 주기적으로 어떠한 작업을 처리합니다.
이런 주기적 작업을 처리하기위해 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를 사용하신다면 웹에 맞게 설정하시고 사용하셔야 함을 알려드립니다.^^
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xmlns="http://java.sun.com/xml/ns/javaee"      
  4.     xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee      
  5.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  id="WebApp_ID" version="2.5">    <listener>  
  6.         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>     
  7.     </listener>      
  8.     <context-param>          
  9.         <param-name>contextConfigLocation</param-name>         
  10.         <param-value>/WEB-INF/config/applicationContext*.xml</param-value>  
  11.     </context-param>  
  12. </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>
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:context="http://www.springframework.org/schema/context"  
  4.        xmlns:p="http://www.springframework.org/schema/p"  
  5.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans      
  7.                            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
  8.                            http://www.springframework.org/schema/context   
  9.                            http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
  10.     <!-- 하나.주기적으로 실행될 클래스 설정 -->  
  11.     <!-- property name은 jobClass로 fix, value는 사용자가 작성한 class 파일 위치 -->  
  12.     <bean id="simpleQuartzJob" class="org.springframework.scheduling.quartz.JobDetailBean">  
  13.         <property name="jobClass" value="net.test.quartz.SimpleQuartzJob"/>  
  14.     </bean>  
  15.   
  16.     <!-- 둘.스케줄러의 interval time 설정 -->  
  17.     <!-- 쿼츠에는 아래와 같이 몇초에 한번씩 돌게 하는 Simple type 과 -->  
  18.     <!-- 무슨 요일 몇시에 한번씩 돌게 하는 날짜로 지정하는 Cron type 이 있다. -->  
  19.     <!-- 현재는 Simple type으로 세팅 -->  
  20.     <!-- jobDetail은 위에서 설정한 실제 동작할 클래스 id를 적어준다 -->  
  21.     <!-- startDelay는 서버 시작후 몇초 뒤에 시작할지 세팅(ms 단위)  -->  
  22.     <!-- repeatInterval은 몇 초에 한번씩 실행될 건지 세팅(ms 단위: 현재 1초) -->  
  23.     <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  
  24.         <property name="jobDetail" ref="simpleQuartzJob"/>  
  25.         <property name="startDelay" value="1000"/>  
  26.         <property name="repeatInterval" value="1000"/>  
  27.     </bean>  
  28.     <!--셋. 실제 동작하게끔 설정 -->  
  29.     <!--ref bean은 위에서 설정한 interval time 아이디를 넣어주면 됨  -->  
  30.     <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
  31.         <property name="triggers">  
  32.             <list>  
  33.                 <ref bean="simpleTrigger"/>  
  34.             </list>  
  35.         </property>  
  36.         <!-- Quartz 실행시 세팅 -->  
  37.         <property name="quartzProperties">  
  38.             <props>  
  39.                 <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>  
  40.                 <prop key="org.quartz.threadPool.threadCount">5</prop>  
  41.                 <prop key="org.quartz.threadPool.threadPriority">4</prop>  
  42.                 <prop key="org.quartz.jobStore.class">org.quartz.simpl.RAMJobStore</prop>  
  43.                 <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>  
  44.             </props>  
  45.         </property>  
  46.     </bean>  
  47. </beans>  

-Cron : linux 의 Cron tab 과 같은 역할을 하는 타입니다. 즉 몇월, 몇일 몇시에 동작하게 하고 싶으면 Cron type을 사용하시면 됩니다.
<Cron type setting>
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:context="http://www.springframework.org/schema/context"  
  4.        xmlns:p="http://www.springframework.org/schema/p"  
  5.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans      
  7.                            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
  8.                            http://www.springframework.org/schema/context   
  9.                            http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
  10.     <!--하나. 주기적으로 실행될 클래스 설정 -->  
  11.     <bean id="cronQuartzJob" class="org.springframework.scheduling.quartz.JobDetailBean">  
  12.         <property name="jobClass" value="net.test.quartz.CronQuartzJob"/>  
  13.     </bean>  
  14.        
  15.     <!--둘. 스케줄러의 interval time 설정-->  
  16.     <!--cronExpression을 통해서 스캐줄러 주기를 설정한다. -->  
  17.     <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">  
  18.         <property name="jobDetail" ref="cronQuartzJob"/>  
  19.         <property name="cronExpression" value="0/1 * * * * ?"/>  
  20.     </bean>  
  21.        
  22.     <!--셋. 실제 동작하게끔 설정 -->  
  23.     <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
  24.         <property name="triggers">  
  25.             <list>  
  26.                 <ref bean="cronTrigger"/>  
  27.             </list>  
  28.         </property>  
  29.         <property name="quartzProperties">  
  30.             <props>  
  31.                 <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>  
  32.                 <prop key="org.quartz.threadPool.threadCount">5</prop>  
  33.                 <prop key="org.quartz.threadPool.threadPriority">4</prop>  
  34.                 <prop key="org.quartz.jobStore.class">org.quartz.simpl.RAMJobStore</prop>  
  35.                 <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>  
  36.             </props>  
  37.         </property>  
  38.     </bean>  
  39. </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 분에 끝난다.

* 시간에 맞춰 돌아가는 스케줄러에서 다른 클래스를 사용하고 싶을 때는 다음과 같이 설정합니다.
  1. <!-- 스프링 DI : 사용할 Service 객체를 생성 -->  
  2. <bean id="quartzJobService" class="net.test.quartz.service.impl.QuartzJobServiceImpl"/>  
  3.   
  4. <bean id="simpleQuartzJob" class="org.springframework.scheduling.quartz.JobDetailBean">  
  5.     <property name="jobClass" value="net.test.quartz.SimpleQuartzJob"/>  
  6.     <!-- 사용하고자 하는 class의 bean id를 등록 -->  
  7.     <property name="jobDataAsMap">  
  8.         <map>  
  9.             <entry key="quartzJobService">  
  10.                 <ref local="quartzJobService"/>  
  11.             </entry>  
  12.         </map>  
  13.     </property>  
  14. </bean>  

 *두가지 스케줄러를 동시에 실행 시킬때
  1. <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
  2.     <property name="triggers">  
  3.         <!--트리거를 두개 생성후 아래와 같이 세팅 -->  
  4.         <list>  
  5.             <ref bean="simpleTrigger"/>  
  6.             <ref bean="cronTrigger"/>  
  7.         </list>  
  8.     </property>  
  9.     <property name="quartzProperties">  
  10.         <props>  
  11.             <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>  
  12.                 <prop key="org.quartz.threadPool.threadCount">5</prop>  
  13.                 <prop key="org.quartz.threadPool.threadPriority">4</prop>  
  14.                 <prop key="org.quartz.jobStore.class">org.quartz.simpl.RAMJobStore</prop>  
  15.                 <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>  
  16.         </props>  
  17.     </property>  
  18. </bean>  


7) 실제 작동할 Class파일 생성
  1. package net.test.quartz;   
  2.   
  3. import net.test.quartz.service.QuartzJobService;   
  4.   
  5. import org.quartz.JobExecutionContext;   
  6. import org.quartz.JobExecutionException;   
  7. import org.springframework.scheduling.quartz.QuartzJobBean;   
  8.   
  9. public class SimpleQuartzJob extends QuartzJobBean{   
  10.     //실행될 클래스는 꼭 QuartzJobBean을 상속받아야 되며    
  11.     //executeInternal method를 override 하면 자동으로 이 메소드가 실행   
  12.   
  13.     //Spring의 DI를 사용하여 Service객체를 setting   
  14.     //DI를 사용하지 않는다면 필요 없는 부분   
  15.     private QuartzJobService quartzJobService;   
  16.     public void setQuartzJobService(QuartzJobService quartzJobService) {   
  17.         this.quartzJobService = quartzJobService;   
  18.     }   
  19.   
  20.   
  21.     @Override  
  22.     protected void executeInternal(JobExecutionContext ex)throws JobExecutionException {   
  23.         quartzJobService.printLog();   
  24.     }   
  25.        
  26. }  


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

함께 업로드 하는 파일은 제가 직접 작업한 프로젝트이구요. 함께 확인 해 보시면 쉽게 쿼츠를 사용하실수 있으실 겁니다.~^^



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


1 Seconds (0--59)
2 Minutes (0--59)
3 Hours (0--23)
4 Day of month (1--31)
5 Month (1--12 or JAN--DEC)
6 Day of week (1--7 or SUN--SAT)
7 Year (1970--2099)

*는 all, ?는 설정않함.
examples..

0 0 10 * * ?
매일 오전 10시에 실행

0 0 10 1 * ?
매월 1일 오전 10시에 실행

0 0 10 ? ? 1 ?
매주 일요일 오전 10시에 실행

0/5 * * * * ?
5초마다 실행



----------------------------------
http://blog.naver.com/wogud71/20054783968

필드 허용범위 허용문자
초 0-59 , - * /
분 0-59 , - * /
시 0-23 , - * /
일 1-31 , - * ? / L W
월 1-12 or JAN-DEC , - * /
요일 1-7 or SUN-SAT , - * ? / L #
년(옵션) 1970-2099 , - * /

* 모든 값
? 특정 값 없음
- 범위 지정에 사용
, 여러 값 지정 구분에 사용
/ 초기값과 증가치 설정에 사용
L 지정할 수 있는 범위의 마지막 값
W 월~금요일 또는 가장 가까운 월/금요일
# 몇 번째 무슨 요일 2#1 => 첫 번째 월요일

예제)
Expression Meaning
초분시일월주(년)
"0 0 12 * * ?" 아무 요일, 매월, 매일 12:00:00
"0 15 10 ? * *" 모든 요일, 매월, 아무 날이나 10:15:00
"0 15 10 * * ?" 아무 요일, 매월, 매일 10:15:00
"0 15 10 * * ? *" 모든 연도, 아무 요일, 매월, 매일 10:15
"0 15 10 * * ? 2005" 2005년 아무 요일이나 매월, 매일 10:15
"0 * 14 * * ?" 아무 요일, 매월, 매일, 14시 매분 0초
"0 0/5 14 * * ?" 아무 요일, 매월, 매일, 14시 매 5분마다 0초
"0 0/5 14,18 * * ?" 아무 요일, 매월, 매일, 14시, 18시 매 5분마다 0초
"0 0-5 14 * * ?" 아무 요일, 매월, 매일, 14:00 부터 매 14:05까지 매 분 0초
"0 10,44 14 ? 3 WED" 3월의 매 주 수요일, 아무 날짜나 14:10:00, 14:44:00
"0 15 10 ? * MON-FRI" 월~금, 매월, 아무 날이나 10:15:00
"0 15 10 15 * ?" 아무 요일, 매월 15일 10:15:00
"0 15 10 L * ?" 아무 요일, 매월 마지막 날 10:15:00
"0 15 10 ? * 6L" 매월 마지막 금요일 아무 날이나 10:15:00
"0 15 10 ? * 6L 2002-2005"
2002년부터 2005년까지 매월 마지막 금요일 아무 날이나 10:15:00
"0 15 10 ? * 6#3" 매월 3번째 금요일 아무 날이나 10:15:00


"?"와 "*"의 차이를 구분하기가 어렵습니다. 그냥 "?"는 한 개만 사용하는 것으로 생각하시면 됩니다.