亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot使用Caffeine實(shí)現(xiàn)緩存的示例代碼

 更新時(shí)間:2022年07月04日 15:04:34   作者:JavaMonsterr  
本文主要介紹了SpringBoot使用Caffeine實(shí)現(xiàn)緩存的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

在本博客中,我們將探討如何使用Spring的緩存框架向任何Spring Boot應(yīng)用程序添加基本緩存支持,如果沒(méi)有正確實(shí)現(xiàn),還將探討緩存的一些問(wèn)題。最后但并非最不重要的一點(diǎn)是,我們將看幾個(gè)在真實(shí)場(chǎng)景中有用的緩存示例。

為什么要在應(yīng)用程序中添加緩存

在深入探討如何向應(yīng)用程序添加緩存之前,首先想到的問(wèn)題是為什么我們需要在應(yīng)用程序中使用緩存。

假設(shè)有一個(gè)包含客戶(hù)數(shù)據(jù)的應(yīng)用程序,用戶(hù)發(fā)出兩個(gè)請(qǐng)求來(lái)獲取客戶(hù)的數(shù)據(jù)(id=100)。

這就是沒(méi)有緩存時(shí)的情況。

如您所見(jiàn),對(duì)于每個(gè)請(qǐng)求,應(yīng)用程序都會(huì)轉(zhuǎn)到數(shù)據(jù)庫(kù)獲取數(shù)據(jù)。從數(shù)據(jù)庫(kù)獲取數(shù)據(jù)是一項(xiàng)成本高昂的操作,因?yàn)樗婕癐O。

但是,如果中間有一個(gè)緩存存儲(chǔ),可以在其中臨時(shí)存儲(chǔ)短時(shí)間的數(shù)據(jù),則可以將這些往返保存到數(shù)據(jù)庫(kù)并在IO時(shí)間保存。

這就是使用緩存時(shí)上述交互的樣子。

在Spring Boot應(yīng)用程序中實(shí)現(xiàn)緩存

SpringBoot提供了什么緩存支持?

  • SpringBoot只提供了一個(gè)緩存抽象,您可以使用它將緩存透明、輕松地添加到Spring應(yīng)用程序中。
  • 它不提供實(shí)際的緩存存儲(chǔ)。
  • 但是,它可以與不同類(lèi)型的緩存提供程序一起工作,如Ehcache、Hazelcast、Redis、Caffee等。
  • SpringBoot的緩存抽象可以添加到方法中(使用注釋?zhuān)?/li>
  • 基本上,在執(zhí)行方法之前,Spring框架將檢查方法數(shù)據(jù)是否已經(jīng)緩存
  • 如果是,則它將從緩存中獲取數(shù)據(jù)。
  • 否則它將執(zhí)行該方法并緩存數(shù)據(jù)
  • 它還提供了從緩存中更新或刪除數(shù)據(jù)的抽象。
  • 在我們當(dāng)前的博客中,我們將了解如何使用Caffeine添加緩存,Caffeine是一種基于Java8的高性能、接近最優(yōu)的緩存庫(kù)。

您可以在 application.yaml 文件中指定使用哪個(gè)緩存提供程序來(lái)設(shè)置 spring.cache.type 屬性。

但是,如果沒(méi)有提供屬性,Spring將根據(jù)添加的庫(kù)自動(dòng)檢測(cè)緩存提供程序。

添加生成依賴(lài)項(xiàng)

現(xiàn)在假設(shè)您已經(jīng)啟動(dòng)并運(yùn)行了基本的Spring boot應(yīng)用程序,讓我們添加緩存依賴(lài)項(xiàng)。

打開(kāi) build.gradle 文件,并添加以下依賴(lài)項(xiàng)以啟用Spring Boot的緩存

compile('org.springframework.boot:spring-boot-starter-cache')

接下來(lái)我們將添加對(duì)Caffeine的依賴(lài)

compile group: 'com.github.ben-manes.caffeine', name: 'caffeine', version: '2.8.5'

緩存配置

現(xiàn)在我們需要在Spring Boot應(yīng)用程序中啟用緩存。

為此,我們需要?jiǎng)?chuàng)建一個(gè)配置類(lèi)并提供注釋 @EnableCaching 。

@Configuration
@EnableCaching
public class CacheConfig {
     
}

現(xiàn)在這個(gè)類(lèi)是一個(gè)空類(lèi),但是我們可以向它添加更多配置(如果需要)。

現(xiàn)在我們已經(jīng)啟用了緩存,讓我們提供緩存名稱(chēng)和緩存屬性的配置,如緩存大小、緩存過(guò)期時(shí)間等

最簡(jiǎn)單的方法是在 application.yaml 中添加配置

spring:
  cache:
    cache-names: customers, users, roles
    caffeine:
      spec: maximumSize=500, expireAfterAccess=60s

上述配置執(zhí)行以下操作

  • 將可用緩存名稱(chēng)限制為客戶(hù)、用戶(hù)和角色。將最大緩存大小設(shè)置為500。
  • 當(dāng)緩存中的對(duì)象數(shù)達(dá)到此限制時(shí),將根據(jù)緩存逐出策略從緩存中刪除對(duì)象。將緩存過(guò)期時(shí)間設(shè)置為1分鐘。
  • 這意味著項(xiàng)目將在添加到緩存1分鐘后從緩存中刪除。

還有另一種配置緩存的方法,而不是在 application.yaml 文件中配置緩存。

您可以在緩存配置類(lèi)中添加并提供一個(gè) CacheManager Bean,該Bean可以完成與上面在 application.yaml 中的配置完全相同的工作

@Bean
public CacheManager cacheManager() {
    Caffeine<Object, Object> caffeineCacheBuilder =
        Caffeine.newBuilder()
            .maximumSize(500)
            .expireAfterAccess(
                    1, TimeUnit.MINUTES);
     
    CaffeineCacheManager cacheManager = 
            new CaffeineCacheManager(
            "customers", "roles", "users");
    cacheManager.setCaffeine(caffeineCacheBuilder);
    return cacheManager;
}

在我們的代碼示例中,我們將使用Java配置。

我們可以在Java中做更多的事情,比如配置 RemovalListener ,當(dāng)一個(gè)項(xiàng)從緩存中刪除時(shí)執(zhí)行 RemovalListener ,或者啟用緩存統(tǒng)計(jì)記錄,等等。

緩存方法結(jié)果

在我們使用的示例Spring boot應(yīng)用程序中,我們已經(jīng)有了以下API GET /API/v1/customer/{id} 來(lái)檢索客戶(hù)記錄。

我們將向CustomerService類(lèi)的 getCustomerByd(longCustomerId) 方法添加緩存。

要做到這一點(diǎn),我們只需要做兩件事

1. 將注釋 @CacheConfig(cacheNames=“customers”) 添加到 CustomerService 類(lèi)

提供此選項(xiàng)將確保 CustomerService 的所有可緩存方法都將使用緩存名稱(chēng)“customers”

2. 向方法 Optional getCustomerById(Long customerId) 添加注釋 @Cacheable

@Service
@Log4j2
@CacheConfig(cacheNames = "customers")
public class CustomerService {
 
    @Autowired
    private CustomerRepository customerRepository;
 
    @Cacheable
    public Optional<Customer> getCustomerById(Long customerId) {
        log.info("Fetching customer by id: {}", customerId);
        return customerRepository.findById(customerId);
    }
}

另外,在方法 getCustomerById() 中添加一個(gè) LOGGER 語(yǔ)句,以便我們知道服務(wù)方法是否得到執(zhí)行,或者值是否從緩存返回。

復(fù)制代碼 代碼如下:
log.info("Fetching customer by id: {}", customerId);

測(cè)試緩存是否正常工作

這就是緩存工作所需的全部?jī)?nèi)容。現(xiàn)在是測(cè)試緩存的時(shí)候了。

啟動(dòng)您的應(yīng)用程序,并點(diǎn)擊客戶(hù)獲取url

http://localhost:8080/api/v1/customer/

在第一次API調(diào)用之后,您將在日志中看到以下行—“ Fetching customer by id ”。

但是,如果再次點(diǎn)擊API,您將不會(huì)在日志中看到任何內(nèi)容。這意味著該方法沒(méi)有得到執(zhí)行,并且從緩存返回客戶(hù)記錄。

現(xiàn)在等待一分鐘(因?yàn)榫彺孢^(guò)期時(shí)間設(shè)置為1分鐘)。

一分鐘后再次點(diǎn)擊GETAPI,您將看到下面的語(yǔ)句再次被記錄——“通過(guò)id獲取客戶(hù)”。

這意味著客戶(hù)記錄在1分鐘后從緩存中刪除,必須再次從數(shù)據(jù)庫(kù)中獲取。

為什么緩存有時(shí)會(huì)很危險(xiǎn)

緩存更新/失效

通常我們緩存 GET 調(diào)用,以提高性能。

但我們需要非常小心的是緩存對(duì)象的更新/刪除。

@CachePut
@cacheexecute

如果未將 @CachePut/@cacheexecute 放入更新/刪除方法中,GET調(diào)用中緩存返回的對(duì)象將與數(shù)據(jù)庫(kù)中存儲(chǔ)的對(duì)象不同。考慮下面的示例場(chǎng)景。

如您所見(jiàn),第二個(gè)請(qǐng)求已將人名更新為“ John Smith ”。但由于它沒(méi)有更新緩存,因此從此處開(kāi)始的所有請(qǐng)求都將從緩存中獲取過(guò)時(shí)的個(gè)人記錄(“ John Doe ”),直到該項(xiàng)在緩存中被刪除/更新。

緩存復(fù)制

大多數(shù)現(xiàn)代web應(yīng)用程序通常有多個(gè)應(yīng)用程序節(jié)點(diǎn),并且在大多數(shù)情況下都有一個(gè)負(fù)載平衡器,可以將用戶(hù)請(qǐng)求重定向到一個(gè)可用的應(yīng)用程序節(jié)點(diǎn)。

這種類(lèi)型的部署為應(yīng)用程序提供了可伸縮性,任何用戶(hù)請(qǐng)求都可以由任何一個(gè)可用的應(yīng)用程序節(jié)點(diǎn)提供服務(wù)。

在這些分布式環(huán)境(具有多個(gè)應(yīng)用服務(wù)器節(jié)點(diǎn))中,緩存可以通過(guò)兩種方式實(shí)現(xiàn)

  • 應(yīng)用服務(wù)器中的嵌入式緩存(正如我們現(xiàn)在看到的)
  • 遠(yuǎn)程緩存服務(wù)器

嵌入式緩存

嵌入式緩存駐留在應(yīng)用程序服務(wù)器中,它隨應(yīng)用程序服務(wù)器啟動(dòng)/停止。由于每臺(tái)服務(wù)器都有自己的緩存副本,因此對(duì)其緩存的任何更改/更新都不會(huì)自動(dòng)反映在其他應(yīng)用程序服務(wù)器的緩存中。

考慮具有嵌入式緩存的多節(jié)點(diǎn)應(yīng)用服務(wù)器的下面場(chǎng)景,其中用戶(hù)可以根據(jù)應(yīng)用服務(wù)器為其請(qǐng)求服務(wù)而得到不同的結(jié)果。

正如您在上面的示例中所看到的,更新請(qǐng)求更新了 Application Node2 的數(shù)據(jù)庫(kù)和嵌入式緩存。

但是, Application Node1 的嵌入式緩存未更新,并且包含過(guò)時(shí)數(shù)據(jù)。因此, Application Node1 的任何請(qǐng)求都將繼續(xù)服務(wù)于舊數(shù)據(jù)。

要解決這個(gè)問(wèn)題,您需要實(shí)現(xiàn) CACHE REPLICATION —其中任何一個(gè)緩存中的任何更新都會(huì)自動(dòng)復(fù)制到其他緩存(下圖中顯示為藍(lán)色虛線)

遠(yuǎn)程緩存服務(wù)器

解決上述問(wèn)題的另一種方法是使用遠(yuǎn)程緩存服務(wù)器(如下所示)。

 

然而,這種方法的最大缺點(diǎn)是增加了響應(yīng)時(shí)間——這是由于從遠(yuǎn)程緩存服務(wù)器獲取數(shù)據(jù)時(shí)的網(wǎng)絡(luò)延遲(與內(nèi)存緩存相比)

緩存自定義

到目前為止,我們看到的緩存示例是向應(yīng)用程序添加基本緩存所需的唯一代碼。

然而,現(xiàn)實(shí)世界的場(chǎng)景可能不是那么簡(jiǎn)單,可能需要進(jìn)行一些定制。在本節(jié)中,我們將看到幾個(gè)這樣的例子

緩存密鑰

我們知道緩存是密鑰、值對(duì)的存儲(chǔ)。

示例1:默認(rèn)緩存鍵–具有單參數(shù)的方法

最簡(jiǎn)單的緩存鍵是當(dāng)方法只有一個(gè)參數(shù),并且該參數(shù)成為緩存鍵時(shí)。在下面的示例中, Long customerId 是緩存鍵

示例2:默認(rèn)緩存鍵–具有多個(gè)參數(shù)的方法

在下面的示例中,緩存鍵是所有三個(gè)參數(shù)的SimpleKey– countryId 、 regionId 、 personId 。

示例3:自定義緩存密鑰

在下面的示例中,我們將此人的 emailAddress 指定為緩存的密鑰

示例4:使用 KeyGenerator 的自定義緩存密鑰

讓我們看看下面的示例–如果要緩存當(dāng)前登錄用戶(hù)的所有角色,該怎么辦。

該方法中沒(méi)有提供任何參數(shù),該方法在內(nèi)部獲取當(dāng)前登錄用戶(hù)并返回其角色。

為了實(shí)現(xiàn)這個(gè)需求,我們需要?jiǎng)?chuàng)建一個(gè)如下所示的自定義密鑰生成器

然后我們可以在我們的方法中使用這個(gè)鍵生成器,如下所示。

條件緩存

在某些用例中,我們只希望在滿(mǎn)足某些條件的情況下緩存結(jié)果

示例1(支持 java.util.Optional –僅當(dāng)存在時(shí)才緩存)

僅當(dāng)結(jié)果中存在 person 對(duì)象時(shí),才緩存 person 對(duì)象。

@Cacheable( value = "persons", unless = "#result?.id")
public Optional<Person> getPerson(Long personId)

示例2(如果需要,by-pass緩存)

@Cacheable(value = "persons", condition="#fetchFromCache")
public Optional<Person> getPerson(long personId, boolean fetchFromCache)

僅當(dāng)方法參數(shù)“ fetchFromCache ”為true時(shí),才從緩存中獲取人員。通過(guò)這種方式,方法的調(diào)用方有時(shí)可以決定繞過(guò)緩存并直接從數(shù)據(jù)庫(kù)獲取值。

示例3(基于對(duì)象屬性的條件計(jì)算)

僅當(dāng)價(jià)格低于500且產(chǎn)品有庫(kù)存時(shí),才緩存產(chǎn)品。

@Cacheable( 
   value="products", 
   condition="#product.price<500",
   unless="#result.outOfStock")
public Product findProduct(Product product)

@CachePut

我們已經(jīng)看到 @Cacheable 用于將項(xiàng)目放入緩存。

但是,如果該對(duì)象被更新,并且我們想要更新緩存,該怎么辦?

我們已經(jīng)在前面的一節(jié)中看到,不更新緩存post任何更新操作都可能導(dǎo)致從緩存返回錯(cuò)誤的結(jié)果。

@CachePut(key = "#person.id")
public Person update(Person person)

但是如果 @Cacheable 和 @CachePut 都將一個(gè)項(xiàng)目放入緩存,它們之間有什么區(qū)別?

主要區(qū)別在于實(shí)際的方法執(zhí)行

@Cacheable
@CachePut

緩存失效

緩存失效與將對(duì)象放入緩存一樣重要。

當(dāng)我們想要從緩存中刪除一個(gè)或多個(gè)對(duì)象時(shí),有很多場(chǎng)景。讓我們看一些例子。

例1

假設(shè)我們有一個(gè)用于批量導(dǎo)入個(gè)人記錄的API。

我們希望在調(diào)用此方法之前,應(yīng)該清除整個(gè) person 緩存(因?yàn)榇蠖鄶?shù) person 記錄可能會(huì)在導(dǎo)入時(shí)更新,而緩存可能會(huì)過(guò)時(shí))。我們可以這樣做如下

@CacheEvict(
   value = "persons", 
   allEntries = true, 
   beforeInvocation = true)
public void importPersons()

例2

我們有一個(gè)Delete Person API,我們希望它在刪除時(shí)也能從緩存中刪除 Person 記錄。

@CacheEvict(
   value = "persons", 
   key = "#person.emailAddress")
public void deletePerson(Person person)

默認(rèn)情況下 @CacheEvict 在方法調(diào)用后運(yùn)行。

到此這篇關(guān)于SpringBoot使用Caffeine實(shí)現(xiàn)緩存的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot Caffeine緩存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IntelliJ?IDEA?2020.2?全家桶及以下版本激活工具大全【喜訊】

    IntelliJ?IDEA?2020.2?全家桶及以下版本激活工具大全【喜訊】

    這篇文章主要介紹了IntelliJ?IDEA?2020.2?全家桶及以下版本激活工具大全【喜訊】,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • SpringBoot如何使用自定義注解實(shí)現(xiàn)接口限流

    SpringBoot如何使用自定義注解實(shí)現(xiàn)接口限流

    這篇文章主要介紹了SpringBoot如何使用自定義注解實(shí)現(xiàn)接口限流,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java中的三種標(biāo)準(zhǔn)注解和四種元注解說(shuō)明

    Java中的三種標(biāo)準(zhǔn)注解和四種元注解說(shuō)明

    這篇文章主要介紹了Java中的三種標(biāo)準(zhǔn)注解和四種元注解說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • springboot中RestTemplate發(fā)送HTTP請(qǐng)求的實(shí)現(xiàn)示例

    springboot中RestTemplate發(fā)送HTTP請(qǐng)求的實(shí)現(xiàn)示例

    RestTemplate是一個(gè) spring-web 提供的執(zhí)行HTTP請(qǐng)求的同步阻塞式工具類(lèi),本文就來(lái)介紹一下RestTemplate發(fā)送HTTP請(qǐng)求,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • 淺談Thread.sleep()為什么要拋出中斷異常

    淺談Thread.sleep()為什么要拋出中斷異常

    本文主要介紹了淺談Thread.sleep()為什么要拋出中斷異常,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • idea中方法、注釋、導(dǎo)入類(lèi)折疊或是展開(kāi)的設(shè)置方法

    idea中方法、注釋、導(dǎo)入類(lèi)折疊或是展開(kāi)的設(shè)置方法

    這篇文章主要介紹了idea中方法、注釋、導(dǎo)入類(lèi)折疊或是展開(kāi)的設(shè)置,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • Spring事物的傳播特性詳解

    Spring事物的傳播特性詳解

    這篇文章主要介紹了Spring事物的傳播性詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-05-05
  • Java正確比較浮點(diǎn)數(shù)的方法

    Java正確比較浮點(diǎn)數(shù)的方法

    這篇文章主要介紹了Java正確比較浮點(diǎn)數(shù)的方法,幫助大家更好的利用Java比較浮點(diǎn)數(shù)數(shù)據(jù),感興趣的朋友可以了解下
    2020-11-11
  • Spring 注入static屬性值方式

    Spring 注入static屬性值方式

    文本介紹了Spring如何從屬性文件給static屬性注入值,在寫(xiě)一些與配置相關(guān)的工具類(lèi)時(shí)常用。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 詳解Spring Boot 打包分離依賴(lài)JAR 和配置文件

    詳解Spring Boot 打包分離依賴(lài)JAR 和配置文件

    這篇文章主要介紹了Spring Boot 打包分離依賴(lài)JAR 和配置文件,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11

最新評(píng)論