Có 1 sự thật là, ngân hàng không bao giờ quên ngày sinh nhật của bạn, luôn luôn chúc bạn sinh nhật vui vẻ từ năm này qua năm khác, đôi khi bạn cảm giác như chỉ có mỗi ngân hàng là quan tâm đến bạn giữa sóng gió cuộc đời này. Nhưng sự thật có phải vậy không?

Quay trở lại với hiện tại, đôi khi chúng ta viết 1 chương trình, bạn cần phải thực hiện 1 tính năng nào đó sau 1 thời gian có định, ví dụ như: mỗi ngày bạn kiểm tra trong danh sách khách hàng của mình, có sinh nhật của những ai, nếu có thì gửi mail chúc mừng sinh nhật cho người đó, hay là cứ đúng 12h chủ nhật hàng tuần là phải gửi file kế hoạch công việc của tuần tiếp theo.

Tất nhiên chúng ta cũng có nhiều giải pháp cho những việc này, ví dụ như là:

  • Tự giác quay tay: Tự kiểm tra ngày sinh khách hàng và soạn mail chúc mừng sinh nhật, hay đúng 12h là gửi file. Nhưng cách này tốn cơm và không ổn tí nào, với 1 số yêu cầu phức tạp và nhanh hơn (1 giây 1 lần) thì cái máy chạy bằng cơm này không thể đáp ứng được
  • Tạo Thread rồi While(true) và check thời gian liên tục, nào đúng giờ đúng phút đúng giây thì thực hiện tác vụ như mong muốn.
  • Sử dụng Quartz lib hay Timer, TimerTask của Java. Cách này khá ổn nhỉ

Spring hỗ trợ chung ta cách 3 trong vòng 2 nốt nhạc, chúng ta có thể kích hoạt chức năng lên lịch trình một cách đơn giản bằng viết thêm annotation @EnableScheduling vào trong main application class hay trong 1 lớp class nào đó mà chúng ta có đặt annotation @Configuration. Bạn có thể xem ví dụ sau

  • Và tất nhiên, việc lên lịch trình cho các công việc trong Spring Boot cực kì đơn giản. Bạn chỉ cần thên annotation @Scheduled cho method và cung cấp 1 vài parameters được sử dụng để quyết định thời gian mà task sẽ chạy.

Sử dụng @Scheduled với 4 tham số sau đây, chúng ta sẽ có 4 cách chạy khác nhau

  • fixedRate: Thể hiện khoảng cách (thời gian) giữa các lần chạy
  • fixedDelay: Thể hiện khoảng cách (thời gian) giữa các lần chạy
  • fixedRate initialDelay: Có thời gian delay cho lần đầu tiên chạy
  • cron: sử dụng cron expression để định nghĩa lịch chạy

Có ai thắc mắc tại sao fixedRate fixedDelay lại có mô tả giống nhau không nhỉ?

Tạo schedule task với fixedRate:

  • Với fixedRate = 1000 thì cứ đúng 1 giây là hệ thống sẽ thực thi nghiệp vụ trong method scheduleFixedRateTask() và không cần quan tâm gì cả (lần chạy trước vẫn chưa thực hiện xong thì don’t care, cứ chạy tiếp lần tiếp theo thôi).

Tạo schedule task với fixedDelay:

  • Cứ sau khoảng thời gian fixedDelay thì nó lại chạy một lần, ví dụ ở trên thì cứ sau 1000ms (1 giây) thì nó lại chạy method scheduleFixedDelayTask một lần.
  • Với fixedDelay thì chỉ khi nào task trước đó thực hiện xong thì nó mới chạy tiếp task đó lại lần nữa. Như ví dụ trên, sau 1 giây mà method scheduleFixedDelayTask chưa chạy xong thì nó sẽ chờ cho tới khi nào xong mới chạy lại lần tiếp theo

Đến đây chắc các bạn cũng nắm rõ fixedRate fixedDelay giống và khác nhau như thế nào rồi nhỉ!

Tạo schedule task với fixedRate và initialDelay:

  • Sau khi hệ thống đã được deploy xong (theo như ví dụ trên), thì phải sau khoảng thời gian initialDelay (10 giây) thì scheduleTaskWithInitialDelay() mới được thực thi, sau đó thì cứ sau fixedRate (2 giây) sẽ chạy tiếp.

Tạo schedule task với cron expression:

Đôi khi bạn có 1 số yêu cầu khác phức tạp hơn mà 3 ý ở trên không thể đáp ứng được như là 12h mỗi chủ nhật hay từ giây thứ 5 đến giây thứ 55 trong khoảng thời gian 12h-13h vào ngày thứ 6, cứ 1 giây lặp lại công việc một lần.

Cùng làm 1 ví dụ thực tế nào

BidiPost.com mang đến kênh thông tin mua bán nhà riêng tại Thành phố Quy Nhơn. Là kênh thông tin bất động sản mang đến nguồn thông tin đa dạng từ nguồn tin rao vặt.

Hiện tại mình thường xuyên đăng tin rao vặt trên một số trang website quảng cáo miễn phí, thật bất ngờ hôm nay mình phát hiện thấy trang BidiPost cũng miễn phí đăng tin. Nhưng mình khá lười khi phải copy dán bài viết của mình từ trang khác và dán vào BidiPost.

Vậy là mình quyết định chôm source của BidiPost bằng cách đi cửa hậu. Mặc dù khá khó khăn nhưng cuối cùng cũng đã làm được (đuối lắm nha các bạn, khổ lắm chứ không sung sướng gì đâu :)))) )

Nào chiến thôi!!

Bước 1: Chôm source, đã xong!

Buớc 2: Thêm annotation @EnableScheduling

Bước 3: Tạo class ScheduledTasks để code nghiệp vụ của mình.

Bước 4: Code phần ngiệp vụ, mục tiêu là cứ 12 tiếng, hệ thống sẽ lấy bài viết trên trang x web để đăng lên BidiPost. Chọn sử dụng fixedRate cho nhanh gọn lẹ

23h10, khuya rồi nên code lẹ cho chạy được là chính :)))

Bước 5: Sau khi code xong thì export ra file War rồi sử dụng bẩy bẩy 4 chín cách để hack vào con server để deploy cái gói war này (đến nhẹ nhàng và ra đi thanh thản)

Bước 6: Nằm phè phởn và chờ xem thành quả

References: https://spring.io/guides/gs/scheduling-tasks/

Nhớ ghi nguồn https://susudev.com khi đăng tải lại bài viết này