SpringFramework 4.3.4 버전에서 Quartz 2.3.0 라이브러리를 사용해서 주기적으로 작업을 실행하는 방법을 알아보겠습니다. 전체 소스는 하단에 첨부해 두었습니다. 앞에서 계속 사용해오던 소스라 DB 연결, 엑셀 다운로드 등의 소스가 같이 있는데 필요 없는 부분은 주석처리하고 테스트 해보시면 되겠습니다.
1. pom.xml 파일에 quartz 라이브러리의 의존성을 추가합니다.
<!-- quartz 라이브러러리 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<!-- 스프링 Quartz 도우미 라이브러리 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
2. 주기적으로 실행될 서비스 메소드를 생성합니다.
com.tistory.pentode.service.BoardService.java파일에 메소드 인터페이스를 추가합니다.
void testJobMethod();
com.tistroy.pentode.service.impl.BoardServiceImpl.java 파일에 구현 메소드를 추가합니다.
...
@Service("boardService")
public class BoardServiceImpl implements BoardService {
...
@Override
public void testJobMethod() {
System.out.println("test job....");
}
...
}
3. root-context.xml 파일에 스케줄러 설정을 추가합니다.
위에서 작성한 서비스 객체의 testJobMethod() 메소드가 주기적으로 실행되도록 설정합니다.
<!-- 테스트용 잡 -->
<bean id="testJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- 서비스 구현 객체의 빈 이름을 인자로 줍니다. -->
<property name="targetObject" ref="boardService" />
<!-- 서비스 객체에서 주기적으로 실행될 메소드른 지정합니다. -->
<property name="targetMethod" value="testJobMethod" />
<!-- 동시 실행을 방지합니다. -->
<property name="concurrent" value="false" />
</bean>
<!-- 테스트용 트리거-->
<bean id="testJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="testJob" />
<!-- CronTrigger를 사용하여 2분 간격으로 실행되도록 지정했습니다. -->
<property name="cronExpression" value="0 0/2 * * * ?" />
</bean>
<!-- 테스트용 스케줄러 -->
<bean id="testJobScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<!-- 앞에서 설정한 트리거를 등록합니다. 필요하면 여러개 만들어서 등록하면 됩니다. -->
<list><ref bean="testJobTrigger" /></list>
</property>
</bean>
4. 실행결과 입니다.
5. Quartz에서 작업을 스케쥴하는데 SimpleTrigger와 CronTrigger 를 사용할 수 있습니다.
5.1 SimpleTrigger - 간단하게 특정 시간 간격으로 작업을 실행합니다.
<!-- 테스트용 트리거-->
<bean id="testJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="testJob" />
<!-- 시작하고 1분후에 실행한다. (milisecond) -->
<property name="startDelay" value="60000" />
<!-- 매 24시간마다 실행한다.86400000 (milisecond) -->
<property name="repeatInterval" value="86400000" />
</bean>
5.2 유닉스 크론 처럼 스케쥴할 수 있습니다.
<!-- 테스트용 트리거-->
<bean id="testJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="testJob" />
<property name="cronExpression" value="0 0/2 * * * ?" />
</bean>
- Cron Expression에는 총 7개의 필드 있고 마지막 필드(년도)는 생략 가능합니다.
필드이름 | 허용 값 |
---|---|
초(Seconds) | 0 ~ 59 |
분(Minutes) | 0 ~ 59 |
시간(Hours) | 0 ~ 23 |
일(Day-of-month) | 1 ~ 31 |
달(Months) | 1 ~ 12 or JAN ~ DEC |
요일(Day-of-week) | 1 ~ 7 or SUN-SAT |
년도(Year)(생략가능) | 1970 ~ 2099 |
- Cron Expression의 특수문자
Expr | 설명 |
---|---|
* | 모든 수를 나타냅니다. |
- | 값의 사이를 의미합니다. "* 10-13 * * * *" 10,11,12,13분에 동작합니다. |
, | 특정값 지칭합니다. "* 10,11,13 * * * *" 10,11,13분에 동작합니다. |
/ | 값의 증가를 표현합니다. "* 0/5 * * * *" 0분부터 시작해서 5분마다 동작합니다. |
? | 특별한 값이 없음을 나타냅니다.(day-of-month, day-of-week 필드만 사용) 일, 요일에 하나만 설정할때 나머지에 지정합니다. |
L | 마지막 날을 나타냅니다.(day-of-month, day-of-week 필드만 사용). 일 필드에 사용되면 이달의 마지막일을 나타냅니다. L-3 은 이달의 마지막날 3일 전부터 마지막날까지를 나타냅니다. 요일 필드에 사용되면 토요일(7 or SAT)을 나타냅니다. 6L or FRIL 은 이달의 마지막 금요일을 나타냅니다. |
W | 주어진 날로부터 가장 가까운 평일(월 - 금)을 나타냅니다. 15W 를 일 필드에 사용하면 이달의 15번째 날에서 가장 가까운 평일을 나타냅니다. |
# | 이달의 n번째 x 요일 을 나타냅니다. 6#3 or FRI#3 은 이달의 세번째 금요일을 나타냅니다. |
- Cron 표현식 예제
* 매 2분 마다 실행 : "0 0/2 * ?"
* 10초뒤 2분마다 실행 : "10 0/2 * ?"
* 매일 오전 1시에 실행 : "0 0 1 * * ?"
* 매주 금요일 오전 1시에 실행 : "0 0 1 ? * FRI"
* 매주 수요일과 금요일 10:30, 11:30, 12:30, 13:30 에 실행 : "0 30 10-13 ? * WED,FRI"
* 매월 5일, 20일 오전 8시부터 오전 10시 사이에 30분 간격으로 실행 : "0 0/30 8-9 5,20 * ?"
6. 실제로 Tomcat 으로 배포했을때 quartz job이 두 번 반복 실행되는 경우가 발생했었습니다.
여기 저기 검색해 본 결과 다음 글에서 원인을 알 수 있었습니다. "http://blog.ajkuhn.com/116"
Tomcat 설정파일의 <Host> 태그의 appBase 와 <Host> 태그에 포함되는 <Context> 태그의 docBase 를 설정할 때 appBase하위폴더로 docBase 를 지정하게 되면 컨텍스트가 두 번 생성되고, 스케줄이 두 번 실행되는 것이었습니다. 값을 다른 곳으로 지정하여 해결했습니다.
이것으로 SpringFrmework에서 quartz 라이브러리를 사용하여 주기적인 작업을 수행하는 방법을 알아 보았습니다.
※ 예제소스
'프로그래밍 > 스프링프레임워크' 카테고리의 다른 글
유틸리티 클래스의 정적 메소드로 커스텀 EL 함수 만들기 (0) | 2018.04.20 |
---|---|
JSTL - jsp 페이지에서 jstl을 사용하여 HTML tag 제거하기 (4) | 2018.04.20 |
전자정부표준프레임워크 Tomcat + jndi로 dataSource 사용하기 (0) | 2018.04.20 |
POI를 사용하여 엑셀 출력하기 (14) | 2018.04.20 |
스프링 시큐리티에서 중복 로그인 방지 및 세션 고정 공격 방지 (2) | 2018.04.20 |