Spring项目中使用Cache Redis实现数据缓存

目录
  • Spring项目中实现数据缓存
    • 一、Spring Cache + Redis 介绍
    • 二、项目中集成
      • 1. 引入依赖
      • 2. 添加 redis 配置类
      • 3. 配置文件增加 redis 配置
      • 4. 启动安装好的 redis
    • 三、Spring Cache 常用注解介绍
      • 1. @Cacheable
      • 2. @CachePut
      • 3. @CacheEvict
    • 四、功能里实现缓存操作
      • 查询操作
      • 导入操作

Spring项目中实现数据缓存

有时候我们为了提高查询速度,会使用缓存,但是并不是所有数据都适合放到缓存中来。

像一些不经常修改的数据、固定的数据、经常查询的数据等,是适合放到缓存的。

那么现在就把之前实现的字典功能里的数据,放到缓存里去。

一、Spring Cache + Redis 介绍

Spring Cache是一个非常优秀的缓存组件。

自 Spring 3.1起,提供了类似于@Transactional注解事务的注解Cache支持,且提供了Cache抽象,方便切换各种底层Cache(如:redis)。

使用Spring Cache的优点:

  • 提供基本的Cache抽象,方便切换各种底层Cache
  • 通过注解Cache可以实现类似于事务一样,缓存逻辑透明的应用到我们的业务代码上,且只需要更少的代码就可以完成
  • 提供事务回滚时也自动回滚缓存
  • 支持比较复杂的缓存逻辑

二、项目中集成

1. 引入依赖

<dependencies>
        <!-- redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- spring2.X集成redis所需common-pool2-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.6.0</version>
        </dependency>
    </dependencies>

2. 添加 redis 配置类

配置类是一个比较固定的写法,需要了解下结构。

// 配置类
@Configuration
// 开启缓存处理
@EnableCaching
public class RedisConfig {
    /**
     * 自定义key规则
     *
     * @return
     */
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }
    /**
     * 设置RedisTemplate规则
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        //序列号key value
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
    /**
     * 设置CacheManager缓存规则
     * @param factory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}

主要是 3 个方法:

  • 自定义key规则:可以更具我们自定义规则生成 key。
  • 设置RedisTemplate规则:后续操作redis,往里存取内容,需要用到 RedisTemplate,这里进行相关设置。
  • 设置CacheManager缓存规则:处理缓存相关的一些规则,比如缓存时间、乱码处理等。

3. 配置文件增加 redis 配置

spring.redis.host=XXX.XXX.XXX.XX
spring.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0

4. 启动安装好的 redis

安装相关可以参考我之前的分享:

https://www.jb51.net/do/plus/view.php?aid=830685

我换了台云服务器,也重新安装了下,测试正常。

这是单机操作,如果需要其他主机也可以链接到redis,还要改个配置:

三、Spring Cache 常用注解介绍

Spring Cache 提供了相关注解,可以让我们很方便实现缓存操作,先看下最常用的几个。

1. @Cacheable

用的最多的注解,功能也很强大,一般用在查询方法上。

可以根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。

说白了,比如我第一次查询缓存操作,如果不存在就去查询数据库,查到数据后返回,并且放到缓存里去,当第二次查询的时候就可以查询缓存里的数据。

查看源码,属性值如下:

value:缓存名,必填,它指定了你的缓存存放在哪块命名空间

cacheNames:与 value 差不多,二选一即可

key:可选属性,可以使用 SpEL 标签自定义缓存的key

2. @CachePut

一般用在新增方法上。

使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。

查看源码,属性值如下:

value:缓存名,必填,它指定了你的缓存存放在哪块命名空间

cacheNames:与 value 差不多,二选一即可

key:可选属性,可以使用 SpEL 标签自定义缓存的key

3. @CacheEvict

一般用在更新或者删除方法上,使用该注解标志的方法,会清空指定的缓存。

查看源码,属性值如下:

value:缓存名,必填,它指定了你的缓存存放在哪块命名空间

cacheNames:与 value 差不多,二选一即可

key:可选属性,可以使用 SpEL 标签自定义缓存的key

allEntries:是否清空所有缓存,默认为 false。如果指定为 true,则方法调用后将立即清空所有的缓存

beforeInvocation:是否在方法执行前就清空,默认为 false。如果指定为 true,则在方法执行前就会清空缓存

四、功能里实现缓存操作

改造之前的字典功能,加入缓存相关操作,在查询和导入(新增)的操作上增加对应注解。

查询操作

在 service 层对应的实现方法上增加注解

@Cacheable(value = "dict", keyGenerator = "keyGenerator")

value = "dict", keyGenerator = "keyGenerator",这里面传入的值就是为了构造key,keyGenerator就是redis配置类里定义的:

接下来到前端刷新一下列表页面,进行一次查询请求,然后查看下redis:

这个 key 就是按照配置类里自定义的规则构建出来的,再来查询一下这个 key:

缓存里有数据了。

导入操作

在 service 层对应的实现方法上增加注解@CacheEvict(value = "dict", allEntries=true)

测试一下,我先del删除掉缓存,然后前端页面做一个导入的操作:

导入成功后,再次查看缓存:

新增成功。

以上就是Spring项目中使用Cache Redis实现数据缓存的详细内容,更多关于Spring Cache Redis数据缓存的资料请关注我们其它相关文章!

时间: 2022-05-31

SpringBoot+SpringCache实现两级缓存(Redis+Caffeine)

1. 缓存.两级缓存 1.1 内容说明 Spring cache:主要包含spring cache定义的接口方法说明和注解中的属性说明 springboot+spring cache:rediscache实现中的缺陷 caffeine简介 spring boot+spring cache实现两级缓存 使用缓存时的流程图 1.2 Sping Cache spring cache是spring-context包中提供的基于注解方式使用的缓存组件,定义了一些标准接口,通过实现这些接口,就可以通过在方法

详解Spring&nbsp;Cache使用Redisson分布式锁解决缓存击穿问题

目录 1 什么是缓存击穿 2 为什么要使用分布式锁 3 什么是Redisson 4 Spring Boot集成Redisson 4.1 添加maven依赖 4.2 配置yml 4.3 配置RedissonConfig 5 使用Redisson的分布式锁解决缓存击穿 1 什么是缓存击穿 一份热点数据,它的访问量非常大.在其缓存失效的瞬间,大量请求直达存储层,导致服务崩溃. 2 为什么要使用分布式锁 在项目中,当共享资源出现竞争情况的时候,为了防止出现并发问题,我们一般会采用锁机制来控制.在单机环境

详解SpringBoot2.0的@Cacheable(Redis)缓存失效时间解决方案

问题   @Cacheable注解不支持配置过期时间,所有需要通过配置CacheManneg来配置默认的过期时间和针对每个类或者是方法进行缓存失效时间配置. 解决   可以采用如下的配置信息来解决的设置失效时间问题 配置信息 @Bean public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { return new RedisCacheManager( RedisCacheWriter.no

Java SpringCache+Redis缓存数据详解

目录 前言 一.什么是SpringCache 二.项目集成Spring Cache + Redis 1.配置方式 三.使用Spring Cache 四.SpringCache原理与不足 1.读模式 2.写模式:(缓存与数据库一致) 五.总结 前言 这几天学习谷粒商城又再次的回顾了一次SpringCache,之前在学习谷粒学院的时候其实已经学习了一次了!!! 这里就对自己学过来的内容进行一次的总结和归纳!!! 一.什么是SpringCache Spring Cache 是一个非常优秀的缓存组件.自

spring的Cache注解和redis的区别说明

目录 spring Cache注解和redis区别 1.不支持TTL 2.内部调用 3.key的问题 Spring Cache注解+redis整合及遇到的坑 先介绍Spring Cache注解 配置Spring注解与Redis整合 我们在Spring-config.xml中来配置 来写RedisCache这个类,让其实现Cache接口 开始使用注解,我是把其作用在倒dao层中 运行结果 key的生成策略 spring Cache注解和redis区别 1.不支持TTL 即不能设置过期时间 expi

分布式医疗挂号系统SpringCache与Redis为数据字典添加缓存

目录 一.SpringCache介绍 二.项目集成Spring Cache 1.添加缓存相关依赖 2.添加redis配置类 3.添加redos配置 三.数据字典配置Spring Cache 1.缓存@Cacheable 2.缓存@CachePut 四.测试缓存是否添加成功 一.SpringCache介绍 Spring Cache 是一个优秀的缓存组件.自Spring 3.1起,提供了类似于@Transactional注解事务的注解Cache支持,且提供了Cache抽象,方便切换各种底层Cache

SpringBoot+Redis实现数据字典的方法

前言 我们在日常的开发过程中针对一些字段采用整型的方式去代替某些具体的含义,比如性别0代表男,1代表女.如果只是一些不会变更的转译我们可以采用常量或者枚举类的方式来实现,但是事实上我们也会遇到那种可能需要变更的,显然这种场景下使用枚举类这种方式是不合理的,那么如何动态地去进行转译呢? 正文 数据字典 数据字典(Data dictionary)是一种用户可以访问的记录数据库和应用程序元数据的目录.主动数据字典是指在对数据库或应用程序结构进行修改时,其内容可以由DBMS自动更新的数据字典.被动数据字

在linux系统下安装redis的方法

去官网找到合适的版本,可以直接下载下来,再用fxp上传,也可以直接以下面这种方式下载: $ wget http://download.redis.io/releases/redis-3.2.9.tar.gz $ tar xzf redis-3.2.9.tar.gz $ cd redis-3.2.9 $ make 启动服务: $ src/redis-server 测试是否成功: $ src/redis-cli redis> set foo bar OK redis> get foo "

浅谈SpringCache与redis集成实现缓存解决方案

缓存可以说是加速服务响应速度的一种非常有效并且简单的方式.在缓存领域,有很多知名的框架,如EhCache .Guava.HazelCast等.Redis作为key-value型数据库,由于他的这一特性,Redis也成为一种流行的数据缓存工具. 在传统方式下对于缓存的处理代码是非常臃肿的. 例如:我们要把一个查询函数加入缓存功能,大致需要三步. 一.在函数执行前,我们需要先检查缓存中是否存在数据,如果存在则返回缓存数据 二.如果不存在,就需要在数据库的数据查询出来. 三.最后把数据存放在缓存中,当

Spring Boot项目利用Redis实现集中式缓存实例

在高并发请求的web服务架构中,随着数据量的提升,缓存机制为绝大多数的后台开发所使用.这篇文章主要介绍如何在Spring Boot项目中为Entity添加利用Redis实现的集中式缓存. 1. 利用Spring Initializr来新建一个spring boot项目 2. 在pom.xml中添加redis.mysql和cache等相关依赖.一般情况下,缓存一般是在大规模数据库存储下所需要的 <dependency> <groupId>org.springframework.boo

CentOS Linux系统下安装Redis过程和配置参数说明

安装过程: 复制代码 代码如下: wget http://code.google.com/p/redis/downloads/detail?name=redis-2.0.4.tar.gz tar xvzf redis-2.0.4.tar.gz cd  redis-2.0.4 make mkdir /home/redis cp redis-server  /home/redis cp redis-benchmark  /home/redis cp redis-cli  /home/redis cp

详解JavaEE 使用 Redis 数据库进行内容缓存和高访问负载

NoSQL(Not Only SQL),泛指非关系型数据库,是为了处理高并发读写.海量数据的高效率存储和访问.高扩展性和高可用性而产生的. 分类 相关产品 典型应用 数据模型 优点 缺点 键值对(Key-Value)存储 Redis.Voldemort.Berkeley DB 内容缓存.处理高访问负载 一系列键值对 快速查询 存储的数据缺少结构化 列存储数据库 Cassandra.HBase.Riak 分布式文件系统 以列簇式存储,将同一列数据存在一起 查询速度快,可扩展性强,更容易进行分布式扩

系统中多种隐藏超级用户添加方法第1/2页

一.如何在图形界面建立隐藏的超级用户 图形界面下适用本地或开3389终端服务的肉鸡上.上面我提到的那位作者说的方法很好,但是较为复杂,还要用到psu.exe(让程序以系统用户身份运行的程序),如果在肉鸡上的话还要上传psu.exe.我说的这个方法将不用到psu.exe这个程序.因为Windows2000有两个注册表编辑器:regedit.exe和regedt32.exe.XP中regedit.exe和regedt32.exe实为一个程序,修改键值的权限时在右键中点"权限"来修改.对re

SpringBoot中使用redis做分布式锁的方法

一.模拟问题 最近在公司遇到一个问题,挂号系统是做的集群,比如启动了两个相同的服务,病人挂号的时候可能会出现同号的情况,比如两个病人挂出来的号都是上午2号.这就出现了问题,由于是集群部署的,所以单纯在代码中的方法中加锁是不能解决这种情况的.下面我将模拟这种情况,用redis做分布式锁来解决这个问题. 1.新建挂号明细表 2.在idea上新建项目 下图是创建好的项目结构,上面那个parent项目是其他项目不用管它,和新建的没有关系 3.开始创建controller,service,dao(mapp

Redis数据库中实现分布式锁的方法

分布式锁是一个在很多环境中非常有用的原语,它是不同进程互斥操作共享资源的唯一方法.有很多的开发库和博客描述如何使用Redis实现DLM(Distributed Lock Manager),但是每个开发库使用不同的方式,而且相比更复杂的设计与实现,很多库使用一些简单低可靠的方式来实现. 这篇文章尝试提供更标准的算法来使用Redis实现分布式锁.我们提出一种算法,叫做Relock,它实现了我们认为比vanilla单一实例方式更安全的DLM(分布式锁管理).我们希望社区分析它并提供反馈,以做为更加复杂

Redis实现分布式锁的几种方法总结

Redis实现分布式锁的几种方法总结 分布式锁是控制分布式系统之间同步访问共享资源的一种方式.在分布式系统中,常常需要协调他们的动作.如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁. 我们来假设一个最简单的秒杀场景:数据库里有一张表,column分别是商品ID,和商品ID对应的库存量,秒杀成功就将此商品库存量-1.现在假设有1000个线程来秒杀两件商品,500个线程秒杀第一个商品,