【Spring学习】Spring Data Redis:RedisTemplate、Repository、Cache注解

1,spring-data-redis官网

1)特点

  1. 提供了对不同Redis客户端的整合(Lettuce和Jedis)
  2. 提供了RedisTemplate统一API来操作Redis
  3. 支持Redis的发布订阅模型
  4. 支持Redis哨兵和Redis集群
  5. 支持基于Lettuce的响应式编程
  6. 支持基于JDK、JSON、字符串、Spring独享的数据序列化及反序列化
  7. 支持基于Redis的JDKCollection实现

2,RedisTemplate

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。

1)常用API

api说明
redisTemplate.opsForValue();操作字符串
redisTemplate.opsForHash();操作hash
redisTemplate.opsForList();操作list
redisTemplate.opsForSet();操作set
redisTemplate.opsForZSet();操作有序set
redisTemplate.expire(key, 60 * 10000 * 30, TimeUnit.MILLISECONDS);设置过期时间

1>API:String

redisTemplate.opsForValue().set("name","tom")
说明api备注
添加单值.set(key,value)
获取单值.get(key)
添加单值并返回这个值是否已经存在.setIfAbsent(key, value)
添加单值并返回旧值.getAndSet(key, value)
批量添加Map<String,String> maps;
.multiSet(maps)
批量获取List<String> keys;
.multiGet(keys)
数值型+1.increment(key,1)
设置过期时间set(key, value, timeout, TimeUnit.SECONDS)过期返回null
字符串追加.append(key,"Hello");

2>API:List数据

template.opsForList().range("list",0,-1)
说明api备注
单个插入Long leftPush(key, value);返回操作后的列表的长度
批量插入Long leftPushAll(K key, V… values);返回操作后的列表的长度;
values可以是String[]List<Object>
查看.range(key,0,-1)从左往右:0,1,2;
从右往左:-1,-2,-3;
可做分页
弹出最左边的元素.leftPop("list")弹出之后该值在列表中将不复存在
修改set(key, index, value)
key存在则插入Long rightPushIfPresent(K key, V value);返回操作后的列表的长度
求subList.trim(key,1,-1)
移除元素Long remove(key, long count, Object value);count> 0:删除从左到右共count个等于value的元素。
count <0:删除等于从右到左共count个等于value的元素。
count = 0:删除等于value的所有元素。
求长度.size(key)

3>API:Hash操作

一个key1对应一个Map,map中每个value中@class后面对应的值为类信息。
在这里插入图片描述

template.opsForHash().put("redisHash","name","tom");
说明api备注
单插入.put(redisKey,hashKey, value)
批量插入Map<String,Object> map
.putAll(key, map)
查单数据.get(redisKey,hashKey)
查所有数据.entries(redisHash)
查key是否存在Boolean hasKey(redisKey, Object hashKey);
批量获取Hash值List multiGet(redisKey, List<Object> kes);
获取key集合Set keys(redisKey)
批量删除Long delete(redisKey, Object… hashKeys)
数值型value + 5increment(redisKey, hashKey, 5)返回操作后的value值
hashkey不存在时设置valueBoolean putIfAbsent(redisKey,hashKey, value)存在返回true,不存在返回true

遍历:

Cursor<Map.Entry<Object, Object>> curosr = template.opsForHash().scan("redisHash", ScanOptions.ScanOptions.NONE);while(curosr.hasNext()){Map.Entry<Object, Object> entry = curosr.next();System.out.println(entry.getKey()+":"+entry.getValue());}

4>API:Set数据

template.opsForSet().add(k,v)
说明api备注
添加Long add(key, V… values);values可以是:String[]
查看所有.members(key)
查询长度.size(key)
查询元素是否存在Boolean isMember(key, Object o);
批量删除Long remove(key, Object… values);values可以是:String[]
随机移除V pop(K key);
将元素value 从 sourcekey所在集合移动到 destKey所在集合Boolean move(sourcekey, V value, destKey)移动后sourcekey集合再没有value元素,destKey集合去重。
求两个集合的交集Set intersect(K key, K otherKey);
求多个无序集合的交集Set intersect(K key, Collection otherKeys);
求多个无序集合的并集Set union(K key, Collection otherKeys);

遍历:

Cursor<Object> curosr = template.opsForSet().scan("setTest", ScanOptions.NONE);while(curosr.hasNext()){System.out.println(curosr.next());}

5>API:ZSet集合

有序的Set集合,排序依据是Score。

template.opsForZSet().add("zset1","zset-1",1.0)
说明api备注
添加单个元素Boolean add(k, v, double score)返回元素是否已存在
批量添加元素Long add(k, Set<TypedTuple> tuples)举例:见下文1.
批量删除Long remove(K key, Object… values);
排序按分数值asc,返回成员o的排名Long rank(key, Object o);排名从0开始
排序按分数值desc,返回成员o的排名Long reverseRank(key, Object o);排名从0开始
按区间查询,按分数值ascSet range(key, 0, -1);
增加元素的score值,并返回增加后的值Double incrementScore(K key, V value, double delta);
  1. 批量添加元素
ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<Object>("zset-5",9.6);ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<Object>("zset-6",9.9);Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<ZSetOperations.TypedTuple<Object>>();tuples.add(objectTypedTuple1);tuples.add(objectTypedTuple2);System.out.println(template.opsForZSet().add("zset1",tuples));System.out.println(template.opsForZSet().range("zset1",0,-1));
  1. 遍历
Cursor<ZSetOperations.TypedTuple<Object>> cursor = template.opsForZSet().scan("zzset1", ScanOptions.NONE);while (cursor.hasNext()){ZSetOperations.TypedTuple<Object> item = cursor.next();System.out.println(item.getValue() + ":" + item.getScore());}

2)使用

1>依赖

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

2>配置文件

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

1>序列化配置

RedisTemplate默认采用JDK的序列化工具,序列化为字节形式,在redis中可读性很差。
修改默认的序列化方式为jackson:

@Configuration
public class RedisConfig {@Bean     //RedisConnectionFactory不需要我们创建Spring会帮助我们创建public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory){
//        1.创建RedisTemplate对象RedisTemplate<String,Object> template = new RedisTemplate<>();
//        2.设置连接工厂template.setConnectionFactory(connectionFactory);
//        3.创建JSON序列化工具GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
//        4.设置Key的序列化template.setKeySerializer(RedisSerializer.string());template.setHashKeySerializer(RedisSerializer.string());
//        5.设置Value的序列化   jsonRedisSerializer使我们第三步new出来的template.setValueSerializer(jsonRedisSerializer);template.setHashValueSerializer(jsonRedisSerializer);
//        6.返回return template;}
}

但是json序列号可能导致一些其他的问题:JSON序列化器会将类的class类型写入到JSON结果中并存入Redis,会带来额外的内存开销。
为了节省内存空间,我们并不会使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key哈value,当要存储Java对象时,手动完成对象的序列化和反序列化。

4>java实现

public class RedisUtil {@Autowiredprivate RedisTemplate redisTemplate;/*** 批量删除对应的value* * @param keys*/public void remove(final String... keys) {for (String key : keys) {remove(key);}}/*** 批量删除key* * @param pattern*/public void removePattern(final String pattern) {Set<Serializable> keys = redisTemplate.keys(pattern);if (keys.size() > 0)redisTemplate.delete(keys);}public void remove(final String key) {if (exists(key)) {redisTemplate.delete(key);}}public boolean exists(final String key) {return redisTemplate.hasKey(key);}public String get(final String key) {Object result = null;ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();result = operations.get(key);if (result == null) {return null;}return result.toString();}public boolean set(final String key, Object value) {boolean result = false;try {ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();operations.set(key, value);result = true;} catch (Exception e) {e.printStackTrace();}return result;}public boolean set(final String key, Object value, Long expireTime) {boolean result = false;try {ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();operations.set(key, value);redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);result = true;} catch (Exception e) {e.printStackTrace();}return result;}public boolean hmset(String key, Map<String, String> value) {boolean result = false;try {redisTemplate.opsForHash().putAll(key, value);result = true;} catch (Exception e) {e.printStackTrace();}return result;}public Map<String, String> hmget(String key) {Map<String, String> result = null;try {result = redisTemplate.opsForHash().entries(key);} catch (Exception e) {e.printStackTrace();}return result;}
}

3)StringRedisTemplate

key和value的序列化方式默认就是String方式,省去了我们自定义RedisTemplate的过程。

    @Autowiredprivate StringRedisTemplate stringRedisTemplate;
//  JSON工具private static final ObjectMapper mapper = new ObjectMapper();@Testvoid testStringTemplate() throws JsonProcessingException {
//      准备对象User user = new User("abc", 18);
//      手动序列化String json = mapper.writeValueAsString(user);
//      写入一条数据到RedisstringRedisTemplate.opsForValue().set("user:200",json);//      读取数据String s = stringRedisTemplate.opsForValue().get("user:200");
//      反序列化User user1 = mapper.readValue(s,User.class);System.out.println(user1);}

3,Redis数据序列化

4,Repository操作

5,Spring Cache

Spring 3.1 引入了对 Cache 的支持,使用使用 JCache(JSR-107)注解简化开发。

1)org.springframework.cache.Cache接口

  1. 包含了缓存的各种操作集合;
  2. 提供了各种xxxCache 的实现,比如:RedisCache
    在这里插入图片描述

2)org.springframework.cache.CacheManager接口

  1. 定义了创建、配置、获取、管理和控制多个唯一命名的 Cache。这些 Cache 存在于 CacheManager 的上下文中。
  2. 提供了各种xxxCacheManager 的实现,比如RedisCacheManager。

3)相关注解

1>@EnableCaching

  1. 开启基于注解的缓存;
  2. 作用在缓存配置类上或者SpringBoot 的主启动类上;

2>@Cacheable

缓存注解。

使用注意:

  1. 基于AOP去实现的,所以必须通过IOC对象去调用。
  2. 要缓存的 Java 对象必须实现 Serializable 接口。
@Cacheable(cacheNames = "usersBySpEL",//key通过变量拼接key="#root.methodName + '[' + #id + ']'",//id大于1才缓存。可缺省condition = "#id > 1",//当id大于10时,条件为true,方法返回值不会被缓存。可缺省unless = "#id > 10")public User getUserBySpEL(Integer id) {}@Cacheable(value = {"menuById"}, key = "'id-' + #menu.id")public Menu findById(Menu menu) {return menu;}
常用属性说明备注代码示例
cacheNames/value缓存名称,用来划分不同的缓存区,避免相同key值互相影响。可以是单值、数组;
在redis中相当于key的一级目录,支持:拼接多层目录
cacheNames = "users"
cacheNames = {"users","account"}
key缓存数据时使用的 key,默认是方法参数。
可以使用 spEL 表达式来编写
keyGeneratorkey 的生成器,统一管理key。key 和 keyGenerator 二选一使用,同时使用会导致异常。keyGenerator = "myKeyGenerator"
cacheManager指定缓存管理器,从哪个缓存管理器里面获取缓存
condition可以用来指定符合条件的情况下才缓存
unless否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存通过 #result 获取方法结果进行判断。
sync是否使用异步模式。默认是方法执行完,以同步的方式将方法返回的结果存在缓存中

spEL常用元数据:

说明示例备注
#root.methodName当前被调用的方法名
#root.method.name当前被调用的方法
#root.target当前被调用的目标对象
#root.targetClass当前被调用的目标对象类
#root.args[0]当前被调用的方法的参数列表
#root.cacheds[0].name当前方法调用使用的缓存区列表
#参数名 或 #p0 或 #a0方法的参数名; 0代表参数的索引
#result方法执行后的返回值如果没有执行则没有内容

3>@CachePut

主要针对配置,能够根据方法的请求参数对其结果进行缓存。

  1. 区别于 @Cacheable,它每次都会触发真实方法的调用,可以保证缓存的一致性。
  2. 属性与 @Cacheable 类同。

4>@CacheEvict

根据一定的条件对缓存进行清空。

  1. 标记在类上时表示其中所有方法的执行都会触发缓存的清除操作;
常用属性说明备注代码示例
value
key
condition
allEntries为true时,清除value属性值中的所有缓存;默认为false,可以指定清除value属性值下具体某个key的缓存
beforeInvocation1. 默认是false,即在方法执行成功后触发删除缓存的操作;
2.如果方法抛出异常未能成功返回,不会触发删除缓存的操作
3.当改为true时,方法执行之前会清除指定的缓存,这样不论方法执行成功还是失败都会清除缓存

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Duilib List 控件学习

这是自带的一个示例; 一开始运行的时候List中是空的,点击Search按钮以后就填充列表框; 先看一下列表框列头是在xml文件中形成的; <List name="domainlist" bkcolor="#FFFFFFFF" ... menu="true"> <ListHeader height="24…

HTTP网络通信协议基础

目录 前言&#xff1a; 1.HTTP协议理论 1.1协议概念 1.2工作原理 2.HTTP抓包工具 2.1Fiddler工具 2.2抓包原理 3.HTTP协议格式 3.1HTTP请求 3.2HTTP响应 3.3格式总结 前言&#xff1a; 在了解完网络编程的传输层UDP和TCP通信协议后&#xff0c;就需要开始对数据进行…

苍穹外卖实操笔记六---缓存商品,购物车功能

苍穹外卖实操笔记六—缓存商品&#xff0c;购物车功能 一.缓存菜品 可以使用redis进行缓存&#xff1b;另外&#xff0c;在实现缓存套餐时可以使用spring cache提高开发效率&#xff1b;   通过缓存数据&#xff0c;降低访问数据库的次数&#xff1b; 使用的缓存逻辑&#…

STM32 STD/HAL库驱动W25Q64模块读写字库数据+OLED0.96显示例程

STM32 STD/HAL库驱动W25Q64 模块读写字库数据OLED0.96显示例程 &#x1f3ac;原创作者对W25Q64保存汉字字库演示&#xff1a; W25Q64保存汉字字库 &#x1f39e;测试字体显示效果&#xff1a; &#x1f4d1;功能实现说明 利用W25Q64保存汉字字库&#xff0c;OLED显示汉字的时…

opencv mat用法赋值克隆的操作和一些基本属性

//Mat基本结构 (头部 数据部分) //赋值的话 就是修改了指针位置 但还是指向了原来数据 并没创建数据 本质上并没有变 //只有克隆或者拷贝时 它才会真正复制一份数据 //代码实现 //创建方法 - 克隆 //Mat m1 src.clone(); //复制 //Mat m2; //src.copyTo(m2); //赋值法 …

C语言求解猴子分桃子

问题&#xff1a;海滩上有一堆桃子&#xff0c;五只猴子来分。第一只猴子把这堆桃子平均分为五份&#xff0c;多了一个&#xff0c;这只 猴子把多的一个扔入海中&#xff0c;拿走了一份。第二只猴子把剩下的桃子又平均分成五份&#xff0c;又多了 一个&#xff0c;它同样把多的…

DataBinding简易入门

简介 DataBinding是Google在18年推出的数据绑定框架&#xff0c;采用了MVVM模式来降低各模块之间代码的耦合度&#xff0c;使得整体代码逻辑设计更加清晰。众所周知&#xff0c;MVVM类似于MVC&#xff0c;主要目的是为分离View&#xff08;视图&#xff09;和Model&#xff08…

渗透专用虚拟机(公开版)

0x01 工具介绍 okfafu渗透虚拟机公开版。解压密码&#xff1a;Mrl64Miku&#xff0c;压缩包大小&#xff1a;15.5G&#xff0c;解压后大小&#xff1a;16.5G。安装的软件已分类并在桌面中体现&#xff0c;也可以使用everything进行查找。包含一些常用的渗透工具以及一些基本工…

如何入门AI Agent?

随着chatgpt问世&#xff0c;大模型已经在加速各行各业的变革&#xff0c;这是我之前对AI Agent行业的粗浅判断。 下面给大家介绍一下如何制作AI Agent&#xff0c;我会用我开发的全赞AI为例子进行简要的介绍&#xff0c;下面是一种工具型AI Agent的框架图 这是一个大量使用工具…

探索海洋世界,基于YOLOv8全系列【n/s/m/l/x】参数模型开发构建海洋场景下海洋生物检测识别分析系统

前面的博文中&#xff0c;开发实践过海底相关生物检测识别的项目&#xff0c;对于海洋场景下的海洋生物检测则很少有所涉及&#xff0c;这里本文的主要目的就是想要开发构建基于YOLOv8的海洋场景下的海洋生物检测识别系统。 首先看下实例效果&#xff1a; 简单看下实例数据情况…

解决 postman测试接口报404 Not Found

JDK版本&#xff1a;jdk17 IDEA版本&#xff1a;IntelliJ IDEA 2022.1.3 文章目录 问题描述原因分析解决方案 问题描述 当我使用postman测试接口时&#xff0c;报了 404 Not Found 的错误&#xff0c;报错截图如下所示 但我的后端程序中已经定义了该接口&#xff0c;如下所示 …

MySQL-----DCL基础操作

▶ DCL简介 DCL英文全称是Data ControlLanguage(数据控制语言)&#xff0c;用来管理数据库用户、控制数据库的访问权限。 DCL--管理用户 ▶ 查询用户 use mysql; select * from user; ▶ 创建用户 ▶ 语法 create user 用户名主机名 identified by 密码 设置为在任意主机上访问…