翻譯自:https://spring.io/guides/gs/caching/
譯者:知秋
來(lái)源:極樂(lè)科技
本指南將指導(dǎo)您完成在Spring所托管bean上啟用緩存的過(guò)程。
What you’ll build
您將構(gòu)建一個(gè)應(yīng)用程序交惯,在一個(gè)簡(jiǎn)單的book repository中啟用緩存。
What you’ll need
- 約15分鐘
- 最喜歡的文本編輯器或IDE
- JDK 1.8或更高版本
- Gradle 2.3+或Maven 3.0+
- 您也可以從本指南導(dǎo)入代碼望迎,以及直接在Spring Tool Suite(STS)中查看網(wǎng)頁(yè),并從那 里開(kāi)始工作 凌外。
How to complete this guide
與大多數(shù)【Spring 入門指南】一樣Spring Guides辩尊,您可以從頭開(kāi)始并完成每個(gè)步驟,也可以繞過(guò)已經(jīng)熟悉的基本設(shè)置步驟康辑。 無(wú)論如何摄欲,你最終得到工作代碼。
- Download 并解壓縮本指南的源代碼倉(cāng)庫(kù)疮薇,或使用 Git: git clone https://github.com/spring-guides/gs-caching.git
- cd 到 gs-caching/initial
- 跳轉(zhuǎn)到Create a Redis message receiver.
當(dāng)你做完這一切, 你可以根據(jù) gs-caching/complete中的代碼檢查結(jié)果胸墙。
Build with Gradle
首先你設(shè)置一個(gè)基本的構(gòu)建腳本。 你可以使用任何你喜歡的一個(gè)來(lái)構(gòu)建項(xiàng)目按咒,當(dāng)使用Spring構(gòu)建應(yīng)用程序時(shí)迟隅,但是需要使用Gradle和Maven 來(lái)寫(xiě)你的代碼。 如果你不熟悉任何一個(gè)励七,請(qǐng)參考使用Gradle構(gòu)建Java項(xiàng)目或使用Maven構(gòu)建Java項(xiàng)目智袭。
Create the directory structure
在您選擇的項(xiàng)目目錄中,創(chuàng)建以下子目錄結(jié)構(gòu); 例如掠抬,在* nix*系統(tǒng)上使用
└── src
└── main
└── java
└── hello
Create a Gradle build file
下面是 initial Gradle build file吼野。
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.3.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
jar {
baseName = 'gs-caching'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-cache")
}
Spring Boot gradle插件提供了許多方便的功能:
- 它收集類路徑上的所有jar,并構(gòu)建一個(gè)單獨(dú)的两波,可運(yùn)行的“über-jar”箫锤,這使得執(zhí)行和傳遞服務(wù)更加方便。
- 它搜索public static void main()方法來(lái)標(biāo)記為可運(yùn)行類雨女。
- 它提供了一個(gè)內(nèi)置的依賴解析器谚攒,設(shè)置版本號(hào)匹配Spring Boot dependencies, 你可以覆蓋任何你想要的版本氛堕,但它會(huì)默認(rèn)為Boot的選擇的版本集馏臭。
Build with Maven
首先你設(shè)置一個(gè)基本的構(gòu)建腳本。 你可以使用任何你喜歡的一個(gè)來(lái)構(gòu)建項(xiàng)目讼稚,當(dāng)使用Spring構(gòu)建應(yīng)用程序括儒,但是需要使用Maven來(lái)構(gòu)建你的代碼。 如果你不熟悉Maven锐想,請(qǐng)參考使用Maven構(gòu)建Java項(xiàng)目.
Create the directory structure
在您選擇的項(xiàng)目目錄中帮寻,創(chuàng)建以下子目錄結(jié)構(gòu); 例如,在* nix*系統(tǒng)上使用
└── src
└── main
└── java
└── hello
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-caching</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Spring Boot Maven插件 提供了許多方便的功能:
- 它收集類路徑上的所有jar赠摇,并構(gòu)建一個(gè)單獨(dú)的固逗,可運(yùn)行的“über-jar”浅蚪,這使得執(zhí)行和運(yùn)輸服務(wù)更加方便。
- 它搜索public static void main()方法來(lái)標(biāo)記為可運(yùn)行類烫罩。
- 它提供了一個(gè)內(nèi)置的依賴解析器惜傲,設(shè)置版本號(hào)匹配Spring Boot dependencies. 你可以覆蓋任何你想要的版本,但它會(huì)默認(rèn)為Boot的選擇的版本集贝攒。
Build with your IDE
閱讀如何通過(guò)本指南直接導(dǎo)入Spring Tool Suite盗誊。
閱讀如何在IntelliJ IDEA上使用本指南。
Create a book repository
首先隘弊,讓我們?yōu)槟愕腷ook創(chuàng)建一個(gè)非常簡(jiǎn)單的模型
src/main/java/hello/Book.java
package hello;
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 + '\'' + '}';
}
}
和該model的存儲(chǔ)庫(kù):
src/main/java/hello/BookRepository.java
package hello;
public interface BookRepository {
Book getByIsbn(String isbn);
}
您可以使用Spring Data在很多的SQL或NoSQL stores中提供repository倉(cāng)庫(kù)的實(shí)現(xiàn)哈踱,但是出于本指南的目的, 將使用模擬一些延遲(網(wǎng)絡(luò)服務(wù)梨熙,慢延遲等)進(jìn)行簡(jiǎn)單地的實(shí)現(xiàn)嚣鄙。
src/main/java/hello/SimpleBookRepository.java
package hello;
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是故意在每個(gè)getByIsbn調(diào)用中插入一個(gè)三秒延遲。 這是一個(gè)例子串结,稍后哑子,你可以通過(guò)加入緩存來(lái)看到加速的效果。
Using the repository
接下來(lái)肌割,連接repository庫(kù)并使用它訪問(wèn)一些書(shū)卧蜓。
src/main/java/hello/Application.java
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- @ SpringBootApplication是一個(gè)方便的注解,添加了以下所有內(nèi)容:
- @ Configuration將類標(biāo)記為應(yīng)用程序上下文的bean定義的來(lái)源把敞。
- @ EnableAutoConfiguration告訴Spring Boot根據(jù)類路徑設(shè)置弥奸,其他bean和各種屬性設(shè)置開(kāi)始添加bean。
- 通常你會(huì)為Spring MVC應(yīng)用程序添加@ EnableWebMvc奋早,但是Spring Boot在類路徑上看到** spring-webmvc **時(shí)會(huì)自動(dòng)添加它盛霎。這將應(yīng)用程序標(biāo)記為Web應(yīng)用程序,并激活關(guān)鍵行為耽装,如設(shè)置一個(gè)“DispatcherServlet”愤炸。
- @ ComponentScan告訴Spring在hello包中尋找其他組件,配置和服務(wù)掉奄,允許它找到控制器规个。
main()方法使用Spring Boot的SpringApplication.run()方法來(lái)啟動(dòng)應(yīng)用程序。你有注意到一行XML姓建?沒(méi)有** web.xml **文件诞仓。這個(gè)Web應(yīng)用程序是100%純Java,你不必處理配置任何管道或基礎(chǔ)設(shè)施速兔。
還有一個(gè)CommandLineRunner墅拭,注入BookRepository和 用不同的參數(shù)調(diào)用它幾次。
src/main/java/hello/AppRunner.java
package hello;
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"));
}
}
如果你嘗試在此時(shí)運(yùn)行應(yīng)用程序涣狗,您會(huì)注意到它很慢谍婉,即使您幾次檢索完全相同的書(shū)舒憾。
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'}
從時(shí)間戳可以看出,每本書(shū)花了大約三秒鐘來(lái)檢索屡萤,即使它是相同的標(biāo)題被重復(fù)抓取珍剑。
Enable caching
讓我們?cè)谀愕腟impleBookRepository上啟用緩存掸宛,這樣書(shū)就會(huì)被緩存在books緩存中死陆。
src/main/java/hello/SimpleBookRepository.java
package hello;
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);
}
}
}
您現(xiàn)在需要啟用緩存注解的處理
src/main/java/hello/Application.java
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@EnableCaching注解觸發(fā)檢查并處理每個(gè)Spring bean用于存在對(duì)公共方法的緩存注解。如果找到這樣的注解唧瘾,則自動(dòng)創(chuàng)建代理以攔截方法調(diào)用并相應(yīng)地處理緩存行為措译。
緩存處理的相應(yīng)注解是Cacheable
,CachePut
和CacheEvict
.有關(guān)更多詳細(xì)信息饰序,可以參考javadocs和文檔领虹。
Spring Boot會(huì)自動(dòng)配置一個(gè)合適的CacheManager,作為相關(guān)緩存求豫。有關(guān)更多詳細(xì)信息塌衰,請(qǐng)參閱Spring Boot文檔。
我們的示例不使用特定的緩存庫(kù)蝠嘉,因此我們的緩存存儲(chǔ)是使用ConcurrentHashMap的簡(jiǎn)單回退最疆。緩存抽象支持各種各樣的緩存庫(kù),并完全符合JSR-107(JCache)蚤告。
Build an executable JAR
您可以使用Gradle或Maven從命令行運(yùn)行應(yīng)用程序努酸。 或者,您可以構(gòu)建單個(gè)可執(zhí)行文件杜恰,其中包含所有必需的依賴關(guān)系获诈,類和資源,并運(yùn)行它心褐。 這使得在整個(gè)開(kāi)發(fā)生命周期中舔涎,易于跨不同環(huán)境將服務(wù)作為應(yīng)用程序進(jìn)行發(fā)布,維護(hù)版本和部署等等逗爹。
如果您使用Gradle终抽,可以使用./gradlew bootRun運(yùn)行應(yīng)用程序。 或者你可以使用./gradlew build來(lái)構(gòu)建JAR文件桶至。 然后可以運(yùn)行JAR文件:
java -jar build/libs/gs-caching-0.1.0.jar
如果您使用Maven昼伴,可以使用./mvnw spring-boot:run運(yùn)行應(yīng)用程序。 或者你可以用./mvnw clean package構(gòu)建JAR文件镣屹。 然后可以運(yùn)行JAR文件:
java -jar target/gs-caching-0.1.0.jar
**上面的過(guò)程將創(chuàng)建一個(gè)可運(yùn)行的JAR圃郊。 您也可以選擇build a classic WAR file
Test the application
現(xiàn)在緩存已啟用,您可以再次執(zhí)行它女蜈,并通過(guò)添加或不使用相同的isbn的額外調(diào)用查看差異持舆。 你應(yīng)該可以看到其產(chǎn)生明顯的區(qū)別色瘩。
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'}
This excerpt from the console shows that the first time to fetch each title took three seconds, but each subsequent call was near instantaneous.
從控制臺(tái)的這段日志顯示,第一次獲取每個(gè)標(biāo)題花了三秒鐘逸寓,但每個(gè)后續(xù)的訪問(wèn)接近瞬間居兆。
最后###
恭喜! 你剛剛通過(guò)Springcache在托管bean上啟用了緩存竹伸。