springBoot集成caffeine,自定义缓存配置 CacheManager

news2024/12/23 13:20:01

目录

springboot集成caffeine

Maven依赖

配置信息:properties文件

config配置

使用案例

Caffeine定制化配置多个cachemanager

springboot集成redis并且定制化配置cachemanager


springboot集成caffeine

Caffeine是一种基于服务器内存的缓存库。它将数据存储在应用程序的内存中,以实现快速的数据访问和高性能。

由于Caffeine缓存在服务器内存中存储数据,因此它适用于需要快速读取和频繁访问的数据,比如一些热门数据、配置信息、常用查询的结果等。但是它不适用于大规模数据或需要持久化存储的数据,因为服务器内存有限,无法存储大量数据,并且缓存数据在应用程序重启后会丢失

Maven依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.2</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- caffeine服务器本地缓存 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <!-- caffeine -->
    <dependency>
        <groupId>com.github.ben-manes.caffeine</groupId>
        <artifactId>caffeine</artifactId>
        <version>2.8.1</version>
    </dependency>
    <!--   可以对自定义配置的信息进行提示 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
    </dependency>
</dependencies>

配置信息:properties文件

/**
 * Caffeine Cache自定义配置属性类
 */
@Data   //lombok插件的  看自己需求是否引入
@Component
@ConfigurationProperties(prefix = "com.common.caffeine")  
//这个ConfigurationProperties是为了方便配置yaml文件,
//如果有需要的话可以在yaml文件中进行配置,需要与spring-boot-configuration-processor
//这个依赖搭配使用,
//然后再在resources目录下创建一个META-INF文件夹,该文件夹下存放一个配置文件提升信息(下面会贴出来的),
//这样的话在yaml文件中进行书写的时候就会有提升信息了
public class CaffeineCacheProperties {

    /**
     * 缓存初始容量  映射的话会很灵活  羊肉串写法与驼峰命名都可以和下面的属性进行映射
     * com.ifi.performance.common.caffeine.init-cache-capacity
     */
    private Integer initCacheCapacity = 256;

    /**
     * 缓存最大容量,超过之后会按照recently or very often(最近最少)策略进行缓存剔除
     * com.ifi.performance.common.caffeine.max-cache-capacity
     */
    private Long maxCacheCapacity = 10000L;

    /**
     * 是否允许空值null作为缓存的value
     * com.ifi.performance.common.caffeine.allow-null-value
     */
    private Boolean allowNullValue = Boolean.TRUE;

}

配置yaml文件提升信息:additional-spring-configuration-metadata.json

{
  "properties": [
    {
      "name": "com.ifi.performance.common.caffeine.init-cache-capacity",
      "type": "java.lang.Integer",
      "description": "Caffeine缓存的初始容量",
      "defaultValue": 256
    },
    {
      "name": "com.ifi.performance.common.caffeine.max-cache-capacity",
      "type": "java.lang.Long",
      "description": "Caffeine缓存的最大容量",
      "defaultValue": "10000L"
    },
    {
      "name": "com.ifi.performance.common.caffeine.allow-null-value",
      "type": "java.lang.Boolean",
      "description": "Caffeine缓存是否允许null作为value的属性",
      "defaultValue": "true"
    }
  ]
}

这样在yaml文件中输入com.common.caffeine的时候就会有提示信息了。

config配置

/**
 * 服务端公用缓存常量类
 */
public interface CacheConstants {

    /**
     * 系统服务端公用缓存名称 默认缓存
     */
    String CACHE_NAME = "server_cache";
}       

编写config配置文件:CaffeineCacheConfig.java

@SpringBootConfiguration
@EnableCaching  //开启注解扫描
@Slf4j
public class CaffeineCacheConfig {

    //刚刚编写的properties配置文件
    @Autowired
    private CaffeineCacheProperties properties;


    /**
     * 默认的全局缓存管理器
     * @return
     */
    @Bean("defaultCacheManager")
    public CaffeineCacheManager defaultCacheManager() {
        CaffeineCacheManager defaultCacheManager = new CaffeineCacheManager(CacheConstants.CACHE_NAME); //指定这个缓存的命名,这里我是使用了一个常量类
        defaultCacheManager.setAllowNullValues(properties.getAllowNullValue());
        Caffeine<Object, Object> caffeineBuilder = Caffeine.newBuilder()
                .initialCapacity(properties.getInitCacheCapacity())
                .maximumSize(properties.getMaxCacheCapacity()) //从配置文件中获取最大容量
                .expireAfterWrite(7, TimeUnit.DAYS); //过期时间
        defaultCacheManager.setCaffeine(caffeineBuilder);
        log.info("the caffeine cache manager is loaded successfully!");
        return defaultCacheManager;
    }
}

使用案例

这样配置好了之后就可以在controller、service中使用配置好的缓存了。

比如说我们要在service中进行使用,案例如下:

@Autowired
@Qualifier(value = "defaultCacheManager") //这里可以直接使用Autowired就行,Autowired默认是按照对象类型进行依赖注入,如果容器中有两个及以上的同一种类型的bean,那么就会报bean冲突的错误,后面的定制化配置会用到这个Autowired
private CaffeineCacheManager defaultCacheManager;

Cache cache = defaultCacheManager.getCache(CacheConstants.CACHE_NAME); //配置类中对这个cachemanager设置的缓存名称
//下面就可以通过cache操作数据:存入缓存或者是从缓存中获取数据、删除数据了。
//存入缓存的数据是key-value形式的,key最好是一个唯一的标识,不然可能会出现缓存覆盖的情况,value可以是一个字符串也可以是自定义的对象,这里我是自定义了一个对象,比如UserCache对象,这个对象中有我需要缓存的数据,比如userid等自己需要的数据
UserCache usercache = new UserCache();
usercache.setuserId = "123456"; //实际业务场景中,比如用户登录成功,可以把用户id设置进来,方便其他业务进行获取  LOGIN_INFO 常量为自定义的一个标识符,方便在查询辨别缓存数据
cache.put(userId+CacheConstants.LOGIN_INFO,usercache);

//特别注意:get缓存数据的时候,很大可能获取到的是null对象,因为比如有一些业务没有被触发从而导致没有填充你需要的数据到缓存,所以这里一定要加一个空指针判断!!!
UserCache usercache = cache.get( userId + CacheConstants.LOGIN_INFO, UserCache.class);
if(usercache == null){
    return null;
}

//清除缓存中指定的数据  通过key来清除缓存中的数据,比如用户退出登录了可以把他的一些缓存信息给清除
cache.evict(userId + CacheConstants.LOGIN_INFO);

因为我们使用的缓存管理接口是spring-cache的,spring-cache中的操作api中并没有提供设置数据缓存的过期时间的,所以如果我们有这种业务需要(比如验证码信息需要5分钟才过期,用户登录信息30天才过期),那么就需要定制化配置cachemanager了,这样从源头上解决问题。

Caffeine定制化配置多个cachemanager

依赖与上面一致,只需要修改CaffeineCacheConfig类与使用方式就行。

@SpringBootConfiguration
@EnableCaching  //开启注解扫描
@Slf4j
public class CaffeineCacheConfig {

    @Autowired
    private CaffeineCacheProperties properties;


    /**
     * 默认的全局缓存管理器
     * @return
     */
    @Primary  //必须要加这个注解,用于标识一个Bean(组件)是首选的候选者。当有多个同类型的Bean(组件)时,使用了@Primary注解的Bean将会成为默认选择,如果没有其他限定符(如@Qualifier)指定具体要使用的Bean,则会优先选择带有@Primary注解的Bean。
    @Bean("defaultCacheManager")
    public CaffeineCacheManager defaultCacheManager() {
        CaffeineCacheManager defaultCacheManager = new CaffeineCacheManager(CacheConstants.ACHE_NAME);
        defaultCacheManager.setAllowNullValues(properties.getAllowNullValue());
        Caffeine<Object, Object> caffeineBuilder = Caffeine.newBuilder()
                .initialCapacity(properties.getInitCacheCapacity())
                .maximumSize(properties.getMaxCacheCapacity())
                .expireAfterWrite(7, TimeUnit.DAYS);
        defaultCacheManager.setCaffeine(caffeineBuilder);
        log.info("the caffeine cache manager is loaded successfully!");
        return defaultCacheManager;
    }

    /**
     *  用于管理验证码缓存,设置过期时间为300秒
     */
    @Bean("verificationCodeCacheManager")
    public CaffeineCacheManager verificationCodeCacheManager() {
        CaffeineCacheManager verificationCodeCacheManager = new CaffeineCacheManager(CacheConstants.CODE_CACHE_NAME);
        verificationCodeCacheManager.setCaffeine(Caffeine.newBuilder()
                .initialCapacity(properties.getInitCacheCapacity())
                .maximumSize(properties.getMaxCacheCapacity())
                .expireAfterWrite(300, TimeUnit.SECONDS));
        log.info("the verificationCodeCacheManager cache manager is loaded successfully!");
        return verificationCodeCacheManager;
    }

}

使用方式,和上面的案例一致,不过这个时候就必须使用@Qualifier来指定相关的bean。其他使用方式都是一致的。

@Autowired
@Qualifier(value = "defaultCacheManager") 
private CaffeineCacheManager defaultCacheManager;

@Autowired
@Qualifier(value = "verificationCodeCacheManager")
private CaffeineCacheManager verificationCodeCacheManager;

springboot集成redis并且定制化配置cachemanager

缓存使用到的Maven依赖:

<!-- 集成redis依赖  -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 提供Redis连接池 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

yaml文件:Redis部分的配置

spring:
  redis:
    database: 0
    host: localhost
    port: 6379
    password: abc123456  #这个看你的Redis版本,一些老的Redis用的是auth,一些比较新的用的是password配置
    timeout: 10s
    lettuce:
      pool:
        # 连接池最大连接数
        max-active: 200
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
        # 连接池中的最大空闲连接
        max-idle: 10
        # 连接池中的最小空闲连接
        min-idle: 3

config配置类:

@SpringBootConfiguration
@EnableCaching
@Slf4j
public class RedisCacheConfig {

    /**
     * 定制链接和操作Redis的客户端工具   配置一些序列化器,这样通过缓存管理工具看到的缓存数据就不是乱码了
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        //配置序列化器
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();

        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        redisTemplate.setDefaultSerializer(genericJackson2JsonRedisSerializer);
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;

    }


    /**
     * 默认的全局缓存管理器   配置一些序列化器,这样通过缓存管理工具看到的缓存数据就不是乱码了
     * @return
     */
    @Primary  //关于这个相关的解释,上面的caffeine配置中都有说明,这里就不额外说明了
    @Bean("defaultCacheManager")
    public RedisCacheManager defaultCacheManager(RedisConnectionFactory redisConnectionFactory) {
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        RedisCacheConfiguration config = RedisCacheConfiguration.
                defaultCacheConfig()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(genericJackson2JsonRedisSerializer));

        RedisCacheManager defaultCacheManager = RedisCacheManager.builder(redisConnectionFactory)
                .cacheDefaults(config).build();

        log.info("the redis defaultCacheManager is loaded successfully!");
        return defaultCacheManager;
    }

    /**
     *  用于管理验证码缓存,设置过期时间为300秒
     */
    @Bean("verificationCodeCacheManager")
    public RedisCacheManager verificationCodeCacheManager(RedisConnectionFactory redisConnectionFactory) {
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        RedisCacheConfiguration config = RedisCacheConfiguration.
                defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(5))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(genericJackson2JsonRedisSerializer));

        RedisCacheManager verificationCodeCacheManager = RedisCacheManager.builder(redisConnectionFactory)
                .cacheDefaults(config).build();

        log.info("the verificationCodeCacheManager cache manager is loaded successfully!");
        return verificationCodeCacheManager;
    }


}

使用方式,和上面的一致:

@Autowired
@Qualifier(value = "defaultCacheManager")
private CaffeineCacheManager defaultCacheManager;

Cache cache = defaultCacheManager.getCache(CacheConstants.CACHE_NAME); //配置类中对这个cachemanager设置的缓存名称

UserCache usercache = new UserCache();
usercache.setuserId = "123456"; 
//实际业务场景中,比如用户登录成功,可以把用户id设置进来,方便其他业务进行获取  LOGIN_INFO 常量为自定义的一个标识符,方便在查询辨别缓存数据
cache.put(userId+CacheConstants.LOGIN_INFO,usercache);

//特别注意:get缓存数据的时候,很大可能获取到的是null对象
UserCache usercache = cache.get( userId + CacheConstants.LOGIN_INFO, UserCache.class);
if(usercache == null){
    return null;
}

//清除缓存中指定的数据  通过key来清除缓存中的数据
cache.evict(userId + CacheConstants.LOGIN_INFO);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/849182.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

批量查询快递信息的最佳解决方案

快递查询是我们日常生活中经常需要进行的操作&#xff0c;然而&#xff0c;当我们有多个快递单号需要查询时&#xff0c;逐个查询就显得非常繁琐和耗时。为了解决这个问题&#xff0c;今天给大家推荐一款实用的软件——【固乔快递查询助手】。 首先&#xff0c;在浏览器中搜索并…

Activity启动过程详解(Android 12源码分析)

Activity的启动方式 启动一个Activity&#xff0c;通常有两种情况&#xff0c;一种是在应用内部启动Activity&#xff0c;另一种是Launcher启动 1、应用内启动 通过startActivity来启动Activity 启动流程&#xff1a; 一、Activity启动的发起 二、Activity的管理——ATMS 三、…

Mysql根据创建时间表分区实践

背景 最近订单表遇到大数据量的问题&#xff0c;并且表中随着时间的积累会变得更大&#xff0c;当数据量较大时&#xff0c;存储的物理文件会变得非常大、使用性能很差。 我们用的是GaussDB。为了提高查询效率&#xff0c;建议表大于500w进行分区&#xff0c;所以在规划阶段我…

opencv基础47 查找图像轮廓cv2.findContours()详解

什么是图像轮廓&#xff1f; 图像轮廓是指图像中物体边缘的连续性曲线。在计算机视觉和图像处理中&#xff0c;轮廓通常被用于检测物体、分割图像以及提取物体特征。 图像轮廓是由一系列连续的像素点组成&#xff0c;这些像素点位于物体边界上。轮廓的特点是在物体和背景之间的…

springboot生成表结构和表数据sql

需求 业务背景是需要某单机程序需要把正在进行的任务导出&#xff0c;然后另一台电脑上单机继续运行&#xff0c;我这里选择的方案是同步SQL形式&#xff0c;并保证ID随机&#xff0c;多个数据库不会重复。 实现 package com.nari.web.controller.demo.controller;import cn…

Android 11 获取启动其他应用

Android 11 获取启动其他应用 本文代码地址 https://gitee.com/chenjim/QueryAppInfo 最新更新地址 https://gitee.com/chenjim/chenjimblog 前言 如果应用以 Android 11&#xff08;API 级别 30&#xff09;或更高版本为目标平台&#xff0c;并查询与设备上已安装的其他应用相…

Python 面试必知必会(一):数据结构

《Python Cookbook》的作者David Beazley的课程PPT开源了&#xff0c;目标用户是希望从编写基础脚本过渡到编写更复杂程序的高级 Python 程序员&#xff0c;课程主题侧重于流行库和框架中使用的编程技术&#xff0c;主要目的是更好地理解 Python 语言本身&#xff0c;以便阅读他…

简易图书管理系统(面向对象思想)

目录 前言 1.整体思路 2.Book包 2.1Book类 2.2BookList类 3.user包 3.1User类 3.2NormalUser类 3.3AdminUser类 4.operation 4.1IOPeration接口 4.2ExitOperation类 4.3FindOperation类 4.4ShowOperation类 4.5AddOperation类 4.6DelOperation类 4.7BorrowOpera…

下半年提速拓店,为什么说屈臣氏引领美妆零售的未来?

屈臣氏过去是美妆零售的先锋&#xff0c;目前来看它或许仍然是先锋。 杰弗里摩尔在《公司进化论》中总结提出&#xff0c;自由市场经济运作的方式&#xff0c;遵循着一些类似自然界有机系统的定律&#xff1a;通俗来说&#xff0c;资源竞争带来“刺激创新”——由消费者偏好形…

看重ARM?苹果、三星、英伟达等知名企业纷纷表示加大投资

根据日经亚洲的报道&#xff0c;芯片设计公司Arm计划进行首次公开募股并在纳斯达克上市。苹果、三星电子、英伟达、英特尔等知名企业计划在Arm美股上市后投资该公司。 据悉&#xff0c;Arm将于9月份上市&#xff0c;预计估值将达到至少600亿美元&#xff08;约合4314亿元人民币…

【PyQt5+matplotlib】获取鼠标在canvas上的点击坐标

示例代码&#xff1a; import sys import matplotlib.pyplot as plt from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvasclass MyMainWindow(QMainWindow):de…

vulnhub靶场-y0usef笔记

vulnhub靶场-y0usef笔记 信息收集 首先fscan找到目标机器ip http://192.168.167.70/ nmap扫描端口 Host is up (0.00029s latency). Not shown: 998 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.13 (Ub…

(十五)大数据实战——hive的安装部署

前言 Hive是由Facebook开源&#xff0c;基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张表&#xff0c;并提供类SQL查询功能。本节内容我们主要介绍一下hive的安装与部署的相关内容。 正文 上传hive安装包到hadoop101服务器/opt/software目录 解…

Reinforcement Learning with Code (对比Monte-Carlo与TD算法)【Code 3. MonteCarlo】

Reinforcement Learning with Code & &#xff08;对比Monte-Carlo与TD算法&#xff09;【Code 3. MonteCarlo】 This note records how the author begin to learn RL. Both theoretical understanding and code practice are presented. Many material are referenced s…

成功搞定H7-TOO的FreeRTOS Trace图形化链表方式展示任务管理

之前推出了H7-TOOL的RTOS Trace功能&#xff0c;已经支持RTX5&#xff0c;ThreadX&#xff0c;uCOS-III&#xff0c;uCOS-II和FreeRTOS&#xff0c;特色是不需要目标板额外做任何代码&#xff0c;实时检测RTOS任务执行情况&#xff0c;支持在线和脱机玩法&#xff0c;效果是下面…

网络编程——字节序和地址转换

字节序和地址转换 一、字节序 1、字节序概念 是指多字节数据的存储顺序,数据在内存中存储的方式 2、分类 大端序(网络字节序)&#xff1a;高位的数据存放在低地址位 arm架构、交换机、路由器 小端序(主机字节序)&#xff1a;高位的数据存放在高地址位 x86架构计算机 注意 …

10_Vue3 其它的组合式API(Composition API)

Vue3 中的其它组合式API 1.shallowReactive 与 shallowRef 2. readonly 与 shallowReadonly 3.toRaw 与 markRaw 4.customRef 5.provide 与 inject 6.响应式数据的判断

pytest测试框架之fixture测试夹具详解

fixture的优势 ​ pytest框架的fixture测试夹具就相当于unittest框架的setup、teardown&#xff0c;但相对之下它的功能更加强大和灵活。 命名方式灵活&#xff0c;不限于unittest的setup、teardown可以实现数据共享&#xff0c;多个模块跨文件共享前置后置可以实现多个模块跨…

fastadmin自定义键值组件Fieldlist

需求场景&#xff1a; 后台设置前端的固定话费充值金额。编辑时要求能够增删改&#xff0c;给到前端的数据&#xff0c;是要根据金额正序排列&#xff0c;用fastadmin的键值组件(Fieldlist)&#xff0c;使用Art-Template模板语法自定义模板。 最终效果如下图所示&#xff1a; …

【深度学习注意力机制系列】—— ECANet注意力机制(附pytorch实现)

ECANet&#xff08;Efficient Channel Attention Network&#xff09;是一种用于图像处理任务的神经网络架构&#xff0c;它在保持高效性的同时&#xff0c;有效地捕捉图像中的通道间关系&#xff0c;从而提升了特征表示的能力。ECANet通过引入通道注意力机制&#xff0c;以及在…