SpringBoot整合Redis案例分析

SpringBoot整合Redis案例分析

这篇文章主要介绍了SpringBoot整合Redis案例分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringBoot整合Redis案例分析文章都会有所收获,下面我们一起来看看吧。

Springboot整合Redis

如果没有Redis,就先去下载

  • 下载路径cmd,然后redis-server.exe redis.windows.conf命令既可以启动服

  • 启动服务后,后面的才可以进行整合

  • 在redis目录下点击redis-cli.exe进行测试结果查看,基本操作如下

    • key * :查看存储内容

    • flushdb :清空数据库

如果redis不熟悉去看

undefined

SpringData也是和SpringBoot齐名的项目!

说明:在SpringBoot2.x之后,原来使用的jedis被替换为了lettuce

jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用jedis pool连接池!【类似于BIO:同步阻塞IO】

lettuce:采用netty【异步请求,性能更高点】,实例可以再多个线程中进行共享,不存在线程不安全的情况!可以减少线程数量了【类似于NIO:同步非阻塞IO】

  • 异步请求一般都需要序列化

源码分析:

  • 源码位置:

@Bean//当这个Bean不存在的时候,这个类就生效//这就说明,我们可以自己定义一个redisTemplate来替换这个默认的!@ConditionalOnMissingBean(name="redisTemplate")@ConditionalOnSingleCandidate(RedisConnectionFactory.class)publicRedisTemplate<Object,Object>redisTemplate(RedisConnectionFactoryredisConnectionFactory){//默认的RedisTemplate没有过多的设置,redis,对象都是需要序列化的!//两个泛型都是Object类型,我们后面使用需要强制转换:我们需要的类型<String,Object>RedisTemplate<Object,Object>template=newRedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);returntemplate;}@Bean@ConditionalOnMissingBean//由于String是Redis最常用的类型,所以说单独提出来了一个Bean@ConditionalOnSingleCandidate(RedisConnectionFactory.class)publicStringRedisTemplatestringRedisTemplate(RedisConnectionFactoryredisConnectionFactory){StringRedisTemplatetemplate=newStringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);returntemplate;}

上手测试【默认的RedisTemplate了解】

1.导入依赖

<!--操作redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--上面redis不兼容时候,可以换成jedis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>

2.配置连接

#SpringBoot所有的配置类,都有一个自动配置类RedisAutoConfiguration#自动配置类都会绑定一个properties配置文件RedisPropertiesspring:redis:host:127.0.0.1#Redis服务器连接端口port:6379#Redis数据库索引(默认为0)database:0#Redis服务器连接密码(默认为空)password:#连接池最大连接数(使用负值表示没有限制)pool:max-active:200#连接池最大阻塞等待时间(使用负值表示没有限制)max-wait:-1#连接池中的最大空闲连接max-idle:10#连接池中的最小空闲连接min-idle:0#连接超时时间(毫秒)timeout:1000

3.测试

  • 实际开发中我们都不会用这种原生的方式来编写代码

  • 一般我们会将这些常用的操作编写成工具类:redisUtils【后面就会有】

    • 前面还有jdbcUtils和MybatisUtils等

@SpringBootTestclassRedis03SpringbootApplicationTests{//注入RedisAutoConfiguration里面配置的类@AutowiredpublicRedisTemplateredisTemplate;@TestvoidcontextLoads(){//redisTemplate:操作我们的数据库,api和我们的是一样的//opsForValue:操作字符串类似String//opsForList:操作List//除了基本的操作,我们常用的方法都可以直接通过redisTemplate进行操作//比如事务和基本的CRUD//获取redis的连接对象,就可以操作数据库的连接了【一般很少来用】/*RedisConnectionconnection=redisTemplate.getConnectionFactory().getConnection();connection.flushDb();connection.flushAll();*/redisTemplate.opsForValue().set("kami","g1x");System.out.println(redisTemplate.opsForValue().get("kami"));}}

4.结果

问题:写到中文的时候,springboot是正常的,但是从redis中的redis.cli.exe运行keys *会出来乱码

  • 解决方法:默认的RedisTemplate没有过多的设置,redis,对象都是需要序列化的!

  • 这是默认的序列化配置

  • 默认序列化方式是JDK序列化

6.这时候我们就需要自己来写配置类

  • 自己写了后,原来默认的RedisTemplate就会失效

  • 创建一个config

  • @ConfigurationpublicclassRedisConfig{//编写我们自己的RedisTemplate@BeanpublicRedisTemplate<String,Object>redisTemplate(RedisConnectionFactoryredisConnectionFactory){RedisTemplate<String,Object>template=newRedisTemplate<>();//这里面到底怎么配置看后面template.setConnectionFactory(redisConnectionFactory);returntemplate;}}


上手测试【自定义的RedisTemplate——实际一般使用】

1.先创建一个pojo,user

//将它变为组件,方便调用@Component@Data@AllArgsConstructor@NoArgsConstructorpublicclassUser{privateStringname;privateIntegerage;}

2.测试类写序列化json对象操作【这里默认的序列化是JDK序列化】

@Testpublicvoidtest()throwsJsonProcessingException{//真实开发中一般都使用json来传递对象,所以要序列化jsonUseruser=newUser("葛",3);//所以要序列化成json对象【变成了json字符串】StringjsonUser=newObjectMapper().writeValueAsString(user);redisTemplate.opsForValue().set("user",jsonUser);System.out.println(redisTemplate.opsForValue().get("user"));}

  • 如果不用上面的序列化json对象操作会报错!String jsonUser = new ObjectMapper().writeValueAsString(user);

  • 下面是关于对象的保存,但是一般都是用json对象

    • 解决方法:在实体类中序列化即可【在企业中,我们所有的pojo都会序列化!SpringBoot】

    • //将它变为组件,方便调用@Component@Data@AllArgsConstructor@NoArgsConstructorpublicclassUserimplementsSerializable{privateStringname;privateIntegerage;}


3.刚才测试的是默认的序列化(JDK),这时候我们自己写其他方式的序列化

  1. 创建一个config

  2. //这里面到底怎么配置看后面Jackson2JsonRedisSerializer<Object>objectJackson2JsonRedisSerializer=newJackson2JsonRedisSerializer<Object>();//配置具体的序列化template.setKeySerializer(objectJackson2JsonRedisSerializer);


    • 多种序列化方式

    1. 写法例子

  3. 自己写很费劲,用已经写好的例子即可

    连接中有不同地方,复制连接中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;importjava.rmi.UnknownHostException;/***@authorzhangzhixi*/@ConfigurationpublicclassRedisConfig{@Bean@SuppressWarnings("all")publicRedisTemplate<String,Object>redisTemplate(RedisConnectionFactoryredisConnectionFactory)throwsUnknownHostException{//自定义StringObjectRedisTemplate<String,Object>template=newRedisTemplate();template.setConnectionFactory(redisConnectionFactory);//Json序列化配置Jackson2JsonRedisSerializer<Object>objectJackson2JsonRedisSerializer=newJackson2JsonRedisSerializer<Object>(Object.class);//ObjectMapper转译ObjectMapperobjectMapper=newObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper);//String的序列化StringRedisSerializerstringRedisSerializer=newStringRedisSerializer();//key采用String的序列化方式template.setKeySerializer(stringRedisSerializer);//hash的key也采用String的序列化方式template.setHashKeySerializer(stringRedisSerializer);//value序列化方式采用jacksontemplate.setValueSerializer(objectJackson2JsonRedisSerializer);//hash的value采用jacksontemplate.setHashValueSerializer(objectJackson2JsonRedisSerializer);template.afterPropertiesSet();returntemplate;}}


    • 企业中直接拿去使用即可

  4. 编写工具类

    packagecom.kami.utils;/***@authorzhangzhixi*@date2021/3/123:33*/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;/***@authormxz*/@ComponentpublicfinalclassRedisUtil{@AutowiredprivateRedisTemplate<String,Object>redisTemplate;/***指定缓存失效时间**@paramkey键*@paramtime时间(秒)*@return*/publicbooleanexpire(Stringkey,longtime){try{if(time>0){redisTemplate.expire(key,time,TimeUnit.SECONDS);}returntrue;}catch(Exceptione){e.printStackTrace();returnfalse;}}/***根据key获取过期时间**@paramkey键(不能为Null)*@return时间(秒)返回0代表永久有效*/publiclonggetExpire(Stringkey){returnredisTemplate.getExpire(key,TimeUnit.SECONDS);}/***判断key是否存在**@paramkey键(不能为Null)*@returntrue存在false不存在*/publicbooleanhashKey(Stringkey){try{returnredisTemplate.hasKey(key);}catch(Exceptione){e.printStackTrace();returnfalse;}}/***删除缓存**@paramkey可以传一个值或多个*/publicvoiddel(String...key){if(key!=null&&key.length>0){redisTemplate.delete(key[0]);}else{redisTemplate.delete(CollectionUtils.arrayToList(key));}}//==================================String====================================/***普通缓存获取**@paramkey键*@return值*/publicObjectget(Stringkey){returnkey==null?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(time>0){redisTemplate.opsForValue().set(key,value,time,TimeUnit.SECONDS);}else{set(key,value);}returntrue;}catch(Exceptione){e.printStackTrace();returnfalse;}}/***递增**@paramkey键*@paramdelta要增加几(大于0)*@return*/publiclongincr(Stringkey,longdelta){if(delta<0){thrownewRuntimeException("递增因子必须大于0");}returnredisTemplate.opsForValue().increment(key,delta);}/***递减**@paramkey键*@paramdelta要减少几(小于0)*@return*/publiclongdecr(Stringkey,longdelta){if(delta<0){thrownewRuntimeException("递减因子必须大于0");}returnredisTemplate.opsForValue().decrement(key,delta);}//================================Map=================================/***HashGet**@paramkey键不能为null*@paramitem项不能为null*/publicObjecthget(Stringkey,Stringitem){returnredisTemplate.opsForHash().get(key,item);}/***获取hashKey对应的所有键值**@paramkey键*@return对应的多个键值*/publicMap<Object,Object>hmget(Stringkey){returnredisTemplate.opsForHash().entries(key);}/***HashSet**@paramkey键*@parammap对应多个键值*/publicbooleanhmset(Stringkey,Map<String,Object>map){try{redisTemplate.opsForHash().putAll(key,map);returntrue;}catch(Exceptione){e.printStackTrace();returnfalse;}}/***HashSet并设置时间**@paramkey键*@parammap对应多个键值*@paramtime时间(秒)*@returntrue成功false失败*/publicbooleanhmset(Stringkey,Map<String,Object>map,longtime){try{redisTemplate.opsForHash().putAll(key,map);if(time>0){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(time>0){expire(key,time);}returntrue;}catch(Exceptione){e.printStackTrace();returnfalse;}}/***删除hash表中的值**@paramkey键不能为null*@paramitem项可以使多个不能为null*/publicvoidhdel(Stringkey,Object...item){redisTemplate.opsForHash().delete(key,item);}/***判断hash表中是否有该项的值**@paramkey键不能为null*@paramitem项不能为null*@returntrue存在false不存在*/publicbooleanhHasKey(Stringkey,Stringitem){returnredisTemplate.opsForHash().hasKey(key,item);}/***hash递增如果不存在,就会创建一个并把新增后的值返回**@paramkey键*@paramitem项*@paramby要增加几(大于0)*/publicdoublehincr(Stringkey,Stringitem,doubleby){returnredisTemplate.opsForHash().increment(key,item,by);}/***hash递减**@paramkey键*@paramitem项*@paramby要减少记(小于0)*/publicdoublehdecr(Stringkey,Stringitem,doubleby){returnredisTemplate.opsForHash().increment(key,item,-by);}//============================set=============================/***根据key获取Set中的所有值**@paramkey键*/publicSet<Object>sGet(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{Longcount=redisTemplate.opsForSet().add(key,values);if(time>0){expire(key,time);}returncount;}catch(Exceptione){e.printStackTrace();return0;}}/***获取set缓存的长度**@paramkey键*/publiclongsGetSetSize(Stringkey){try{returnredisTemplate.opsForSet().size(key);}catch(Exceptione){e.printStackTrace();return0;}}/***移除值为value的**@paramkey键*@paramvalues值可以是多个*@return移除的个数*/publiclongsetRemove(Stringkey,Object...values){try{Longcount=redisTemplate.opsForSet().remove(key,values);returncount;}catch(Exceptione){e.printStackTrace();return0;}}//===============================list=================================/***获取list缓存的内容**@paramkey键*@paramstart开始*@paramend结束0到-1代表所有值*/publicList<Object>lGet(Stringkey,longstart,longend){try{returnredisTemplate.opsForList().range(key,start,end);}catch(Exceptione){e.printStackTrace();returnnull;}}/***获取list缓存的长度**@paramkey键*/publiclonglGetListSize(Stringkey){try{returnredisTemplate.opsForList().size(key);}catch(Exceptione){e.printStackTrace();return0;}}/***通过索引获取list中的值**@paramkey键*@paramindex索引index>=0时,0表头,1第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推*/publicObjectlGetIndex(Stringkey,longindex){try{returnredisTemplate.opsForList().index(key,index);}catch(Exceptione){e.printStackTrace();returnnull;}}/***将list放入缓存**@paramkey键*@paramvalue值*/publicbooleanlSet(Stringkey,Objectvalue){try{redisTemplate.opsForList().rightPush(key,value);returntrue;}catch(Exceptione){e.printStackTrace();returnfalse;}}/***将list放入缓存**@paramkey键*@paramvalue值*@paramtime时间(秒)*/publicbooleanlSet(Stringkey,Objectvalue,longtime){try{redisTemplate.opsForList().rightPush(key,value);if(time>0){expire(key,time);}returntrue;}catch(Exceptione){e.printStackTrace();returnfalse;}}/***将list放入缓存**@paramkey键*@paramvalue值*@return*/publicbooleanlSet(Stringkey,List<Object>value){try{redisTemplate.opsForList().rightPushAll(key,value);returntrue;}catch(Exceptione){e.printStackTrace();returnfalse;}}/***将list放入缓存**@paramkey键*@paramvalue值*@paramtime时间(秒)*@return*/publicbooleanlSet(Stringkey,List<Object>value,longtime){try{redisTemplate.opsForList().rightPushAll(key,value);if(time>0){expire(key,time);}returntrue;}catch(Exceptione){e.printStackTrace();returnfalse;}}/***根据索引修改list中的某条数据**@paramkey键*@paramindex索引*@paramvalue值*@return*/publicbooleanlUpdateIndex(Stringkey,longindex,Objectvalue){try{redisTemplate.opsForList().set(key,index,value);returntrue;}catch(Exceptione){e.printStackTrace();returnfalse;}}/***移除N个值为value**@paramkey键*@paramcount移除多少个*@paramvalue值*@return移除的个数*/publiclonglRemove(Stringkey,longcount,Objectvalue){try{Longremove=redisTemplate.opsForList().remove(key,count,value);returnremove;}catch(Exceptione){e.printStackTrace();return0;}}//===============================HyperLogLog=================================publiclongpfadd(Stringkey,Stringvalue){returnredisTemplate.opsForHyperLogLog().add(key,value);}publiclongpfcount(Stringkey){returnredisTemplate.opsForHyperLogLog().size(key);}publicvoidpfremove(Stringkey){redisTemplate.opsForHyperLogLog().delete(key);}publicvoidpfmerge(Stringkey1,Stringkey2){redisTemplate.opsForHyperLogLog().union(key1,key2);}}


    • 我们真实的分发中,或者在你们的公司,一般都可以看到一个公司自己封装RedisUtil

  5. 转到测试类

    @SpringBootTestclassRedis02SpringbootApplicationTests{@Autowired//指定我们自己定义的redis序列化配置privateRedisTemplate<String,Object>redisTemplate;@AutowiredprivateRedisUtilredisUtil;@Testvoidtest1(){//清空数据库redisTemplate.getConnectionFactory().getConnection().flushDb();Useruser=newUser("zhangsha",23);redisUtil.set("user",user);System.out.println(redisUtil.get("user"));}}


    • 这时候注入的RedisTemplate需要导入的是我们的

  6. 结果就是输出前加了转译【不再是乱码】

    1. redis目录中的redis-cle.exe

    2. 执行结果

关于“SpringBoot整合Redis案例分析”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“SpringBoot整合Redis案例分析”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注恰卡编程网行业资讯频道。

发布于 2022-03-29 22:28:29
收藏
分享
海报
0 条评论
30
上一篇:redis使用实例分析 下一篇:springboot整合linux上的redis时报错怎么解决
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码