热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

springboot整合redis做缓存操作

SpringCache简介Spring可以根据@Cacheable、@CachePut、@CacheEvict、@EnableCaching等注解就可以实现对数据的缓存功能。添加依

Spring Cache简介

Spring可以根据@Cacheable 、@CachePut 、@CacheEvict 、@EnableCaching等注解就可以实现对数据的缓存功能。

添加依赖

由于SpringBoot 2.x中默认并没有使用Redis连接池,所以需要在pom.xml中添加commons-pool2的依赖;


    org.apache.commons
    commons-pool2



    org.springframework.boot
    spring-boot-starter-data-redis

在application.yml配置文件中,添加redis的配置

spring:
  redis:
    # Redis服务器地址
    host: 192.168.1.111
    # Redis数据库索引(默认为0)
    database: 0
    # Redis服务器连接端口
    port: 6379
    # Redis服务器连接密码(默认为空)
    password:
    # 连接超时时间
    timeout: 1000ms
    lettuce:
      pool:
        # 连接池最大连接数
        max-active: 8
        # 连接池最大空闲连接数
        max-idle: 8
        # 连接池最小空闲连接数
        min-idle: 0
        # 连接池最大阻塞等待时间,负值表示没有限制
        max-wait: -1ms

添加redisConfig配置类,配置redisTemplate模板

// 开启redis缓存功能
@EnableCaching
// 备注这是一个配置类
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    /**
     * 配置redis模板文件
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisSerializer serializer = redisSerializer();
        // 创建RedisTemplate对象
        RedisTemplate redisTemplate = new RedisTemplate<>();
        // 配置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // redis key 序列化方式使用stringSerial
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // redis value 序列化方式使用jackson
        redisTemplate.setValueSerializer(serializer);
        // redis hash key 序列化方式使用stringSerial
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        // redis hash value 序列化方式使用jackson
        redisTemplate.setHashValueSerializer(serializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    /**
     * 配置序列化
     * @return
     */
    @Bean
    public RedisSerializer redisSerializer() {
        // 定义Jackson2JsonRedisSerializer序列化对象
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会报异常
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(objectMapper);
        return serializer;
    }

    /**
     * 自定义缓存管理器
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        RedisCacheConfiguration redisCacheCOnfiguration= RedisCacheConfiguration
                .defaultCacheConfig()
                // 设置value 为自动转json的Object
             .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer()))
                // 缓存有效期为一天
                .entryTtl(Duration.ofDays(1));
        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }

}

常用注解

@EnableCaching

开启缓存功能,一般放在启动类上,也可放在redisConfig配置文件上。

@Cacheable

使用该注解的方法当缓存存在时,会从缓存中获取数据而不执行方法,当缓存不存在时,会执行方法并把返回结果存入缓存中。

一般使用在查询方法上,可以设置如下属性:

value:缓存名称(必填),指定缓存的命名空间;
key:用于设置在命名空间中的缓存key值,可以使用SpEL表达式定义,如果不指定,则缺省按照方法的所有参数进行组合;
unless:条件符合则不缓存;
condition:条件符合则缓存。

执行这个方法的时候,会先去redis中,根据ceshi::user:id(这个id就是前段传来的id)作为key去查找,如果找到直接返回redis中的数据

如果没有找到就执行该方法,由于unless属性,当返回结果为空就不存入redis中,这里的result是固定写法,指的就是当前返回值User

当不指定key的时候,就会以方法名作为key,这里就是以id作为key。

@Cacheable(value = "ceshi", key = "'user:'+#id", unless = "#result==null")
@GetMapping("{id}")
public User getUserById(@PathVariable("id") Long id) {
    User user = new User();
    user.setAge(1);
    user.setUserId(10L);
    user.setUsername("张三");
    user.setPassword("123");
    user.setToken("2223334455:333:332");
    return user;
}

springboot整合redis做缓存操作

ceshi::user:id在工具中会以:分隔,所以就会出现图片中的ceshi下一级为空的样子。

@CachePut

使用该注解的方法每次执行时都会把返回结果存入缓存中

一般使用在新增方法上,但是本人觉得新增可以不增加缓存,当查询到这个数据的时候没有再添加缓存即可,可以设置如下属性:

value:缓存名称(必填),指定缓存的命名空间;
key:用于设置在命名空间中的缓存key值,可以使用SpEL表达式定义,如果不指定,则缺省按照方法的所有参数进行组合;
unless:条件符合则不缓存;
condition:条件符合则缓存。

// 更新ceshi 缓存
@CachePut (value= "ceshi" ,key= "#account.getName()" ) 
public Account updateAccount(Account account) {
   return updateDB(account);
}

@CacheEvict

使用该注解的方法执行时能够根据一定的条件对缓存进行清空。

一般使用在更新或删除方法上,可以设置如下属性:

value:缓存名称(必填),指定缓存的命名空间;
key:用于设置在命名空间中的缓存key值,可以使用SpEL表达式定义;
condition:条件符合则缓存。

allEntries:是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存

beforeInvocation:是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存

// 清空key为ceshi::user:id 的缓存
@CacheEvict(cacheNames = "ceshi", key = "'user:'+#id")
@DeleteMapping("{id}")
public int deleteObject(@PathVariable("id") Long id) {
    return 0;
}

// 清空ceshi 所有缓存
@CacheEvict (value= "ceshi" ,allEntries= true ) 
public void reload() {
    reloadAll()
}
 
// 清空ceshi下 userName.length() <=4的缓存
@Cacheable (value= "ceshi" ,cOndition= "#userName.length() <=4" ) 
public Account getAccountByName(String userName) {
  // 方法内部实现不考虑缓存逻辑,直接实现业务
  return getFromDB(userName);
}

但是以上的做缓存都是粒度比较大的,如果想单独做一些缓存,设置特定的时间什么的,就需要用到以下的工具类

redis工具类

/**
 * spring redis 工具类
 **/
@Component
public class RedisCache {
    
    @Autowired
    public RedisTemplate redisTemplate;

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key   缓存的键值
     * @param value 缓存的值
     */
    public  void setCacheObject(final String key, final T value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key      缓存的键值
     * @param value    缓存的值
     * @param timeout  时间
     * @param timeUnit 时间颗粒度
     */
    public  void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }

    /**
     * 设置有效时间
     *
     * @param key     Redis键
     * @param timeout 超时时间
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout) {
        return expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 设置有效时间
     *
     * @param key     Redis键
     * @param timeout 超时时间
     * @param unit    时间单位
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout, final TimeUnit unit) {
        return redisTemplate.expire(key, timeout, unit);
    }

    /**
     * 获得缓存的基本对象。
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public  T getCacheObject(final String key) {
        ValueOperations operation = redisTemplate.opsForValue();
        return operation.get(key);
    }

    /**
     * 删除单个对象
     *
     * @param key
     */
    public boolean deleteObject(final String key) {
        return redisTemplate.delete(key);
    }

    /**
     * 删除集合对象
     *
     * @param collection 多个对象
     * @return
     */
    public long deleteObject(final Collection collection) {
        return redisTemplate.delete(collection);
    }

    /**
     * 缓存List数据
     *
     * @param key    缓存的键值
     * @param values 待缓存的List数据
     * @return 缓存的对象
     */
    public  long setCacheList(final String key, final List dataList) {
        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
        return count == null ? 0 : count;
    }

    /**
     * 获得缓存的list对象
     *
     * @param key 缓存的键值
     * @return 缓存键值对应的数据
     */
    public  List getCacheList(final String key) {
        return redisTemplate.opsForList().range(key, 0, -1);
    }

    /**
     * 缓存Set
     *
     * @param key     缓存键值
     * @param dataSet 缓存的数据
     * @return 缓存数据的对象
     */
    public  long setCacheSet(final String key, final Set dataSet) {
        Long count = redisTemplate.opsForSet().add(key, dataSet);
        return count == null ? 0 : count;
    }

    /**
     * 获得缓存的set
     *
     * @param key
     * @return
     */
    public  Set getCacheSet(final String key) {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 缓存Map
     *
     * @param key
     * @param dataMap
     */
    public  void setCacheMap(final String key, final Map dataMap) {
        if (dataMap != null) {
            redisTemplate.opsForHash().putAll(key, dataMap);
        }
    }

    /**
     * 获得缓存的Map
     *
     * @param key
     * @return
     */
    public  Map getCacheMap(final String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 往Hash中存入数据
     *
     * @param key   Redis键
     * @param hKey  Hash键
     * @param value 值
     */
    public  void setCacheMapValue(final String key, final String hKey, final T value) {
        redisTemplate.opsForHash().put(key, hKey, value);
    }

    /**
     * 获取Hash中的数据
     *
     * @param key  Redis键
     * @param hKey Hash键
     * @return Hash中的对象
     */
    public  T getCacheMapValue(final String key, final String hKey) {
        HashOperations opsForHash = redisTemplate.opsForHash();
        return opsForHash.get(key, hKey);
    }

    /**
     * 获取多个Hash中的数据
     *
     * @param key   Redis键
     * @param hKeys Hash键集合
     * @return Hash对象集合
     */
    public  List getMultiCacheMapValue(final String key, final Collection hKeys) {
        return redisTemplate.opsForHash().multiGet(key, hKeys);
    }

    /**
     * 获得缓存的基本对象列表
     *
     * @param pattern 字符串前缀
     * @return 对象列表
     */
    public Collection keys(final String pattern) {
        return redisTemplate.keys(pattern);
    }
    
}

参考:http://www.macrozheng.com/#/reference/spring_data_redis

http://www.ruoyi.vip/


推荐阅读
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • CentOS 6.5安装VMware Tools及共享文件夹显示问题解决方法
    本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ... [详细]
author-avatar
Twosssss
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有