本文章为系列文章,如需系统观看请按照文章顺序阅读,如有所了解,解决针对性问题,可直接阅读,谢谢支持!前言 Java操作Redis有很多种方式,主要有Jedis,redisson,lettuce等还有Spring家族的springdataredisJedis 是Redis的Java实现客户端,提供了比较全面的Redis命令的支持Redisson 实现了分布式和可扩展的Java数据结构,提供很多分布式相关操作服务,例如,分布式锁,分布式集合,延迟队列Lettuce 用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器,主要在一些分布式缓存框架上使用比较多springdataredisSpringDataRedis项目(简称SDR)对Redis的KeyValue数据存储操作提供了更高层次的抽象类似于SpringFramework对JDBC支持一样项目主页:http:projects。spring。iospringdataredis项目文档:http:docs。spring。iospringdataredisdocsSpringDataRedis使得在Spring应用中读写Redis数据库更加容易。SpringDataRedis提供了四种Redis服务的Java客户端包的集成,分别是Jedis,JRedis,SRPandLettuce 一般我们都会选择springdataredis核心对象RedisConnectionFactory redis的连接工厂类,根据Redis配置连接上Redis服务RedisTemplate 熟悉Spring操作JDBC都知道JdbcTemplate作用,这个类也一样,spring封装了RedisTemplate对象来进行对redis的各种操作,它支持所有的redis原生的apiOperation 针对Jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口ValueOperations:String类型数据操作HashOperations:针对map类型的数据操作ListOperations:针对list类型的数据操作SetOperations:set类型数据操作ZSetOperations:zset类型数据操作BoundKeyOperations 提供了对key的bound(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须显式的再次指定KeyBoundValueOperations:RedisStringValuekey约束BoundHashOperations:RedisHashkey约束BoundListOperations:RedisListkey约束BoundSetOperations:RedisSetkey约束BoundZSetOperations:RedisSortSetkey约束RedisTemplate序列化问题介绍 当数据存储到Redis时,键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer问题 springdataredis中redisTemplate默认使用JDK的序列化策略,会出现两个问题使用rediscli或者可视化工具查看数据时,不管是key还是value头部都会携带很多特殊字符,不易查看,Java代码中获取数据时不受影响,但是对运维来说就不友好了JDKSerializer太费资源解决使用Jacksonserializer替代JDKSerializerStringRedisSerializer结合GenericJackson2JsonRedisSerializerspringdataredis支持的序列化策略 springdataredis默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略GenericToStringSerializer:可以将任何对象泛化为字符串并序列化Jackson2JsonRedisSerializer:跟JacksonJsonRedisSerializer实际上是一样的JacksonJsonRedisSerializer:序列化object对象为json字符串JdkSerializationRedisSerializer:序列化java对象(被序列化的对象必须实现Serializable接口)StringRedisSerializer:简单的字符串序列化GenericToStringSerializer:类似StringRedisSerializer的字符串序列化GenericJackson2JsonRedisSerializer:类似Jackson2JsonRedisSerializer,但使用时构造函数不用特定的类 key和hashKey:推荐使用StringRedisSerializer:简单的字符串序列化 value和hashValue:推荐使用Jackson2JsonRedisSerializerRedisTemplate和StringRedisTemplate的区别两者的关系是StringRedisTemplate继承RedisTemplate。两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存 当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可,但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择开搞开发环境 SpringBoot2。1。5、Redis5。0。5、Maven3。5。0、mybatisPlus3。2。0pom依赖!web启动器dependencygroupIdorg。springframework。bootgroupIdspringbootstarterwebartifactIddependency!redis启动器dependencygroupIdorg。springframework。bootgroupIdspringbootstarterdataredisartifactIddependencydependencygroupIdcom。alibabagroupIdfastjsonartifactIdversion1。2。7versiondependencydependencygroupIdorg。springframework。bootgroupIdspringbootstartertestartifactIdscopetestscopedependencyapplication。yml文件spring:Redis配置redis:host:test201port:6379password:这些都有默认配置,如果没有特殊需求可不写连接超时时间(2。0中该参数的类型为Duration,这里在配置的时候需要指明单位timeout:2000ms连接池最大连接数(使用负值表示没有限制)maxactive:8连接池最大阻塞等待时间(使用负值表示没有限制)maxwait:1ms连接池中的最大空闲连接maxidle:8连接池中的最小空闲连接minidle:0RedisConfig配置类 上边咱们说默认的RedisTemplate使用的序列化方式是JDK的,会存在特殊字符的问题而且性能损耗较大,我们创建JavaConfig修改默认实现的RedisTemplate序列化方式importcom。fasterxml。jackson。annotation。JsonAutoDetect;importcom。fasterxml。jackson。annotation。PropertyAccessor;importcom。fasterxml。jackson。databind。ObjectMapper;importorg。springframework。context。annotation。Bean;importorg。springframework。context。annotation。Configuration;importorg。springframework。data。redis。connection。RedisConnectionFactory;importorg。springframework。data。redis。core。RedisTemplate;importorg。springframework。data。redis。serializer。Jackson2JsonRedisSerializer;importorg。springframework。data。redis。serializer。StringRedisSerializer;Redis的配置类SDR项目操作Redis的话需要使用RedisTemplate对象但是该对象默认使用的数据序列化方法是JDK的,可能会存在特殊字符key和hashKey我们推荐使用String序列化value我们推荐是JSON存储,使用Json序列化添加Configuration注解,否则该类不会被加载ConfigurationpublicclassRedisConfig{Bean:创建对象放到IOC容器中RedisConnectionFactory:Redis的连接工厂,根据application。yml文件中的Redis的配置做Redis连接和连接池的管理该对象在项目初始化时被创建,有一个实现类是LettuceConnectionFactoryBeanpublicRedisTemplateString,ObjectredisTemplate(RedisConnectionFactoryconnectionFactory){创建原生的RedisTemplate对象RedisTemplateString,ObjectredisTemplatenewRedisTemplateString,Object();设置连接工厂redisTemplate。setConnectionFactory(connectionFactory);使用Jackson2JsonRedisSerialize替换默认的JDK序列化Jackson2JsonRedisSerializerjackson2JsonRedisSerializernewJackson2JsonRedisSerializer(Object。class);创建JSON序列化的对象,value使用JSON序列化方式ObjectMapperomnewObjectMapper();设置序列化的策略om。setVisibility(PropertyAccessor。ALL,JsonAutoDetect。Visibility。ANY);启用默认的类型om。enableDefaultTyping(ObjectMapper。DefaultTyping。NONFINAL);引用JSON序列化jackson2JsonRedisSerializer。setObjectMapper(om);创建String序列化,我们的key使用String序列化方式StringRedisSerializerstringRedisSerializernewStringRedisSerializer();key采用String的序列化方式redisTemplate。setKeySerializer(stringRedisSerializer);hash的key也采用String的序列化方式redisTemplate。setHashKeySerializer(stringRedisSerializer);value序列化方式采用JSONredisTemplate。setValueSerializer(jackson2JsonRedisSerializer);hash的value序列化方式采用JSONredisTemplate。setHashValueSerializer(jackson2JsonRedisSerializer);使用该配置redisTemplate。afterPropertiesSet();返回修改后的RedisTemplate对象returnredisTemplate;}}测试类packagecom。tian。redis;importorg。junit。Test;importorg。junit。runner。RunWith;importorg。springframework。beans。factory。annotation。Autowired;importorg。springframework。boot。test。context。SpringBootTest;importorg。springframework。data。redis。core。;importorg。springframework。test。context。junit4。SpringRunner;importjava。util。;importjava。util。concurrent。TimeUnit;RunWith(SpringRunner。class)SpringBootTestpublicclassDay0512RedisApplicationTests{TestpublicvoidcontextLoads(){}注入RedisTemplateAutowiredprivateRedisTemplateredisTemplate;操作StringTestpublicvoidtest1(){获取操作String类型的对象ValueOperationsvalueOperationsredisTemplate。opsForValue();存储数据try{valueOperations。set(user1,添哥);valueOperations。set(user2,小添哥哥);System。out。println(存储数据成功);获取数据Stringuser1(String)valueOperations。get(user1);Stringuser2(String)valueOperations。get(user2);System。out。println(user1user2);}catch(Exceptione){e。printStackTrace();}}操作listTestpublicvoidtest2(){ListOperationsoperationsredisTemplate。opsForList();Longnumoperations。leftPushAll(l1,l11,l22,l33,l44);System。out。println(插入数据个数》num);取值Listlistoperations。range(l1,0,1);for(Objecto:list){System。out。println(list》o);}}操作setTestpublicvoidtest3(){SetOperationsoperationsredisTemplate。opsForSet();Longnumoperations。add(s1,s11,s22,s33,s44,s11,s22,s55);System。out。println(num);获取Setsetoperations。members(s1);for(Objecto:set){System。out。println(o);}}操作zsetTestpublicvoidtest4(){ZSetOperationsoperationsredisTemplate。opsForZSet();operations。add(z1,z10,100。00);operations。add(z1,z20,200。00);operations。add(z1,z5,50。00);获取值Setsetoperations。range(z1,0,1);for(Objecto:set){System。out。println(o);}}操作HashTestpublicvoidtest5(){HashOperationsoperationsredisTemplate。opsForHash();存储学生1operations。put(stu:1:info,name,小添);operations。put(stu:1:info,classRoom,快刀班);存储学生2HashMapString,ObjectmapnewHashMap();添加学生信息map。put(name,晓添);map。put(classRoom,吃瓜班);operations。putAll(stu:2:info,map);获取数据1Objectnameoperations。get(stu:1:info,name);ObjectclassRoomoperations。get(stu:1:info,classRoom);System。out。println(学生1》nameclassRoom);获取数据2Mapentriesoperations。entries(stu:2:info);遍历mapSetsetentries。keySet();for(Objecto:set){System。out。println(oentries。get(o));}}对key的操作Testpublicvoidtest6(){判断key是否存在BooleanhasKeyredisTemplate。hasKey(stu:2:info);System。out。println(stu:2:infohasKey);设置过期时间,k3键10秒过期redisTemplate。expire(k3,10,TimeUnit。SECONDS);设置l1键在20205137点过期redisTemplate。expireAt(l1,newDate(2020,5,13,7,00,00));}}下方两个测试是使用RedisUtil中封装使用boundHashOps方式操作Testpublicvoidt1(){StudentstudentnewStudent();student。setId(100);student。setName(石靓仔);student。setSex(男);student。setBirth(19950626);redisUtil。putSome(Student。class,student,student。getId(),student);}Testpublicvoidt2(){ListStudentstudentListnewArrayList();CursorMap。EntryString,ObjectstudentredisUtil。getSome(student,Student。class);while(student。hasNext()){System。out。println(student。getCursorId());Map。EntryString,Objectnextstudent。next();Studentstudent1(Student)next。getValue();studentList。add(student1);}for(Studentstudent1:studentList){System。out。println(student1);}}RedisUtil类 封装一些常用的操作,大家可以根据自己的需求进行封装,这个作为参考吧packagecom。tian。springbootredis。util;importorg。springframework。beans。factory。annotation。Autowired;importorg。springframework。data。redis。core。RedisTemplate;importorg。springframework。stereotype。Component;importorg。springframework。util。CollectionUtils;importjava。util。List;importjava。util。Map;importjava。util。Set;importjava。util。concurrent。TimeUnit;ClassName:RedisUtilsDescription:date:201911110011下午19:59authorsttsinceJDK1。8ComponentpublicclassRedisUtil{AutowiredpublicRedisTemplateredisTemplate;common26指定缓存失效时间27paramkey键28paramtime时间(秒)29return30publicbooleanexpire(Stringkey,longtime){try{if(time0){redisTemplate。expire(key,time,TimeUnit。SECONDS);}returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}根据key获取过期时间paramkey键不能为nullreturn时间(秒)返回0代表为永久有效publiclonggetExpire(Stringkey){returnredisTemplate。getExpire(key,TimeUnit。SECONDS);}判断key是否存在paramkey键returntrue存在false不存在publicbooleanhasKey(Stringkey){try{returnredisTemplate。hasKey(key);}catch(Exceptione){e。printStackTrace();returnfalse;}}删除缓存paramkey可以传一个值或多个SuppressWarnings(unchecked)publicbooleandel(String。。。key){if(key!nullkey。length0){if(key。length1){returnredisTemplate。delete(key〔0〕);}returnredisTemplate。delete(CollectionUtils。arrayToList(key))0?true:false;}returnfalse;}匹配所有的keyparampetternreturnpublicSetStringkeys(Stringpettern){if(pettern。trim()!pettern!null){returnredisTemplate。keys(pettern);}returnnull;}String普通缓存获取paramkey键return值publicObjectget(Stringkey){returnkeynull?null:redisTemplate。opsForValue()。get(key);}普通缓存放入paramkey键paramvalue值returntrue成功false失败publicbooleanset(Stringkey,Objectvalue){try{redisTemplate。opsForValue()。set(key,value);returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}普通缓存放入并设置时间paramkey键paramvalue值paramtime时间(秒)time要大于0如果time小于等于0将设置无限期returntrue成功false失败publicbooleanset(Stringkey,Objectvalue,longtime){try{if(time0){redisTemplate。opsForValue()。set(key,value,time,TimeUnit。SECONDS);}else{set(key,value);}returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}递增paramkey键paramdelta要增加几(大于0)returnpubliclongincr(Stringkey,longdelta){if(delta0){thrownewRuntimeException(递增因子必须大于0);}returnredisTemplate。opsForValue()。increment(key,delta);}递减paramkey键paramdelta要减少几(小于0)returnpubliclongdecr(Stringkey,longdelta){if(delta0){thrownewRuntimeException(递减因子必须大于0);}returnredisTemplate。opsForValue()。increment(key,delta);}MapHashGetparamkey键不能为nullparamitem项不能为nullreturn值publicObjecthget(Stringkey,Stringitem){returnredisTemplate。opsForHash()。get(key,item);}获取hashKey对应的所有键值paramkey键return对应的多个键值publicListObjecthmget(Stringkey){returnredisTemplate。opsForHash()。values(key);}HashSetparamkey键parammap对应多个键值returntrue成功false失败publicbooleanhmset(Stringkey,MapString,Objectmap){try{redisTemplate。opsForHash()。putAll(key,map);returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}HashSet并设置时间paramkey键parammap对应多个键值paramtime时间(秒)returntrue成功false失败publicbooleanhmset(Stringkey,MapString,Objectmap,longtime){try{redisTemplate。opsForHash()。putAll(key,map);if(time0){expire(key,time);}returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}向一张hash表中放入数据,如果不存在将创建paramkey键paramitem项paramvalue值returntrue成功false失败publicbooleanhset(Stringkey,Stringitem,Objectvalue){try{redisTemplate。opsForHash()。put(key,item,value);returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}向一张hash表中放入数据,如果不存在将创建paramkey键paramitem项paramvalue值paramtime时间(秒)注意:如果已存在的hash表有时间,这里将会替换原有的时间returntrue成功false失败publicbooleanhset(Stringkey,Stringitem,Objectvalue,longtime){try{redisTemplate。opsForHash()。put(key,item,value);if(time0){expire(key,time);}returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}删除hash表中的值paramkey键不能为nullparamitem项可以使多个不能为nullpublicvoidhdel(Stringkey,Object。。。item){redisTemplate。opsForHash()。delete(key,item);}判断hash表中是否有该项的值paramkey键不能为nullparamitem项不能为nullreturntrue存在false不存在publicbooleanhHasKey(Stringkey,Stringitem){returnredisTemplate。opsForHash()。hasKey(key,item);}hash递增如果不存在,就会创建一个并把新增后的值返回paramkey键paramitem项paramby要增加几(大于0)returnpublicdoublehincr(Stringkey,Stringitem,doubleby){returnredisTemplate。opsForHash()。increment(key,item,by);}hash递减paramkey键paramitem项paramby要减少记(小于0)returnpublicdoublehdecr(Stringkey,Stringitem,doubleby){returnredisTemplate。opsForHash()。increment(key,item,by);}存储对象paramkeyparamfieldparamvaluepublicvoidputSome(Classcls,Stringkey,Stringfield,Objectvalue){redisTemplate。setHashValueSerializer(newJackson2JsonRedisSerializer(cls));redisTemplate。boundHashOps(key)。put(field,value);}获取对象paramkeyparamclsreturnpublicCursorMap。EntryString,ObjectgetSome(Stringkey,Classcls){redisTemplate。setHashValueSerializer(newJackson2JsonRedisSerializer(cls));CursorMap。EntryString,ObjectscanredisTemplate。boundHashOps(key)。scan(ScanOptions。scanOptions()。build());returnscan;}set根据key获取Set中的所有值paramkey键returnpublicSetObjectsGet(Stringkey){try{returnredisTemplate。opsForSet()。members(key);}catch(Exceptione){e。printStackTrace();returnnull;}}根据value从一个set中查询,是否存在paramkey键paramvalue值returntrue存在false不存在publicbooleansHasKey(Stringkey,Objectvalue){try{returnredisTemplate。opsForSet()。isMember(key,value);}catch(Exceptione){e。printStackTrace();returnfalse;}}将数据放入set缓存paramkey键paramvalues值可以是多个return成功个数publiclongsSet(Stringkey,Object。。。values){try{returnredisTemplate。opsForSet()。add(key,values);}catch(Exceptione){e。printStackTrace();return0;}}将set数据放入缓存paramkey键paramtime时间(秒)paramvalues值可以是多个return成功个数publiclongsSetAndTime(Stringkey,longtime,Object。。。values){try{LongcountredisTemplate。opsForSet()。add(key,values);if(time0)expire(key,time);returncount;}catch(Exceptione){e。printStackTrace();return0;}}获取set缓存的长度paramkey键returnpubliclongsGetSetSize(Stringkey){try{returnredisTemplate。opsForSet()。size(key);}catch(Exceptione){e。printStackTrace();return0;}}移除值为value的paramkey键paramvalues值可以是多个return移除的个数publiclongsetRemove(Stringkey,Object。。。values){try{LongcountredisTemplate。opsForSet()。remove(key,values);returncount;}catch(Exceptione){e。printStackTrace();return0;}}list获取list缓存的内容paramkey键paramstart开始paramend结束0到1代表所有值returnpublicListObjectlGet(Stringkey,longstart,longend){try{returnredisTemplate。opsForList()。range(key,start,end);}catch(Exceptione){e。printStackTrace();returnnull;}}获取list缓存的长度paramkey键returnpubliclonglGetListSize(Stringkey){try{returnredisTemplate。opsForList()。size(key);}catch(Exceptione){e。printStackTrace();return0;}}通过索引获取list中的值paramkey键paramindex索引index0时,0表头,1第二个元素,依次类推;index0时,1,表尾,2倒数第二个元素,依次类推returnpublicObjectlGetIndex(Stringkey,longindex){try{returnredisTemplate。opsForList()。index(key,index);}catch(Exceptione){e。printStackTrace();returnnull;}}将list放入缓存paramkey键paramvalue值returnpublicbooleanlSet(Stringkey,Objectvalue){try{redisTemplate。opsForList()。rightPush(key,value);returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}将list放入缓存paramkey键paramvalue值paramtime时间(秒)returnpublicbooleanlSet(Stringkey,Objectvalue,longtime){try{redisTemplate。opsForList()。rightPush(key,value);if(time0)expire(key,time);returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}将list放入缓存paramkey键paramvalue值returnpublicbooleanlSet(Stringkey,ListObjectvalue){try{redisTemplate。opsForList()。rightPushAll(key,value);returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}将list放入缓存paramkey键paramvalue值paramtime时间(秒)returnpublicbooleanlSet(Stringkey,ListObjectvalue,longtime){try{redisTemplate。opsForList()。rightPushAll(key,value);if(time0)expire(key,time);returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}根据索引修改list中的某条数据paramkey键paramindex索引paramvalue值returnpublicbooleanlUpdateIndex(Stringkey,longindex,Objectvalue){try{redisTemplate。opsForList()。set(key,index,value);returntrue;}catch(Exceptione){e。printStackTrace();returnfalse;}}移除N个值为valueparamkey键paramcount移除多少个paramvalue值return移除的个数publiclonglRemove(Stringkey,longcount,Objectvalue){try{LongremoveredisTemplate。opsForList()。remove(key,count,value);returnremove;}catch(Exceptione){e。printStackTrace();return0;}}} 收藏等于学会,多多支持我吧!长期稳定输出优质系列文章!!!