Java 本地缓存CaffeineCache简单使用案例

发布时间:2024年01月16日

一、需求

项目中用到了本地缓存CaffeineCache,在这里简单介绍一下使用方法。

二、CaffeineCache缓存的两种方式

缓存配置有两种:SimpleCacheManager和CaffeineCacheManager
它们配置的区别如下:

1、SimpleCacheManager

当应用程序启动时,通过配置多个CaffeineCache来创建多个缓存。可以为每个方法单独配置缓存过期时间。

2、CaffeineCacheManager

使用一个全局的Caffeine配置,来创建所有的缓存。不能为每个方法,单独配置缓存过期时间,但可以在程序启动时,
全局的配置缓存,方便设置所有方法的缓存过期时间。

3、总结

如果想要每个方法单独配置缓存过期时间,使用第一种方式。否则,想全局设置的缓存配置,使用第二种方式。

三、pom依赖

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>2.6.2</version>
        </dependency>

四、配置管理器方式一–采用SimpleCacheManager

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 缓存配置有两种:SimpleCacheManager和CaffeineCacheManager
 * 它们配置的区别如下:
 * <p>
 * SimpleCacheManager:
 * 当应用程序启动时,通过配置多个CaffeineCache来创建多个缓存。可以为每个方法单独配置缓存过期时间。
 * <p>
 * CaffeineCacheManager:
 * 使用一个全局的Caffeine配置,来创建所有的缓存。不能为每个方法,单独配置缓存过期时间,但可以在程序启动时,
 * 全局的配置缓存,方便设置所有方法的缓存过期时间。
 * <p>
 * 总结:
 * 如果想要每个方法单独配置缓存过期时间,建议使用第一种方式。
 * 否则,你想设置全局的缓存配置,建议使用第二种方式。
 */
@EnableCaching
@Configuration
public class SimpleCaffeineConfig {


//    /**
//     * 写法一:初始化SimpleCacheManager管理器
//     * @return
//     */
//    @Bean
//    @Primary
//    public CacheManager simpleCacheManager() {
//        SimpleCacheManager cacheManager = new SimpleCacheManager();
//        ArrayList<CaffeineCache> caches = new ArrayList<>();
//        Map<String, Object> map = putCacheRule();
//        for (String name : map.keySet()) {
//            caches.add(new CaffeineCache(name, (Cache<Object, Object>) map.get(name)));
//        }
//        cacheManager.setCaches(caches);
//        return cacheManager;
//    }
//
//    /**
//     * 配置多个缓存
//     *
//     * @return
//     */
//    private static Map<String, Object> putCacheRule() {
//        Map<String, Object> map = new ConcurrentHashMap<>();
//        map.put("caffeine_test_1", Caffeine.newBuilder().recordStats()
//                .expireAfterWrite(1, TimeUnit.MINUTES)
                .maximumSize(10000)
//                .build());
//        map.put("caffeine_test_2", Caffeine.newBuilder().recordStats()
//                .expireAfterWrite(2, TimeUnit.HOURS)
                .maximumSize(10000)
//                .build());
//        return map;
//    }

    /**
     * 写法二:初始化SimpleCacheManager管理器
     *
     * @return
     */
    @Bean
    public CacheManager caffeineCacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        List<CaffeineCache> caches = new ArrayList<>();
        //缓存一:失效时间是1分钟
        caches.add(new CaffeineCache("simple_caffeine_test_1",
                Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build()));
        //缓存二:失效时间是1小时
        caches.add(new CaffeineCache("simple_caffeine_test_2",
                Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build()));
        cacheManager.setCaches(caches);
        return cacheManager;
    }
}

五、配置管理器方式一–采用CaffeineCacheManager

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 缓存配置有两种:SimpleCacheManager和CaffeineCacheManager
 * 它们配置的区别如下:
 * <p>
 * SimpleCacheManager:
 * 当应用程序启动时,通过配置多个CaffeineCache来创建多个缓存。可以为每个方法单独配置缓存过期时间。
 * <p>
 * CaffeineCacheManager:
 * 使用一个全局的Caffeine配置,来创建所有的缓存。不能为每个方法,单独配置缓存过期时间,但可以在程序启动时,
 * 全局的配置缓存,方便设置所有方法的缓存过期时间。
 * <p>
 * 总结:
 * 如果想要每个方法单独配置缓存过期时间,建议使用第一种方式。
 * 否则,你想设置全局的缓存配置,建议使用第二种方式。
 */
@EnableCaching
@Configuration
public class CaffeineCacheConfig {

    @Bean
    public CacheManager caffeineCacheManager() {
        CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
        Caffeine<Object, Object> caffeine = Caffeine.newBuilder()
                // 初始大小
                .initialCapacity(10)
                // 最大容量
                .maximumSize(100)
                // 打开统计
                .recordStats()
                // 5分钟不访问自动丢弃
                .expireAfterAccess(5, TimeUnit.MINUTES);
        caffeineCacheManager.setCaffeine(caffeine);
        // 设定缓存器名称
        caffeineCacheManager.setCacheNames(getKeys());
        // 值不可为空
        caffeineCacheManager.setAllowNullValues(false);
        return caffeineCacheManager;
    }

    /**
     * 配置缓存key
     *
     * @return
     */
    public static List<String> getKeys() {
        List<String> names = new ArrayList<>(1);
        names.add("cache_caffeine_test_1");
        return names;
    }
}

六、定义service

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.UUID;

/**
 * @Author:
 * @Description
 * @Date: 上午9:32 2024/1/16
 */
@Service
public class CaffeineService {

    /**
     * 方式一:SimpleCacheManager
     * <p>
     * 注解的参数包括:
     * <p>
     * cacheNames:指定缓存的名称。
     * key:指定缓存的 key。这里的 key 是一个 SpEL 表达式,表示使用方法的参数,作为 key。
     * unless:指定当方法的返回值为 null 时,不将结果缓存。
     * unless这个注解的作用是,当调用这个方法时,会先在本地缓存中查找是否已经缓存了结果,如果有,则直接返回缓存中的结果;
     * 如果没有,则执行方法体,并将方法的返回值缓存到本地缓存中,供下次使用。如果方法的返回值为 null,则不会将结果缓存。
     * <p>
     *
     * @param name
     * @param address
     * @return
     */
//    @Cacheable(value = "simple_caffeine_test_1", key = "#root.methodName+'_'+#root.args[0]+'_'+#root.args[1]", unless = "#result == null")
    @Cacheable(value = "simple_caffeine_test_1", key = "#root.args[0]+'_'+#root.args[1]", unless = "#result == null")
    public String testSimpleCaffeine(String name, String address) {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return name + address;
    }

    /**
     * 更新缓存
     */
    @CachePut(value = "simple_caffeine_test_1", key = "#root.args[0]+'_'+#root.args[1]", unless = "#result == null")
    public String update(String name, String address) {
        return name + address+ UUID.randomUUID().toString();
    }

    /**
     * 删除缓存
     */
    @CacheEvict(value = "simple_caffeine_test_1", key = "#root.args[0]+'_'+#root.args[1]")
    public String del(String name, String address) {
        return "";
    }

    /**
     * 方式二:CaffeineCacheManager
     *
     * @param name
     * @param address
     * @return
     */
    @Cacheable(value = "cache_caffeine_test_1", key = "#root.methodName+'_'+#root.args[0]+'_'+#root.args[1]", unless = "#result == null")
    public String testCacheCaffeine(String name, String address) {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return name + address;
    }
}

七、定义controller

import com.example.service.CaffeineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author:
 * @Description
 * @Date: 上午9:32 2024/1/16
 */
@RestController
@RequestMapping("/caffeine")
public class CaffeineController {

    @Autowired
    private CaffeineService caffeineService;

    @GetMapping("/simple")
    public String testSimpleCaffeine(String name, String address){

        return caffeineService.testSimpleCaffeine(name,address);
    }

    @GetMapping("/update")
    public String testUpdate(String name, String address){

        return caffeineService.update(name,address);
    }

    @GetMapping("/del")
    public String testDel(String name, String address){
        return caffeineService.del(name,address);
    }

    @GetMapping("/cache")
    public String testCacheCaffeine(String name, String address){

        return caffeineService.testCacheCaffeine(name,address);
    }
}

八、测试

注意:SimpleCaffeineConfig和CaffeineCacheConfig必须注释掉其中一个类,来分别测试

1、启动项目,这里以SimpleCaffeine方式进行测试
2、模拟加入缓存,地址栏输入:localhost:8077/caffeine/simple?name=111&address=222 等待三秒数据返回
3、继续操作第2步,这时候看到数据返回需要6毫秒,缓存生效
4、模拟数据更新,地址栏输入:localhost:8077/caffeine/update?name=111&address=222
5、模拟读取缓存更新后的数据,地址栏输入:localhost:8077/caffeine/simple?name=111&address=222 看到数据已更新,且数据返回需要5毫秒,缓存更新生效
6、模拟清空缓存,地址栏输入:localhost:8077/caffeine/del?name=111&address=222 ,然后地址栏输入:localhost:8077/caffeine/simple?name=111&address=222 返回数据需要3.15秒,缓存清空生效

九、完整代码

文章来源:https://blog.csdn.net/weixin_43969830/article/details/135632272
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。