๐ CS ์คํฐ๋/Java, Spring
[Spring] โ Quartz ๋ผ์ด๋ธ๋ฌ๋ฆฌ Scheduling
iknowDev
2023. 3. 9. 22:58
ํน์ ์๊ฐ ๊ฐ๊ฒฉ์ ๋ฐ๋ณตํ๊ฑฐ๋ ํน์ ํ ์๊ฐ์ ๋ก์ง์ ์ํํ๋ ๊ฒ์ Scheduler๋ผ๊ณ ํฉ๋๋ค.
์ด๋ฌํ ์์ ์ ์ํด Spring์์๋ 2๊ฐ์ง ์ต์ ์ ์ ๊ณตํฉ๋๋ค.
- Spring Scheduler
- Spring Quartz
๊ทธ ์ค ์ธ๋ฐํ ์ ์ด๊ฐ ๊ฐ๋ฅํ Quartz Scheduler ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด ์์๋ด ์๋ค.
๊ธฐ๋ณธ ๊ตฌ์ฑ
Job | ์ค์ผ์ค๋งํ ์ค์ ์์
์ ๊ฐ์ง๋ ๊ฐ์ฒด - JobListener |
JobData | Job์์ ์ฌ์ฉํ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๋ ๊ฐ์ฒด |
JobDataMap |
์ค์ผ์ค๋ฌ์์ Job ์คํ ์ ์ฌ์ฉํ ๋ณ์ ๊ฐ ์ ๋ฌ ์ฉ๋ (key-value ํ์) |
JobDetail |
Job์ ์ ๋ณด๋ฅผ ๊ตฌ์ฑํ๋ ๊ฐ์ฒด |
JobBuilder | Job์ instances ์ ์ํ๋ JobDetail instances ๋น๋์ ์ฌ์ฉ |
Trigger |
Job์ด ์ธ์ ์ํ๋ ์ง๋ฅผ ๊ตฌ์ฑํ๋ ๊ฐ์ฒด - TriggerListener |
TriggerBuilder | Trigger instances ๋น๋์ ์ฌ์ฉ |
Scheduler | JobDetail๊ณผ Trigger ์ ๋ณด๋ฅผ ์ด์ฉํด์ Job์ ์์คํ ์ ๋ฑ๋กํ๊ณ , Trigger๊ฐ ๋์ํ๋ฉด ์ง์ ๋ Job์ ์คํ์ํค๋ ๊ฐ์ฒด |
SchedulerFactory | Scheduler ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๊ฐ์ฒด |
quartz.properties | Quartz ์ค์ผ์ค๋ฌ๋ฅผ ์ํ ์ค์ ๊ฐ ๊ตฌ์ฑ ํ์ผ |
JobStore | ์ค์ผ์ค๋ฌ์ ๋ฑ๋ก๋ Job์ ์ ๋ณด์ ์คํ์ด๋ ฅ์ด ์ ์ฅ๋๋ ๊ณต๊ฐ |
JobExecutionContext |
execute ๋ฉ์๋์ ํ๋ผ๋ฏธํฐ๋ก ๋์ด๊ฐ๋ ์ธ์์ด๋ค. JobDetail ์ธ์คํด์ค๊ฐ Scheduler์ ์ํด ์คํ๋ ๋ ๋์ด์ค๊ณ , ์คํ์ด ์๋ฃ๋ ๋ค์๋ Trigger๋ก ๋์ด๊ฐ๋ค. |
์์ ์ฝ๋
์ค์ผ์ฅด๋ง๋ ์๊ฐ์ ๋ฐฐ์น ์์ ์ ํ๊ธฐ ์ํด์
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
@PersistJobDataAfterExecution
public class SchedulerTest implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
int idx = dataMap.getInt("idx");
System.out.println("* " + idx + " ์ค์ผ์ค๋ฌ ์ํ [" + new Date(System.currentTimeMillis()) + "]");
dataMap.putAsString("idx", idx+1);
if (5 <= idx) { // ์ํ ํ์ ์ง์
JobExecutionException e = new JobExecutionException("End Repeat");
e.setUnscheduleAllTriggers(true);
throw e;
}
}
}
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class Simpletest {
public static void main(String[] args) {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
try {
Scheduler scheduler = schedulerFactory.getScheduler();
JobDetail job = JobBuilder.newJob(SchedulerTest.class)
.withIdentity("jobName", Scheduler.DEFAULT_GROUP)
.usingJobData("idx", 1)
.build();
// 5์ด ์ฃผ๊ธฐ Simple ์ค์ผ์ค๋ง
SimpleTrigger simplTrigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", Scheduler.DEFAULT_GROUP)
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(5)
.withRepeatCount(3)) // ๋ฐ๋ณต ํ์
.build();
// 10์ด ์ฃผ๊ธฐ Cron ์ค์ผ์ค๋ง
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity("trigger2", Scheduler.DEFAULT_GROUP)
.withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?"))
.build();
scheduler.scheduleJob(job, cronTrigger);
scheduler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
SimpleTrigger (3์ด ๊ฐ๊ฒฉ ์์ ์ํ ๋ฐ๋ณต)
Cron Trigger (10์ด ๊ฐ๊ฒฉ ์์ ์ํ ๋ฐ๋ณต)
Cron Trigger Expression
CronTrigger๋ “๋งค์ผ ์์์ผ 9์”, ๋๋ “๋งค ์ฃผ๋ง ์คํ 7์”, “1์ ํ๋ฌ๊ฐ ๋งค์ฃผ ํ ์์ผ ์คํ 12์์์ 1์ ์ฌ์ด 10๋ถ ๊ฐ๊ฒฉ”๊ณผ ๊ฐ์ด ์ค์ผ์ค ์ค์ ์ ํ ์ ์์ต๋๋ค.
- ์ด(Seconds)
- ๋ถ(Minutes)
- ์(Hours)
- ์ผ(Day-of-Month)
- ์(Months)
- ์์ผ(Days-of-Week)
- ์ฐ๋(Year) - optional
? | ์ค์ ๊ฐ ์์์ ์ฌ์ฉ ์ผ(day-of-month)์ ์์ผ(day-of-week) ํ๋์์๋ง ํ์ฉ |
/ | ๊ฐ์ ์ฆ๊ฐ ํํ์ ์ฌ์ฉ ๋ถ(Minutes) ํ๋์ ‘0/10’ ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ์ด๊ฒ์ “0๋ถ ๋ถํฐ ์์ํ์ฌ (์๊ฐ์) ๋งค 10๋ถ ๋ง๋ค”๋ฅผ ์๋ฏธ |
L | ์ผ(day-of-month) ํ๋์์ ์ฌ์ฉ๋์์ ๊ฒฝ์ฐ ์ด๋ฌ์ ๋ง์ง๋ง ๋ ์ ์๋ฏธ 1์์ด๋ฉด 31์ผ์ด ๋๊ณ , 2์์ 28์ผ(์ค๋ 29์ผ)์ด ๋จ "6L” ๋๋ “FRIL”์ “์ด๋ฌ์ ๋ง์ง๋ง ๊ธ์์ผ”์ ์๋ฏธ |
W | ์ฃผ์ด์ง ๋ ๋ก๋ถํฐ ๊ฐ์ฅ ๊ฐ๊น์ด ํ์ผ(์์์ผ~๊ธ์์ผ) “21W”๋ผ๋ ๊ฐ์ ์ผ(day-of-month)ํ๋์ ์ค์ ํ๋ฉด, “์ด๋ฌ์ 21๋ฒ์งธ๋ ์์ ๊ฐ์ฅ ๊ฐ๊น์ด ํ์ผ”์ ์๋ฏธ |
# | ์ด๋ฌ์ n๋ฒ์งธ X์์ผ “2#1” ๋๋ “MON#1”์ ์์ผ(day-of-week) ํ๋์ ์ค์ ํ ๊ฒฝ์ฐ ์ด๊ฒ์ “์ด๋ฌ์ ์ฒซ๋ฒ์งธ ์์์ผ”์ ์๋ฏธ |
Expression | Meaning |
0 0 12 * * ? | Fire at 12pm (noon) every day |
0 15 10 ? * * | Fire at 10:15am every day |
0 15 10 * * ? | Fire at 10:15am every day |
0 15 10 * * ? * | Fire at 10:15am every day |
0 15 10 * * ? 2005 | Fire at 10:15am every day during the year 2005 |
0 * 14 * * ? | Fire every minute starting at 2pm and ending at 2:59pm, every day |
0 0/5 14 * * ? | Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day |
0 0/5 14,18 * * ? | Fire every 5 minutes starting at 2pm and ending at 2:55pm, AND fire every 5 minutes starting at 6pm and ending at 6:55pm, every day |
0 0-5 14 * * ? | Fire every minute starting at 2pm and ending at 2:05pm, every day |
0 10,44 14 ? 3 WED | Fire at 2:10pm and at 2:44pm every Wednesday in the month of March. |
0 15 10 ? * MON-FRI | Fire at 10:15am every Monday, Tuesday, Wednesday, Thursday and Friday |
0 15 10 15 * ? | Fire at 10:15am on the 15th day of every month |
0 15 10 L * ? | Fire at 10:15am on the last day of every month |
0 15 10 L-2 * ? | Fire at 10:15am on the 2nd-to-last last day of every month |
0 15 10 ? * 6L | Fire at 10:15am on the last Friday of every month |
0 15 10 ? * 6L | Fire at 10:15am on the last Friday of every month |
0 15 10 ? * 6L 2002-2005 | Fire at 10:15am on every last friday of every month during the years 2002, 2003, 2004 and 2005 |
0 15 10 ? * 6#3 | Fire at 10:15am on the third Friday of every month |
0 0 12 1/5 * ? | Fire at 12pm (noon) every 5 days every month, starting on the first day of the month. |
0 11 11 11 11 ? | Fire every November 11th at 11:11am. |
http://www.cronmaker.com/ ๋งํฌ๋ฅผ ํตํด Cron ํํ์์ ๋ง๋ค์ด ๋ณผ ์ ์๋ค.
์ค์ ์ ์ํ pom.xml (์ฝ๋ ๋ณด๊ธฐ)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>quartz_test</groupId>
<artifactId>simple01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java-version>1.7</java-version>
<org.springframework-version>4.2.3.RELEASE</org.springframework-version>
<maven.test.skip>true</maven.test.skip>
<cobertura.skip>true</cobertura.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- quartz scheduler -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Set a compiler level -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>${java-version}</source>
<target>${java-version}</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
</build>
</project>