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 into
gs-caching/initial
-
直接跳到 建立書籍模型。
當您完成時,您可以將您的結果與 gs-caching/complete
中的程式碼進行比較。
從 Spring Initializr 開始
您可以使用這個 預先初始化的專案,然後點擊「Generate」以下載 ZIP 檔案。 這個專案已配置為符合本教學課程中的範例。
要手動初始化專案
-
導覽至 https://start.spring.io。 此服務會提取應用程式所需的所有相依性,並為您完成大部分設定。
-
選擇 Gradle 或 Maven 以及您想要使用的語言。 本指南假設您選擇了 Java。
-
點擊 Dependencies 並選擇 Spring cache abstraction。
-
點擊 Generate。
-
下載產生的 ZIP 檔案,該檔案是使用您的選擇配置的 Web 應用程式的封存檔。
如果您的 IDE 具有 Spring Initializr 整合,您可以從您的 IDE 完成此過程。 |
您也可以從 Github 分叉專案並在您的 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)來查看差異。 它應該會產生巨大的差異。 以下清單顯示了啟用快取後的輸出
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 上啟用了快取。
參見
以下指南也可能有所幫助
想要編寫新的指南或貢獻現有的指南? 請查看我們的 貢獻指南。
所有指南均以 ASLv2 授權發布用於程式碼,並以 Attribution, NoDerivatives creative commons 授權 發布用於寫作。 |