高端网站设计新鸿儒,企业建站系统下载,老版51个人空间找照片,绍兴网站设计1#xff0c;spring-data-redis官网
1#xff09;特点
提供了对不同Redis客户端的整合#xff08;Lettuce和Jedis#xff09;提供了RedisTemplate统一API来操作Redis支持Redis的发布订阅模型支持Redis哨兵和Redis集群支持基于Lettuce的响应式编程支持基于JDK、JSON、字符…1spring-data-redis官网
1特点
提供了对不同Redis客户端的整合Lettuce和Jedis提供了RedisTemplate统一API来操作Redis支持Redis的发布订阅模型支持Redis哨兵和Redis集群支持基于Lettuce的响应式编程支持基于JDK、JSON、字符串、Spring独享的数据序列化及反序列化支持基于Redis的JDKCollection实现
2RedisTemplate
SpringDataRedis中提供了RedisTemplate工具类其中封装了各种对Redis的操作。
1常用API
api说明redisTemplate.opsForValue();操作字符串redisTemplate.opsForHash();操作hashredisTemplate.opsForList();操作listredisTemplate.opsForSet();操作setredisTemplate.opsForZSet();操作有序setredisTemplate.expire(key, 60 * 10000 * 30, TimeUnit.MILLISECONDS);设置过期时间
1API:String
redisTemplate.opsForValue().set(name,tom)说明api备注添加单值.set(key,value)获取单值.get(key)添加单值并返回这个值是否已经存在.setIfAbsent(key, value)添加单值并返回旧值.getAndSet(key, value)批量添加MapString,String maps; .multiSet(maps)批量获取ListString keys; .multiGet(keys)数值型1.increment(key,1)设置过期时间set(key, value, timeout, TimeUnit.SECONDS)过期返回null字符串追加.append(key,Hello);
2API:List数据
template.opsForList().range(list,0,-1)说明api备注单个插入Long leftPush(key, value);返回操作后的列表的长度批量插入Long leftPushAll(K key, V… values);返回操作后的列表的长度values可以是String[]、ListObject查看.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)
3API:Hash操作
一个key1对应一个Mapmap中每个value中class后面对应的值为类信息。
template.opsForHash().put(redisHash,name,tom);说明api备注单插入.put(redisKey,hashKey, value)批量插入MapString,Object map .putAll(key, map)查单数据.get(redisKey,hashKey)查所有数据.entries(redisHash)查key是否存在Boolean hasKey(redisKey, Object hashKey);批量获取Hash值List multiGet(redisKey, ListObject kes);获取key集合Set keys(redisKey)批量删除Long delete(redisKey, Object… hashKeys)数值型value 5increment(redisKey, hashKey, 5)返回操作后的value值hashkey不存在时设置valueBoolean putIfAbsent(redisKey,hashKey, value)存在返回true不存在返回true
遍历
CursorMap.EntryObject, Object curosr template.opsForHash().scan(redisHash, ScanOptions.ScanOptions.NONE);while(curosr.hasNext()){Map.EntryObject, Object entry curosr.next();System.out.println(entry.getKey():entry.getValue());}4API: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);
遍历
CursorObject curosr template.opsForSet().scan(setTest, ScanOptions.NONE);while(curosr.hasNext()){System.out.println(curosr.next());}5API:ZSet集合
有序的Set集合排序依据是Score。
template.opsForZSet().add(zset1,zset-1,1.0)说明api备注添加单个元素Boolean add(k, v, double score)返回元素是否已存在批量添加元素Long add(k, SetTypedTuple 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);
批量添加元素
ZSetOperations.TypedTupleObject objectTypedTuple1 new DefaultTypedTupleObject(zset-5,9.6);ZSetOperations.TypedTupleObject objectTypedTuple2 new DefaultTypedTupleObject(zset-6,9.9);SetZSetOperations.TypedTupleObject tuples new HashSetZSetOperations.TypedTupleObject();tuples.add(objectTypedTuple1);tuples.add(objectTypedTuple2);System.out.println(template.opsForZSet().add(zset1,tuples));System.out.println(template.opsForZSet().range(zset1,0,-1));遍历
CursorZSetOperations.TypedTupleObject cursor template.opsForZSet().scan(zzset1, ScanOptions.NONE);while (cursor.hasNext()){ZSetOperations.TypedTupleObject item cursor.next();System.out.println(item.getValue() : item.getScore());}2使用
1依赖
!-- Redis依赖--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependency
!-- 连接池依赖--dependencygroupIdorg.apache.commons/groupIdartifactIdcommons-pool2/artifactId/dependency2配置文件
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 RedisTemplateString,Object redisTemplate(RedisConnectionFactory connectionFactory){
// 1.创建RedisTemplate对象RedisTemplateString,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对象时手动完成对象的序列化和反序列化。
4java实现
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) {SetSerializable 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;ValueOperationsSerializable, 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 {ValueOperationsSerializable, 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 {ValueOperationsSerializable, 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, MapString, String value) {boolean result false;try {redisTemplate.opsForHash().putAll(key, value);result true;} catch (Exception e) {e.printStackTrace();}return result;}public MapString, String hmget(String key) {MapString, String result null;try {result redisTemplate.opsForHash().entries(key);} catch (Exception e) {e.printStackTrace();}return result;}
}3StringRedisTemplate
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);}3Redis数据序列化
4Repository操作
类似jpa操作只要Redis服务器版本在2.8.0以上不用事务就可以使用Repository做各种操作。 注意Repository和jpa的Repository是同一个意味着jpa支持的api在redis操作中通用。
1注解
注解说明属性对比jpaRedisHash用来定义实体。value定义了不同类型对象存储时使用的前缀也叫做键空间默认是全限定类名timeToLive定义缓存的秒数类似EntityId定义对象的标识符类似IdIndexed定义二级索引加在属性上可以将该属性定义为查询用的索引Reference缓存对象引用一般引用的对象也会被展开存储在当前对象中添加了该注解后会直接存储该对象在Redis中的引用
2使用
不需要添加依赖。 spring-boot自动添加了EnableRedisRepositories注解。实体
RedisHash(valuemenu,timeToLive60)
public class RedisMenuItem implements Serializable{Idprivste Long id;Indexedprivate String name;private Size size;private Money price;
}定义Repository接口
public interface RedisMenuRepository extends CrudRepositoryRedisMenuItem, Long{ListRedisMenuItem findByName(String name);
}查询
ListMenuItem itemList menuRepository.findAll();menuRepository.save(menuItem);5Spring Cache
Spring 3.1 引入了对 Cache 的支持使用使用 JCacheJSR-107注解简化开发。 注意可支持幂等操作的接口才可以使用缓存注解因为缓存和参数无关即不管什么参数返回值一样。
1org.springframework.cache.Cache接口
包含了缓存的各种操作集合提供了各种xxxCache 的实现比如RedisCache
2org.springframework.cache.CacheManager接口
定义了创建、配置、获取、管理和控制多个唯一命名的 Cache。这些 Cache 存在于 CacheManager 的上下文中。提供了各种xxxCacheManager 的实现比如RedisCacheManager。
3相关注解
1EnableCaching
开启基于注解的缓存作用在缓存配置类上或者SpringBoot 的主启动类上
2Cacheable
缓存注解。
使用注意
基于AOP去实现的所以必须通过IOC对象去调用。要缓存的 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 myKeyGeneratorcacheManager指定缓存管理器从哪个缓存管理器里面获取缓存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方法执行后的返回值如果没有执行则没有内容
3CachePut
主要针对配置能够根据方法的请求参数对其结果进行缓存。
区别于 Cacheable它每次都会触发真实方法的调用可以保证缓存的一致性。属性与 Cacheable 类同。
4CacheEvict
根据一定的条件对缓存进行清空。
标记在类上时表示其中所有方法的执行都会触发缓存的清除操作
常用属性说明备注代码示例valuekeyconditionallEntries为true时清除value属性值中的所有缓存默认为false可以指定清除value属性值下具体某个key的缓存beforeInvocation1. 默认是false即在方法执行成功后触发删除缓存的操作 2.如果方法抛出异常未能成功返回不会触发删除缓存的操作 3.当改为true时方法执行之前会清除指定的缓存这样不论方法执行成功还是失败都会清除缓存
4缓存实现
上文中基于注解的缓存接口有一层CacheMananger抽象其中用ConcurrentHashMap维护了多个Cache通过cacheNames指定了哪个Cache。