欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot整合SpringCache緩存的實現(xiàn)示例

 更新時間:2025年07月07日 10:01:59   作者:陌殤殤  
本文主要使用springcache緩存管理技術(shù)高效處理緩存,支持本地緩存,redis等,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧

1.介紹

Spring Cache 提供了 CacheCacheManager 接口來統(tǒng)一管理不同的緩存技術(shù)。Cache 是緩存的抽象,CacheManager 負責管理多個 Cache 實例。Spring Cache 支持多種緩存實現(xiàn),包括:

  • ConcurrentHashMap:默認的緩存實現(xiàn),適用于簡單的本地緩存。
  • Redis:基于 Redis 的分布式緩存,適用于高并發(fā)場景。
  • Ehcache:符合 JSR-107 標準的緩存實現(xiàn),支持二級緩存。
  • Caffeine:基于 Java 8 的高性能緩存庫,適用于需要高性能的場景。
  • JSR-107:支持 JSR-107 標準的緩存實現(xiàn)。

2.SpringBoot整合

本文基于springboot2.7版本測試

1.導入xml依賴

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

2.配置yml

spring:
  cache:
    cache-names: user
    type: redis
    redis:
      #緩存前綴
      key-prefix: moshangshang_
      #是否啟用緩存統(tǒng)計信息。
      enable-statistics: false
      #是否允許緩存 null 值。
      cache-null-values: true
      #寫入 Redis 時是否使用 key prefix。
      use-key-prefix: true

  redis:
    port: 6379
    host: 127.0.0.1
    password: root
    lettuce:
      pool:
        max-active: 20 #連接池最大連接數(shù)(使用負值表示沒有限制)
        max-idle: 8   #連接池中的最大空閑連接
        min-idle: 5   # 連接池中的最小空閑連接
    timeout: 6000   #連接超時時長(毫秒)

如果cache-null-values:屬性啟用不能緩存null值,則緩存null時會拋出下方異常

java.lang.IllegalArgumentException: Cache 'user' does not allow 'null' values. Avoid storing null via '@Cacheable(unless="#result == null")' or configure RedisCache to allow 'null' via RedisCacheConfiguration.

cache-names屬性說明:

用于管理全的緩存key的全局配置,多個用逗號分割,比如 cache-names: user; use-key-prefix: false,則表示 @Cacheable(cacheNames = "user“)之類的注解不會使用key-prefix指定的緩存前綴,未配置的緩存名稱則采用默認全局配置

3.使用@EnableCaching啟用SpringCache

@SpringBootApplication
@EnableCaching
public class CacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheApplication.class, args);
    }
}

4.@Cacheable

@Cacheable 用于標記方法或類,表示該方法的返回值可以被緩存。
當方法執(zhí)行前,Spring 會檢查緩存中是否存在相同 key 的緩存元素,如果存在則直接返回,否則執(zhí)行方法并將結(jié)果存入緩存。

@Cacheable 的方法必須為 public:如果方法不是 public 的,Spring 無法通過代理來訪問緩存。

  • value 或 cacheNames:指定緩存的名稱,可以是單個字符串或字符串數(shù)組。
  • key:指定緩存的鍵,可以使用 SpEL 表達式來定義。
  • condition:指定緩存的條件,只有當條件為 true 時,才會從緩存中獲取結(jié)果。
  • unless:指定不將結(jié)果放入緩存的條件,即使結(jié)果存在,也不會被緩存。
  • sync:是否使用同步方式獲取緩存,避免多個線程同時執(zhí)行方法。
  • 在某些場景下,需要確保緩存和數(shù)據(jù)庫的一致性,可以使用 @Cacheable 的 sync 屬性來啟用同步更新。且在多線程環(huán)境下確保只有一個線程執(zhí)行查詢。
   /**
     * 根據(jù)id查詢用戶信息
     * 生成的key為moshangshang_user::38
     */
    @GetMapping("/query/{id}")
    @Cacheable(cacheNames = "user",key = "#id",unless = "#result == null")
    public User getById(@PathVariable Long id){
        return userService.getById(id);
    }

5.@CachePut

@CachePut 用于標記方法,表示每次調(diào)用該方法時都會執(zhí)行并存入緩存。

它總是會執(zhí)行方法,并將結(jié)果添加到緩存中,不會檢查緩存中是否存在相同 key 的緩存元素。

  • value 或 cacheNames:指定緩存的名稱,可以是單個字符串或字符串數(shù)組。
  • key:指定緩存的鍵,可以使用 SpEL 表達式來定義。
  • condition:指定緩存的條件,只有當條件為 true 時,才會從緩存中獲取結(jié)果。
  • unless:指定不將結(jié)果放入緩存的條件,即使結(jié)果存在,也不會被緩存。
    @PostMapping("/save")
    @CachePut( key = "#user.id")
    public User updateUser(User user) {
        userService.saveOrUpdate(user);
        return user;
    }

6.@CacheEvict

@CacheEvict 用于標記方法,表示該方法執(zhí)行時會清除緩存中的數(shù)據(jù)。

@CacheEvict 在方法執(zhí)行期間拋出異常不會清空緩存:如果方法執(zhí)行過程中拋出異常,@CacheEvict 的 allEntries 屬性不會生效。

它可以用于刪除緩存中的所有鍵值對,也可以用于清除特定的 key。

  • value 或 cacheNames:指定緩存的名稱,可以是單個字符串或字符串數(shù)組。
  • key:指定緩存的鍵,可以使用 SpEL 表達式來定義。
  • condition:指定緩存的條件,只有當條件為 true 時,才會從緩存中獲取結(jié)果。
  • beforeInvocation:是否在方法執(zhí)行前清除緩存,為 true 時在方法執(zhí)行前清除緩存。
  • allEntries:是否清除所有緩存條目,為 true 時清除所有緩存。
    /**
     * @CacheEvict 在方法執(zhí)行期間拋出異常不會清空緩存:如果方法執(zhí)行過程中拋出異常,@CacheEvict 的 allEntries 屬性不會生效。
     * @CacheEvict 用于標記方法,表示該方法執(zhí)行時會清除緩存中的數(shù)據(jù)。
     * 它可以用于刪除緩存中的所有鍵值對,也可以用于清除特定的 key。
     * value 或 cacheNames:指定要清除的緩存名稱。
     * key:指定要清除的緩存鍵,可以使用 SpEL 表達式來定義。
     * allEntries:是否清除所有緩存條目,為 true 時清除所有緩存。
     * beforeInvocation:是否在方法執(zhí)行前清除緩存,為 true 時在方法執(zhí)行前清除緩存。
     * condition:指定清除緩存的條件,只有當條件為 true 時,才會清除緩存。
     */
    @GetMapping("/delete/{id}")
    @CacheEvict(key = "#id", allEntries = false)
    public void deleteUser(@PathVariable Long id) {
        userService.removeById(id);
    }

7. @Caching

@Caching 是一個組合注解,可以同時應用多個其他注解,表示該方法會同時執(zhí)行 @Cacheable、@CachePut 和 @CacheEvict 的操作。

    @GetMapping("/save/caching")
    @Caching(
            cacheable = @Cacheable( key = "#user.id"),
            put = @CachePut( key = "#user.id"),
            evict = @CacheEvict( key = "#user.id")
    )
    public User saveUser(User user) {
        userService.save(user);
        return user;
    }

8.@CacheConfig

@CacheConfig 用于在類上設(shè)置公共的緩存配置,避免在每個方法上重復配置。

/**
 * @CacheConfig 用于在類上設(shè)置公共的緩存配置,避免在每個方法上重復配置。
 */
@RestController
@AllArgsConstructor
@RequestMapping("cache")
@CacheConfig(cacheNames = "user")
public class CacheController {

    private final IUserService userService;

 
    @GetMapping("/query/{id}")
    @Cacheable(key = "#id",unless = "#result == null")
    public User getById(@PathVariable Long id){
        return userService.getById(id);
    }
}

3.其他屬性配置

1.keyGenerator屬性

keyGenerator 屬性用于指定默認的鍵生成器(Key Generator)。如果在方法上未顯式指定 key 屬性,則使用該屬性值作為默認的鍵生成器。

1.配置生成器

@Configuration
public class CacheConfig {

    @Bean(name = "customKeyGenerator")
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> method.getName() + "[" + Arrays.asList(params) + "]";
    }
}

等同于

    @Bean(name = "customKeyGenerator")
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                return method.getName() + "[" + Arrays.asList(params) + "]";
            }
        };
    }

2.使用

生成的key為moshangshang_user::getById[[39]]

    @Cacheable(unless = "#result == null",keyGenerator = "customKeyGenerator")
    public User getById(@PathVariable Long id){
        return userService.getById(id);
    }

2.cacheManager屬性

cacheManager 屬性用于指定當前使用的 CacheManager 實現(xiàn)類的名稱。CacheManager 是 Spring 定義的一個接口,用于管理緩存(Cache)的創(chuàng)建和配置。Spring 提供了多種 CacheManager 的實現(xiàn),例如 ConcurrentMapCacheManagerEhCacheCacheManager、CaffeineCacheManager 等。通過設(shè)置 cacheManager 屬性,可以指定使用哪種緩存管理器來管理緩存。

創(chuàng)建自定義的緩存管理器

@Configuration
public class CacheConfig {
    
    @Bean
    public ConcurrentMapCacheManager mapCacheManager() {
        return new ConcurrentMapCacheManager("user-map","user");
    }
    
}

cacheManager() 方法返回了一個 ConcurrentMapCacheManager 實例,并且指定了緩存名稱。這個 CacheManager 將被用于管理名為 指定的緩存。

    /**
     * 執(zhí)行的是mapCacheManager的緩存管理器
     */
    @GetMapping("/manger/map/query/{id}")
    @Cacheable(cacheManager = "mapCacheManager")
    public User getRedisMangerById(@PathVariable Long id){
        return userService.getById(id);
    }

3.cacheResolver屬性

cacheResolver 屬性用于指定一個自定義的 CacheResolver 實現(xiàn)。默認情況下,Spring 使用 SimpleCacheResolver 來解析緩存操作。通過自定義 CacheResolver,可以實現(xiàn)更復雜的緩存邏輯,例如根據(jù)方法名動態(tài)選擇緩存名稱或緩存管理器。

  • cacheManager 和 cacheResolver 是互斥的:如果同時指定了 cacheManager 和 cacheResolver,Spring 會拋出異常,因為 CacheResolver 的實現(xiàn)會忽略自定義的 CacheManager 。
  • 自定義 CacheResolver 的靈活性:通過自定義 CacheResolver,可以實現(xiàn)更靈活的緩存管理,例如根據(jù)方法名、參數(shù)或上下文動態(tài)選擇緩存名稱或緩存管理器 。
  • Spring 4.1 及以上版本:從 Spring 4.1 開始,@Cacheable、@CachePut、@CacheEvict 等注解的 value 屬性不再是強制性的,因為 CacheResolver 可以提供緩存名稱信息

自定義緩存解析器

getById方法取user緩存名稱下數(shù)據(jù),其他取user-map下數(shù)據(jù)

public class CustomCacheResolver implements CacheResolver {
    
    private final ConcurrentMapCacheManager concurrentMapCacheManager;
    
    private final RedisCacheManager redisCacheManager;

    public CustomCacheResolver(ConcurrentMapCacheManager concurrentMapCacheManager, 
                               RedisCacheManager redisCacheManager) {
        this.concurrentMapCacheManager = concurrentMapCacheManager;
        this.redisCacheManager = redisCacheManager;
    }



    @Override
    public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
        Collection<Cache> caches = new ArrayList<>();
        if (context.getTarget().getClass() == CacheController.class) {
            if (context.getMethod().getName().equals("getRedisById")) {
                caches.add(redisCacheManager.getCache("user"));
            }else {
                caches.add(concurrentMapCacheManager.getCache("user-map"));
            }
        }
        return caches;
    }
}

配置自定義緩存管理器并注冊緩存解析器

配置了自定義的CacheManager會導致yml里面的相關(guān)配置失效(任何一個都會,比如指定map的緩存管理器,yml配redis,則redis的配置也不生效)

    @Bean
    public ConcurrentMapCacheManager mapCacheManager() {
        return new ConcurrentMapCacheManager("user-map","user");
    }


    @Primary
    @Bean
    public RedisCacheManager redisCacheManager(RedisTemplate<String, Object> redisTemplate) {
        return RedisCacheManager.builder(Objects.requireNonNull(redisTemplate.getConnectionFactory()))
                .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(Duration.ofMinutes(10)) // 設(shè)置默認緩存過期時間為10分鐘
                        .disableCachingNullValues()) // 禁用緩存空值
                .withInitialCacheConfigurations(initialCacheConfigurations()) // 設(shè)置特定緩存的配置
                .build();
    }

    private Map<String, RedisCacheConfiguration> initialCacheConfigurations() {
        Map<String, RedisCacheConfiguration> initialConfigurations = new HashMap<>();
        // 設(shè)置特定緩存的過期時間
        initialConfigurations.put("user", RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(1)) // 設(shè)置特定緩存的過期時間為1小時
                .disableCachingNullValues());
        return initialConfigurations;
    }

    @Bean
    public CacheResolver customCacheResolver(ConcurrentMapCacheManager concurrentMapCacheManager,
                                             RedisCacheManager redisCacheManager) {
        return new CustomCacheResolver(concurrentMapCacheManager,redisCacheManager);
    }

測試

  /**
     * 執(zhí)行的是RedisCacheManager的緩存管理器
     */
    @GetMapping("/resolver/redis/query/{id}")
    @Cacheable(unless = "#result == null",cacheResolver = "customCacheResolver")
    public User getRedisById(@PathVariable Long id){
        return userService.getById(id);
    }

    /**
     * 執(zhí)行的是ConcurrentMapCacheManager的緩存管理器
     */
    @GetMapping("/resolver/map/query/{id}")
    @Cacheable(cacheNames = "user-map",unless = "#result == null",cacheResolver = "customCacheResolver")
    public User getMapCacheById(@PathVariable Long id){
        return userService.getById(id);
    }

4.CacheManagerCustomizer

CacheManagerCustomizer 是一個用于在緩存管理器初始化之前對其進行自定義配置的接口。通過實現(xiàn)該接口的 Bean,可以對緩存管理器進行定制,例如設(shè)置緩存名稱、是否允許緩存空值、設(shè)置緩存過期時間等。

  • 自定義緩存配置:CacheManagerCustomizer 允許在緩存管理器初始化之前對緩存進行配置,例如設(shè)置緩存名稱、過期時間、序列化方式等。這使得開發(fā)者可以針對不同的緩存需求進行靈活配置。
  • 覆蓋默認配置:如果使用了 CacheManagerCustomizer,那么 application.yml 或 application.properties 中的緩存配置將不會生效,因為 CacheManagerCustomizer 會覆蓋默認的配置 。
  • 支持多種緩存類型:CacheManagerCustomizer 不僅適用于 ConcurrentMapCacheManager,還可以用于其他類型的緩存管理器,如 RedisCacheManager、CaffeineCacheManager 等。通過實現(xiàn) CacheManagerCustomizer 接口,可以對不同類型的緩存管理器進行統(tǒng)一的配置 。
  • 提供回調(diào)機制:CacheManagerCustomizer 提供了一個 customize 方法,該方法會在緩存管理器初始化之前被調(diào)用,允許開發(fā)者對緩存管理器進行定制。例如,可以設(shè)置緩存名稱、允許或禁止緩存空值等 。
@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
    return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {
        @Override
        public void customize(ConcurrentMapCacheManager cacheManager) {
            cacheManager.setCacheNames(Arrays.asList("user"));
            cacheManager.setAllowNullValues(false); // 禁用緩存空值
        }
    };
}


    @Bean
    public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
        return (builder) -> {
            builder.cacheDefaults(
                    RedisCacheConfiguration.defaultCacheConfig()
                            .entryTtl(Duration.ofMinutes(10)) // 默認過期時間為 10 分鐘
                            .disableCachingNullValues()); // 禁用緩存空值
        };
    }

如果配置了自定義的緩存管理器(redisCacheManager),則CacheManagerCustomizer將不生效

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

相關(guān)文章

  • SpringBoot如何使用Template請求http接口

    SpringBoot如何使用Template請求http接口

    在Spring?Boot中,如果你想要通過模板(template)的方式連接HTTP服務,并發(fā)送HTTP請求,有幾種不同的方式可以實現(xiàn),但最直接和常用的方式之一是使用RestTemplate,這篇文章主要介紹了SpringBoot使用Template請求http接口,需要的朋友可以參考下
    2024-08-08
  • idea如何將指定目錄打成jar包

    idea如何將指定目錄打成jar包

    這篇文章主要介紹了idea如何將指定目錄打成jar包問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Struts1教程之ActionMapping_動力節(jié)點Java學院整理

    Struts1教程之ActionMapping_動力節(jié)點Java學院整理

    這篇文章主要介紹了Struts1教程之ActionMapping,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • Spring Cloud OAuth2中/oauth/token的返回內(nèi)容格式

    Spring Cloud OAuth2中/oauth/token的返回內(nèi)容格式

    Spring Cloud OAuth2 生成access token的請求/oauth/token的返回內(nèi)容就需要自定義,本文就詳細介紹一下,感興趣的可以了解一下
    2021-07-07
  • 全面了解Java中對于異常的捕捉方法

    全面了解Java中對于異常的捕捉方法

    這篇文章主要全面介紹了Java中對于異常的捕捉方法,是Java入門學習中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-11-11
  • 你知道將Bean交給Spring容器管理有幾種方式(推薦)

    你知道將Bean交給Spring容器管理有幾種方式(推薦)

    Spring核心是?IOC?和?AOP?,我們在Spring項目中,我們需要將Bean交給Spring容器,也就是IOC管理,這樣你才可以使用注解來進行依賴注入,這篇文章主要介紹了你知道將Bean交給Spring容器管理有幾種方式,需要的朋友可以參考下
    2022-10-10
  • Java源碼解析HashMap簡介

    Java源碼解析HashMap簡介

    今天小編就為大家分享一篇關(guān)于Java源碼解析HashMap簡介,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • IDEA中設(shè)置Run Dashboard方式

    IDEA中設(shè)置Run Dashboard方式

    這篇文章主要介紹了IDEA中設(shè)置Run Dashboard方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • java實現(xiàn)學生成績錄入系統(tǒng)

    java實現(xiàn)學生成績錄入系統(tǒng)

    這篇文章主要為大家詳細介紹了java實現(xiàn)學生成績錄入系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • java數(shù)據(jù)結(jié)構(gòu)算法稀疏數(shù)組示例詳解

    java數(shù)據(jù)結(jié)構(gòu)算法稀疏數(shù)組示例詳解

    這篇文章主要為大家介紹了java數(shù)據(jù)結(jié)構(gòu)算法稀疏數(shù)組示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06

最新評論