首先需要知道redis支持的五大数据类型:
String(字符串),Hash(哈希),List(列表),Set(集合),Zset(有序集合)
开始操作:
创建项目:
添加以下四个部分:
在pom文件中导入以下依赖:
com.baomidou mybatis-plus-boot-starter 3.5.1
更改mysql的版本号
在YAML文件中配置如下内容:端口号,连接数据库,配置redis连接,添加日志
配置完redis之后打开redis文件夹,shift+右击,打开终端窗口,输入命令开启redis服务
开启服务之后最小化即可。使用redis需要redistemplate对象。所以需要创建一张配置文件,具体代码如下所示。
redistemplate对象每次都从连接池中获取一个连接,并执行回调,执行完毕后将连接放回连接池。
配置完成之后进行测试。
编写控制器,编写添加方法和展示方法。
opsforvalue()方法的使用:
opsforvalue().set(key,value):添加一个字符串类型的值。
opsforvalue().get(key):获取key键对应的值。
打开redis桌面管理器(redis可视化工具),可以看到在key:username前多了一串莫名的字符。
这是因为在redisTemplate对象中,默认采取JdkSerializationRedisSerializer类进行对key和value的序列化,会产生一些额外的字符。不想看见就必须修改序列化方式。
解决方法:在redis配置中设置所设的key和value序列化,所用的对象时RedisSerializer,打开他的源码可发现,他可以将值序列化成java,json,string,toarray等类型。
保险起见,最好在方法头部打上@Primary注解,防止在spring容器中存在多个该对象的实例。
@Primary:赋予bean更高的优先级。
配置完成后移除可视化工具中的值,并打开postman重新测试,测试成功后再打开可视化工具即可看到刚刚所传的值。
在用户使用应用程序获取数据时,如果redis中有数据,则从redis中获取,如果没有则从数据库中获取并将数据存到redis中。
那通过代码需要怎么实现呢?
以userinfo表为实例类查询表中的数据。
注意:此处查询表的数据返回的是一个list集合,list集合中的每一条数据代表一个对象,即RedisTemplate
注释掉刚刚所配置的value为String类型的序列化。
其余的mapper,service,service实现类均与之前相同,这边不再一一赘述。
编写控制器。按照上面的逻辑,先从redis中获取数据,如果redis中没有数据则从数据库中获取并存到redis中。
进行测试。
第一次测试的时候打开控制台可以看到,数据是从数据库中获取的。
此时打开redis可视化工具,数据已经保存到了redis中。
这是清空控制台,再进行一次查询。可以看到,数据仍能显示,但是控制台中没有任何信息。
所以此次查询是从redis中直接获取的。
但是这种缓存过于繁琐,在此之前我们已经学过了注解和框架,所以可以使用更简单的写法。
具体如下:
在启动类头部添加@EnableCaching注解
@EnableCaching:开启全局缓存。
在控制器头部添加@CacheConfig注解
@CacheConfig:会在redis中形成一个Hash结构,hash结构中存在2个key,这个注解用来设置第一个key的值。
查询
在控制器中新增一个查询方法,并在方法头部添加@Cacheable注解。
@Cacheable:应用在查询方法上的注解,可以将方法的返回值直接存入redis中。
此时进行测试,第一次是从数据库中获取,获取完毕之后由于@Cacheable注解会将返回的值直接存入redis中,所以后面进行测试可以直接从redis中获取。
添加
@CachePut()注解
在控制器中写添加方法。
其中@CachePut():同步更新缓存。(即将返回的结果存入redis中)。
在进行完测试后,所返回的结果会直接保存到redis缓存中。
删除
在控制器中添加删除方法
@CacheEvict()注解:相当于一个触发器,在每次调用被它注解的方法时,就会触发删除它指定的缓存的动作,所返回的结果不会存到redis缓存中。
#p:为参数列表
以查询单个对象为例。
在控制器中添加查询单个对象的方法。
在@Cacheable注解里设置key值为#p0 ,其中#p为参数列表,0表示列表中的第一个参数。
这时打开工具进行查询,从数据库中获取数据之后将值保存到redis中,如下图所示:3就表示我所查询对象的id
#result:查询结果
以查询单个对象为例。
如果仅按以上写法,所查询的值无论是否为空都会存入redis缓存中。
即使后续我通过数据库将id为19的值存到数据库中,我再次查询也仍为空。
这是因为我所查询的顺序时先从redis缓存中获取数据,如果数据不存在则从数据库中查询,通过上面的操作可以看出,我将空值存到了redis缓存中,所以即使当我在数据库中存值之后再查询也仍为空,因为他是从redis中获取数据的。
这就造成了缓存中的数据与数据库中的数据存在偏差。
为了比曼这种错误。
需要用到#result。
如下所示:
unless = “#result == null”,即排除结果为null的情况。
通过以上作法,即使我查询的值为空也不会存到redis缓存中。