+1

Tạo một project đơn giản với Spring boot cache - Thymeleaf và sử dụng annotation "@Scheduled" cho trigger

Trong bài viết này, tôi sẽ hướng dẫn các bạn 2 phần:

  • Sử dụng Spring boot cache để cache data response

  • Clear cache sau mỗi lần call api update data

Công cụ và thư viện được sử dụng trong bài viết:

  • Spring tool suite 4
  • Spring boot 3.0.1
  • Spring boot cache
  • Spring boot thymeleaf
  • Maven 3
  • Java 11
  • Postman

Trong bài viết này tôi không hướng dẫn lại về Thymeleaf, tham khảo lại các bài viết dưới đây:

https://viblo.asia/p/tao-mot-project-voi-spring-boot-va-elasticsearch-841-su-dung-thu-vien-spring-data-elasticsearch-huong-dan-cai-dat-va-su-khac-nhau-giua-2-phien-ban-8xx-voi-7xx-elasticsearch-Rk74aRXvJeO

https://viblo.asia/p/tao-mot-project-voi-spring-boot-thymeleaf-elasticsearch-su-dung-http2-tao-service-run-elasticsearch-yZjJYjolLOE

https://viblo.asia/p/gui-mail-voi-mailtrap-ket-hop-spring-boot-thymeleaf-elasticsearch-xac-thuc-voi-otp-khi-dang-nhap-Yym40ZEjL91

1. Cấu trúc thư mục:

image.png

2. Nội dung pom file:

image.png

3. Nội dung application class:

Trong class applciation, tôi khai báo annotation "@EnableCaching" để apply cache

image.png

4. Nội dung ContactController class:

Trong ContactController, tôi khởi tạo trước 1 list contacts với static block

image.png

5. Nội dung ContactModel class:

image.png

Sau khi tạo xong các class ở trên, tôi start project lên:

image.png

6. Nội dung "index.html" file:

Để query data từ list trong Thymeleaf, các bạn có thể sử dụng "th:each" và để đọc những attributes -> có thể sử dụng "th:text"

image.png

Tiếp theo, trước khi apply cache cho api tôi sẽ dùng postman để test thời gian phản hồi(time response) khi chưa apply cache, tôi call api "http://localhost:8080/contact/1"(1 là id contact):

Time response khoảng 35ms

image.png

Tiếp theo, tôi thử apply cache cho api ở trên. Tôi thêm annotation "@Cacheable":

image.png

Tại annotation "@Cacheable" tôi để name value là "contacts", có nghĩa là khi lần call api đầu tiên -> sẽ get data và kết quả trả về sẽ được lưu trong cache với tên là "contacts" và key value là id , name value các bạn đặt tên tuỳ ý

Sau khi apply cache, tôi tiến hành kiểm tra với 1 số kịch bản như bên dưới để xác định cache được apply thành công hoặc chưa:

* Kịch bản 1: Call api "http://localhost:8080/contact/1" với id là "1" lần thứ 1:

Tại thời điểm này, tôi có in một message trong function -> cho lần đầu tiên sẽ vẫn xử lý get data trong function và show message, cũng tại thời điểm này data response sẽ được lưu vào cache

image.png

Time response: 288ms

image.png

* Kịch bản 2: Call api "http://localhost:8080/contact/1" với id là "1" lần thứ 2:

Tại thời điểm này, hệ thống sẽ kiểm tra trong cache với name "contacts" để thấy với id là "1" có data đang được lưu trong cache hay không, nếu thấy có data trong cache -> sẽ load data từ cache(không cần vô function để get data)

image.png

Các bạn có thể thấy ngoài message được in trong lần call api đầu tiên -> lần thứ 2 không có message được in ra -> data được lấy trực tiếp từ cache

Check Postman, thấy time response giảm đáng kể còn khoảng 7ms

image.png

Tôi tiếp tục call api tiếp lần thứ 3 và thấy time response chỉ còn khoảng 4ms:

image.png

* Kịch bản 3: Call api "http://localhost:8080/contact/2" với id là "2" lần thứ 1:

Với kịch bản này, tôi muốn kiểm tra để thấy sau khi data response của contact id là "1" được lưu trong cache thì tiếp đến sau khi call get data contact id là "2" -> có show message hay không ?

image.png

=> Các bạn thấy với contact id là "2" nó sẽ call bên trong function để get data bởi vì trong cache không có thông tin id là "2"

* Kịch bản 4: Call api update contact "http://localhost:8080/updateContact/1" với id là "1":

Trong kịch bản này, tôi thử update data cho id contact là "1" và sau kịch bản này tôi sẽ kiểm tra call lại api get detail contact id là "1" để thấy data response có được lấy theo data mới hay cũ(data đã được lưu trong cache trước đó)

Data body update cho id contact là "1":

{
    "id": "1",
    "name": "Visible Mask",
    "phoneNumber": "123456789",
    "education": "ABC",
    "occupation": "Java Dev"
}

image.png

=> Update data success

* Kịch bản 5: Call api get detail contact "http://localhost:8080/contact/1" với id là "1":

Tại kịch bản này, tôi sẽ check sau khi call api get detail contact với id là "1" -> data response sẽ vẫn lấy từ cache trước đó(data cũ) hay call vô function để get new data

image.png

=> Như các bạn thấy, hệ thống vẫn sẽ load data từ cache được lưu trước đó. Vậy, chúng ta cần xử lý clear cache cho mục đích load new data sau khi update

Để tiến hành clear cache, tôi sử dụng annotation "@CacheEvict", tôi tạo mới 1 function để xử lý clear cache với id tương ứng và add annotation vào:

image.png

Tôi để name value là "contacts" mục đích để khi call đến function clear cache sẽ clear cache trong cache name "contacts" với id(key) tương ứng

* Kịch bản 6: Call api clear cache "http://localhost:8080/clearCache/1" với id cần clear trong cache là "1":

image.png

* Kịch bản 7: Call api get detail contact "http://localhost:8080/contact/1" với id là "1":

Sau khi clear cache success -> sau khi call api get detail contact id là "1" sẽ được load theo data mới nhất:

image.png

image.png

Tiếp theo, tôi hướng dẫn các bạn sử dụng annotation "@Scheduled" để trigger function tự động clear all cache. Đầu tiên tôi tạo tiếp 1 function xử lý clear all cache:

image.png

Để enable schedule, tôi add annotation "@EnableScheduling" trong class application:

image.png

Hiện tại, tôi set timeout là sau 20 second(20000 milisecond) -> function clear all cache sẽ được trigger

Sau khi update xong, tôi restart project và test call api get detail contact với id là "1", trong lần call đầu tiên -> sẽ show message và save response data trong cache:

image.png

Sau 20 second, function clear all cache được trigger thành công:

image.png

Tiếp theo, để tiện cho việc clear cache sau mỗi lần người dùng call api update data, tôi add annotation "@CacheEvict" đến function xử lý update data:

image.png

Tôi restart lại project và dùng postman call api get detail contact với id là "1":

image.png

image.png

Lần đầu tiên, hệ thống sẽ vẫn call bên trong function để get data, tiếp theo tôi call api update data cho contact id là "1":

image.png

Sau khi update data success -> đồng thời cũng đã clear tất cả cache -> tôi call api get detail 1 lần nữa với contact id là "1":

image.png

image.png

=> các bạn thấy, hệ thống sẽ call bên trong function để get new data và lưu vào cache lần nữa, những lần sau khi call api get detail -> sẽ chỉ load data từ cache:

Trong bài viết tiếp theo, tôi sẽ hướng dẫn các bạn lưu data response tại cache browser, các bạn cũng thấy mỗi khi chúng ta thực hiện 1 action nào đó trên web -> sẽ send request đến backend server để xử lý và response data, việc chúng ta xử lý lưu cache trong bài viết này chỉ giảm thời gian xử lý tại backend, nên nếu chúng ta xử lý lưu cache tại browser -> về mặt logic nó cũng tương tự như xử lý tại backend, nghĩa là cho lần tiên gửi request(call api) đến backend -> backend xử lý dữ liệu và response data thì lúc này chúng ta sẽ lưu response data này trong cache browser và cho những lần request tiếp theo -> sẽ load data trực tiếp từ cache browser, không cần call api đến backend.

Download source: http://megaurl.in/7leygd2


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí