package com.example.caching;
public class Book {
private String isbn;
private String title;
public Book(String isbn, String title) {
this.isbn = isbn;
this.title = title;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public String toString() {
return "Book{" + "isbn='" + isbn + '\'' + ", title='" + title + '\'' + '}';
}
}
使用 Spring 快取資料
本指南將引導您完成在 Spring 管理的 bean 上啟用快取的過程。
您將構建什麼
您將構建一個應用程式,為簡單的圖書儲存庫啟用快取。
您需要什麼
-
大約 15 分鐘
-
一個喜歡的文字編輯器或 IDE
-
Java 17 或更高版本
-
您還可以將程式碼直接匯入到您的 IDE 中
如何完成本指南
與大多數 Spring 入門指南一樣,您可以從頭開始並完成每個步驟,也可以跳過您已熟悉的基本設定步驟。無論哪種方式,您最終都會得到可工作的程式碼。
要從頭開始,請轉到從 Spring Initializr 開始。
要跳過基礎知識,請執行以下操作
-
下載 並解壓本指南的原始碼儲存庫,或使用 Git 克隆它:
git clone https://github.com/spring-guides/gs-caching.git -
cd 進入
gs-caching/initial -
跳轉到 建立圖書模型。
完成後,您可以將您的結果與 gs-caching/complete 中的程式碼進行比較。
從 Spring Initializr 開始
您可以使用這個 預初始化專案 並單擊“生成”下載 ZIP 檔案。該專案已配置為符合本教程中的示例。
手動初始化專案
-
導航到 https://start.spring.io。此服務會為您拉取應用程式所需的所有依賴項,併為您完成大部分設定。
-
選擇 Gradle 或 Maven 以及您想要使用的語言。本指南假設您選擇了 Java。
-
單擊 Dependencies 並選擇 Spring cache abstraction。
-
單擊生成。
-
下載生成的 ZIP 檔案,這是一個已根據您的選擇配置好的 Web 應用程式存檔。
| 如果您的 IDE 集成了 Spring Initializr,您可以從 IDE 中完成此過程。 |
| 您還可以從 Github fork 該專案並在您的 IDE 或其他編輯器中開啟它。 |
建立圖書模型
首先,您需要為您的圖書建立一個簡單的模型。以下列表(來自 src/main/java/com/example/caching/Book.java)顯示瞭如何做到這一點
建立圖書儲存庫
您還需要該模型的儲存庫。以下列表(來自 src/main/java/com/example/caching/BookRepository.java)顯示了一個這樣的儲存庫
package com.example.caching;
public interface BookRepository {
Book getByIsbn(String isbn);
}
您可以使用 {SpringData}[Spring Data] 為各種 SQL 或 NoSQL 儲存提供儲存庫的實現。但是,在本指南的目的下,您將僅使用一個樸素的實現,該實現模擬一些延遲(網路服務、緩慢的延遲或其他問題)。以下列表(來自 src/main/java/com/example/caching/SimpleBookRepository.java)顯示了一個這樣的儲存庫
package com.example.caching;
import org.springframework.stereotype.Component;
@Component
public class SimpleBookRepository implements BookRepository {
@Override
public Book getByIsbn(String isbn) {
simulateSlowService();
return new Book(isbn, "Some book");
}
// Don't do this at home
private void simulateSlowService() {
try {
long time = 3000L;
Thread.sleep(time);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
simulateSlowService 會在每次 getByIsbn 呼叫中故意插入三秒鐘的延遲。稍後,您將使用快取來加速此示例。
使用儲存庫
接下來,您需要將儲存庫連線起來並使用它來訪問一些圖書。以下列表(來自 src/main/java/com/example/caching/CachingApplication.java)顯示瞭如何做到這一點
package com.example.caching;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CachingApplication {
public static void main(String[] args) {
SpringApplication.run(CachingApplication.class, args);
}
}
@SpringBootApplication 是一個方便的註解,它添加了以下所有內容
-
@Configuration:將類標記為應用程式上下文的 bean 定義源。 -
@EnableAutoConfiguration:告訴 Spring Boot 根據類路徑設定、其他 bean 和各種屬性設定開始新增 bean。例如,如果spring-webmvc在類路徑中,此註解會將應用程式標記為 Web 應用程式並激活關鍵行為,例如設定DispatcherServlet。 -
@ComponentScan:告訴 Spring 在com/example包中查詢其他元件、配置和服務,使其能夠找到控制器。
main() 方法使用 Spring Boot 的 SpringApplication.run() 方法啟動應用程式。您是否注意到沒有一行 XML?也沒有 web.xml 檔案。這個 Web 應用程式是 100% 純 Java,您不必處理任何管道或基礎設施的配置。
您還需要一個 CommandLineRunner 來注入 BookRepository 並用不同的引數多次呼叫它。以下列表(來自 src/main/java/com/example/caching/AppRunner.java)顯示了該類
package com.example.caching;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class AppRunner implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(AppRunner.class);
private final BookRepository bookRepository;
public AppRunner(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
@Override
public void run(String... args) throws Exception {
logger.info(".... Fetching books");
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("isbn-1234"));
logger.info("isbn-4567 -->" + bookRepository.getByIsbn("isbn-4567"));
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("isbn-1234"));
logger.info("isbn-4567 -->" + bookRepository.getByIsbn("isbn-4567"));
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("isbn-1234"));
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("isbn-1234"));
}
}
如果您此時嘗試執行應用程式,您應該會注意到它相當慢,即使您多次檢索完全相同的圖書。以下示例輸出顯示了我們(故意糟糕)的程式碼建立的三秒延遲
2014-06-05 12:15:35.783 ... : .... Fetching books
2014-06-05 12:15:40.783 ... : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
2014-06-05 12:15:43.784 ... : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
2014-06-05 12:15:46.786 ... : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
我們可以透過啟用快取來改善這種情況。
啟用快取
現在您可以為您的 SimpleBookRepository 啟用快取,以便圖書被快取到 books 快取中。以下列表(來自 src/main/java/com/example/caching/SimpleBookRepository.java)顯示了儲存庫定義
package com.example.caching;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public class SimpleBookRepository implements BookRepository {
@Override
@Cacheable("books")
public Book getByIsbn(String isbn) {
simulateSlowService();
return new Book(isbn, "Some book");
}
// Don't do this at home
private void simulateSlowService() {
try {
long time = 3000L;
Thread.sleep(time);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
您現在需要啟用快取註解的處理,如下例(來自 src/main/java/com/example/caching/CachingApplication.java)所示
package com.example.caching;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class CachingApplication {
public static void main(String[] args) {
SpringApplication.run(CachingApplication.class, args);
}
}
@EnableCaching 註解會觸發一個後處理器,該後處理器會檢查每個 Spring bean 的公共方法上是否存在快取註解。如果找到此類註解,會自動建立一個代理來攔截方法呼叫並相應地處理快取行為。
後處理器處理 @Cacheable、@CachePut 和 @CacheEvict 註解。您可以參考 Javadoc 和 參考指南 以獲取更多詳細資訊。
Spring Boot 會自動配置一個合適的 CacheManager 作為相關快取的提供程式。有關更多詳細資訊,請參閱 Spring Boot 文件。
我們的示例不使用特定的快取庫,因此我們的快取儲存是使用 ConcurrentHashMap 的簡單後備方案。快取抽象支援廣泛的快取庫,並且完全符合 JSR-107 (JCache)。
構建可執行 JAR
您可以使用 Gradle 或 Maven 從命令列執行應用程式。您還可以構建一個包含所有必要依賴項、類和資源並執行的單個可執行 JAR 檔案。構建可執行 JAR 使在整個開發生命週期中,跨不同環境等,輕鬆交付、版本化和部署服務作為應用程式。
如果您使用 Gradle,您可以透過使用 ./gradlew bootRun 執行應用程式。或者,您可以透過使用 ./gradlew build 構建 JAR 檔案,然後按如下方式執行 JAR 檔案
如果您使用 Maven,您可以透過使用 ./mvnw spring-boot:run 執行應用程式。或者,您可以使用 ./mvnw clean package 構建 JAR 檔案,然後按如下方式執行 JAR 檔案
| 這裡描述的步驟建立了一個可執行的 JAR。您還可以構建一個經典的 WAR 檔案。 |
測試應用程式
現在快取已啟用,您可以再次執行應用程式,並透過新增具有相同 ISBN 或不同 ISBN 的其他呼叫來檢視差異。這應該會帶來巨大的不同。以下列表顯示了啟用快取後的輸出
2016-09-01 11:12:47.033 .. : .... Fetching books
2016-09-01 11:12:50.039 .. : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
2016-09-01 11:12:53.044 .. : isbn-4567 -->Book{isbn='isbn-4567', title='Some book'}
2016-09-01 11:12:53.045 .. : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
2016-09-01 11:12:53.045 .. : isbn-4567 -->Book{isbn='isbn-4567', title='Some book'}
2016-09-01 11:12:53.045 .. : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
2016-09-01 11:12:53.045 .. : isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
在前面的示例輸出中,第一次檢索圖書仍然需要三秒鐘。但是,第二次及後續相同圖書的檢索速度要快得多,這表明快取正在發揮作用。
總結
恭喜!您剛剛為 Spring 管理的 bean 啟用了快取。