سلام :)
گاهی نیاز هست که ما یک سری کار ها و تسک ها را در دوره زمانی مشخص یا بصورت زمان بندی شده اجرا کنیم، Spring Boot این امکان را برای ما فراهم می کند که وظایف را برای اجرا در یک دوره زمانی معین با کمک انوتیشن Scheduled@ زمان بندی کنیم.
ابتدا باید زمانبندی(scheduling) را در پروژه SpringBoot فعال کنیم برای اینکار نیاز هست که در بالای کلاس اصلی اسپرینگ که شامل متد main پروژه هست انوتیشن @EnableScheduling اضافه کنیم، در کنار انوتیشن @SpringBootApplication. به عنوان مثال:
// Annotation @SpringBootApplication @EnableScheduling // Class public class SchedulerApplication { // Main driver method public static void main(String[] args) { SpringApplication.run(SchedulerApplication.class,args); } }
خب حال برای نوشتن کدهای زمان بندی شده ما نیاز داریم به ایجاد یک @Component کلاس که اسم اون رو Scheduler می گذاریم و درون آن متد scheduleTask() را برای زمان بندی یک کار با استفاده از انوتیشن Scheduled@ تعریف می کند.
متد ()schedulerTask در کلاس Scheduler به سادگی تاریخ و زمانی را که task در آن اجرا می شود چاپ می کند.
// Annotation @Component // Class public class Scheduler { // Method // To trigger the scheduler every one minute // between 19:00 PM to 19:59 PM @Scheduled(cron = "0 * 19 * * ?") public void scheduleTask() { SimpleDateFormat dateFormat = new SimpleDateFormat( "dd-MM-yyyy HH:mm:ss.SSS"); String strDate = dateFormat.format(new Date()); System.out.println( "Cron job Scheduler: Job running at - " + strDate); } }
عنصر cron مشخصشده در انوتیشن Scheduled@ اجازه میدهد تا عبارات cron را برای دربرداشتن تریگرها در ثانیه، دقیقه، ساعت، روز ماه، ماه، و روز هفته تعریف کنیم. عبارت مشخص شده در اینجا در عنصر cron زمانبندی را هر یک دقیقه بین ساعت 19:00 تا 19:59.00 راه اندازی کند.
یعنی هر یک دقیقه بین ساعت 19:00 تا 19:59.00 تابع scheduleTask صدا زده می شود و ما خروجی آن را در کنسول مشاهده می کنیم.
*برای اجرای یک متد در زمان مشخص، باید از انوتیشن Scheduled@ در بالاسر متد مربوطه استفاده نمایید، که به صورت کلی 4 نوع ورودی fixedDelay،fixedRate،initialDelay و cronرا دارد. که ما در مثال بالا از cron استفاده کردیم حال بیایید این چهار نوع را بررسی کنیم
در این حالت، مدت زمان بین پایان آخرین اجرا و شروع اجرای بعدی ثابت است. کار همیشه منتظر می ماند تا کار قبلی تمام شود.این گزینه باید زمانی استفاده شود که اجرای قبلی قبل از اجرای مجدد اجباری باشد که یک عدد ثابت به میلی ثانیه دریافت می کند.
@Scheduled(fixedDelay = 1000) public void scheduleFixedDelayTask() { System.out.println( "Fixed delay task - " + System.currentTimeMillis() / 1000); }
این گزینه باید زمانی استفاده شود که هر اجرای وظیفه مستقل باشد که یک عدد ثابت به میلی ثانیه دریافت می کند.
توجه داشته باشید که کارهای برنامه ریزی شده به طور پیش فرض به صورت موازی اجرا نمی شوند. بنابراین حتی اگر از fixedRate استفاده کنیم، تا زمانی که کار قبلی انجام نشود، کار بعدی فراخوانی نخواهد شد.
@Scheduled(fixedRate = 1000) public void scheduleFixedRateTask() { System.out.println( "Fixed rate task - " + System.currentTimeMillis() / 1000); }
اگر میخواهیم از رفتار موازی در کارهای زمانبندیشده پشتیبانی کنیم، باید انوتیشن @Async را اضافه کنیم:
@EnableAsync public class ScheduledFixedRateExample { @Async @Scheduled(fixedRate = 1000) public void scheduleFixedRateTaskAsync() throws InterruptedException { System.out.println( "Fixed rate task async - " + System.currentTimeMillis() / 1000); Thread.sleep(2000); } }
برای زمانی است که بخواهیم اجرای اول را در زمان متفاوتی انجام دهیم و بعد با fixed rate/fixed Delay تکرار های بعدی را مشخص کنیم.
اولین اجرا با تاخیر 1 ثانیه ای انجام می شود، سپس سایر اجرا ها هر 2 ثانیه.
@Scheduled(fixedDelay = 1000, initialDelay = 2000) public void scheduleFixedRateWithInitialDelayTask() { long now = System.currentTimeMillis() / 1000; System.out.println( "Fixed rate task with one second initial delay - " + now); }
توجه داشته باشید که چگونه در این مثال از fixedDelay و همچنین initialDelay استفاده می کنیم. این کار برای اولین بار بعد از مقدار initialDelay اجرا می شود و مطابق با fixedDelay به اجرای آن ادامه می دهد.
گاهی اوقات تاخیرها و نرخ ها کافی نیستند و ما به انعطاف پذیری یک عبارت cron برای کنترل وظایف خود نیاز داریم. ممکن است شرایطی پیش بیاید که اجرای متد به فواصل زمانی خاصی نیاز داشته باشد. مثلا هر هفته یا آخر هر ماه یا بین یک بازه زمانی مشخص و یا ...
ترتیب قرار گیری مقادیر به صورت زیر است.مقدار سال اجباری نمی باشد ولی سایر فیلد ها باید پر شود.
<second> <minute> <hour> <day-of-month> <month> <day-of-week> <year>
میتوانید از سایت زیر یک عبارت cron تولید یا تست نمایید
https://crontab.cronhub.io/
برای مثال:
@Scheduled(cron = "0 15 10 15 * ?") public void scheduleTaskUsingCron) { long now = System.currentTimeMillis() / 1000; System.out.println( "schedule tasks using cron jobs - " + now); }
توجه داشته باشید که در این مثال، ما یک کار را برنامه ریزی می کنیم که در ساعت 10:15 صبح پانزدهمین روز هر ماه اجرا شود.
* به طور پیش فرض، Spring از منطقه زمانی محلی سرور برای عبارت cron استفاده می کند. با این حال، ما می توانیم از ویژگی zone برای تغییر این منطقه زمانی استفاده کنیم:
@Scheduled(cron = "0 15 10 15 * ?", zone = "Europe/Paris")
هاردکد کردن این زمانبندیها ساده است، اما معمولاً نیاز داریم که بتوانیم برنامه را بدون کامپایل مجدد و استقرار مجدد کل برنامه کنترل کنیم.
برای اینکار می توانیم از Spring Expressions و فایل application.properties استفاده کنیم برای اینکار به شکل زیر عمل می کنیم
@Scheduled(fixedDelayString = "${fixedDelay.in.milliseconds}")
و قرار دادن fixedDelay.in.milliseconds=1000 در application.properties
@Scheduled(fixedRateString = "${fixedRate.in.milliseconds}")
و قرار دادن fixedRate.in.milliseconds=1000 در application.properties
@Scheduled(cron = "${cron.expression}")
و قرار دادن مقدار cron.expression در application.properties
cron.expression="0 15 10 15 * ?"