JedisConnectionFactory如何获取Redis,jedisconnectionfactory配置(Redis之RedisTemplate的序列化方式深入解读)
关于【JedisConnectionFactory如何获取Redis】,jedisconnectionfactory配置,今天犇涌小编给您分享一下,如果对您有所帮助别忘了关注本站哦。
1、Redis之RedisTemplate的序列化方式深入解读
概述
使用Spring提供的Spring Data Redis操作redis必然要使用Spring提供的模板类RedisTemplate,使用RedisTemplate离不开Redis的序列化方式,今天通过本篇文章主要讲解Redis序列化的那些坑。
RedisTemplate
可以看到4个序列化相关的属性 ,主要是用于KEY和VALUE的序列化,比如说我们经常会将POJO对象存储到Redis中,一般情况下会使用JSON方式序列化成字符串存储到Redis中 。
Spring提供的Redis数据结构的操作类
- ValueOperations 类,提供 Redis String API 操作
- ListOperations 类,提供 Redis List API 操作
- SetOperations 类,提供 Redis Set API 操作
- ZSetOperations 类,提供 Redis ZSet(Sorted Set) API 操作
- GeoOperations 类,提供 Redis Geo API 操作
- HyperLogLogOperations 类,提供 Redis HyperLogLog API 操作
StringRedisTemplate
RedisTemplate支持泛型,StringRedisTemplate K/V 均为String类型。
org.springframework.data.redis.core.StringRedisTemplate继承RedisTemplate类,使用org.springframework.data.redis.serializer.StringRedisSerializer字符串序列化方式。
RedisSerializer序列化接口
RedisSerializer接口是Redis序列化接口,用于Redis KEY和VALUE的序列化。
RedisSerializer接口的实现类如下:
默认Redis提供了11中的序列化方式,归类一下主要分为:
- JDK序列化方式(默认)
- String序列化方式
- JSON序列化方式
- XML序列化方式
JDK序列化方式(默认)
org.springframework.data.redis.serializer.JdkSerializationRedisSerializer,默认不配置的情况RedisTemplate采用的是该数据序列化方式,可以查看一下源码:
Spring Boot自动化配置RedisTemplate Bean对象时,就未设置默认的序列化方式。绝大多数情况下,并不推荐使用JdkSerializationRedisSerializer进行序列化。主要是不方便人工排查数据。我们来做个测试:
运行单元测试:
发现key跟value的值都是16进制字符串,可以看到key跟value实际上保存的都是以byte[]字节数组的格式存储:
key被序列化成这样,线上通过key去查询对应的value非常不方便,所以key肯定是不能被这样序列化的。value被序列化成这样,除了阅读可能困难一点,不支持跨语言外,实际上也没多大问题。不过,实际线上场景,还是使用JSON序列化居多。
String序列化方式
org.springframework.data.redis.serializer.StringRedisSerializer,字符串和二进制数组都直接转换:
默认的话,StringRedisTemplate的key和value采用的就是这种序列化方案。
JSON序列话方式
GenericJackson2JsonRedisSerializer
org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer 使用Jackson 实现JSON的序列化方式,Generic单词翻译过来表示:通用的意思,可以看出,是支持所有类。
RedisConfig配置
通过配置方式选择对应Redis数据的序列化方式,配置如下:
package com.example.jedisserializefrombytestojson.config;import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;/** * Redis配置 * * @author: jacklin * @date: 2022/9/9 0:07 */@Configurationpublic class RedisConfig { //GenericJackson2JsonRedisSerializer @Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){ RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); //String的序列化方式 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // 使用GenericJackson2JsonRedisSerializer 替换默认序列化(默认采用的是JDK序列化) GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(); //key序列化方式采用String类型 template.setKeySerializer(stringRedisSerializer); //value序列化方式采用jackson类型 template.setValueSerializer(genericJackson2JsonRedisSerializer); //hash的key序列化方式也是采用String类型 template.setHashKeySerializer(stringRedisSerializer); //hash的value也是采用jackson类型 template.setHashValueSerializer(genericJackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } ////Jackson2JsonRedisSerializer //@Bean //@ConditionalOnMissingBean(name = "redisTemplate") //public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { // RedisTemplate<String, Object> template = new RedisTemplate<>(); // template.setConnectionFactory(factory); // // //String的序列化方式 // StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // // 使用Jackson2JsonRedisSerialize 替换默认序列化(默认采用的是JDK序列化) // Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); // // //key序列化方式采用String类型 // template.setKeySerializer(stringRedisSerializer); // //value序列化方式采用jackson类型 // template.setValueSerializer(jackson2JsonRedisSerializer); // //hash的key序列化方式也是采用String类型 // template.setHashKeySerializer(stringRedisSerializer); // //hash的value也是采用jackson类型 // template.setHashValueSerializer(jackson2JsonRedisSerializer); // template.afterPropertiesSet(); // return template; //} // ////FastJsonRedisSerializer //@Bean("redisTemplate") //public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){ // RedisTemplate<String, Object> template = new RedisTemplate<>(); // template.setConnectionFactory(factory); // // //String序列化方式 // StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // // 使用FastJsonRedisSerializer替换默认序列化(默认采用的是JDK序列化) // FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); // // //key序列化方式采用String类型 // template.setKeySerializer(stringRedisSerializer); // //value序列化方式采用jackson类型 // template.setValueSerializer(fastJsonRedisSerializer); // //hash的key序列化方式也是采用String类型 // template.setHashKeySerializer(stringRedisSerializer); // //hash的value也是采用jackson类型 // template.setHashValueSerializer(fastJsonRedisSerializer); // template.afterPropertiesSet(); // return template; //}}复制代码
运行以下测试类:
@Testvoid redisTemplateSerializeTest() { String redisTemplateStringKey = "redisTemplateStringKey"; String redisTemplateUserObjectKey = "redisTemplateUserObjectKey"; String redisTemplateUserArrayObjectKey = "redisTemplateUserArrayObjectKey"; String redisTemplateJSONObjectKey = "redisTemplateJSONObjectKey"; String redisTemplateJSONArrayKey = "redisTemplateJSONArrayKey"; //序列化String类型和反序列化String类型 redisTemplate.opsForValue().set(redisTemplateStringKey, "austin"); String austin = (String) redisTemplate.opsForValue().get(redisTemplateStringKey); System.out.println("stringGet: " + austin); //序列化Object对象类型和反序列化Object对象类型 (User对象) User user = new User("123", "austin", 25); redisTemplate.opsForValue().set(redisTemplateUserObjectKey, user); User userGet = (User) redisTemplate.opsForValue().get(redisTemplateUserObjectKey); System.out.println("userGet: " + userGet); //序列化Object对象数组类型和反序列化Object对象数组类型 (User[]对象数组) User user1 = new User("1", "austin1", 25); User user2 = new User("2", "austin2", 25); User[] userArray = new User[]{user1, user2}; redisTemplate.opsForValue().set(redisTemplateUserArrayObjectKey, userArray); User[] userArrayGet = (User[]) redisTemplate.opsForValue().get(redisTemplateUserArrayObjectKey); System.out.println("userArrayGet: " + userArrayGet); //序列化JSONObject对象类型和反序列化JSONObject对象类型 JSONObject jsonObject = new JSONObject(); jsonObject.put("id", "123"); jsonObject.put("name", "austin"); jsonObject.put("age", 25); redisTemplate.opsForValue().set(redisTemplateJSONObjectKey, jsonObject); JSONObject jsonObjectGet = (JSONObject) redisTemplate.opsForValue().get(redisTemplateJSONObjectKey); System.out.println("jsonObjectGet: " + jsonObjectGet); //序列化JSONArray对象类型和反序列化JSONArray对象类型 JSONArray jsonArray = new JSONArray(); JSONObject jsonObject1 = new JSONObject(); jsonObject1.put("id", "1"); jsonObject1.put("name", "austin1"); jsonObject1.put("age", 25); JSONObject jsonObject2 = new JSONObject(); jsonObject2.put("id", "1"); jsonObject2.put("name", "austin2"); jsonObject2.put("age", 25); jsonArray.add(jsonObject1); jsonArray.add(jsonObject2); redisTemplate.opsForValue().set(redisTemplateJSONArrayKey, jsonArray); JSONArray jsonArrayGet = (JSONArray) redisTemplate.opsForValue().get(redisTemplateJSONArrayKey); System.out.println("jsonArrayGet: " + jsonArrayGet);}复制代码
观察redis数据的存储格式:
key- value:
- 字符串类型
Key: redisTemplateStringKeyValue: "austin"复制代码
- 对象类型
Key: redisTemplateUserObjectKeyValue:{ "@class": "com.example.jedisserializefrombytestojson.User", "id": "123", "name": "austin", "age": 25}复制代码
- 对象数组类型
Key: redisTemplateUserArrayObjectKeyValue: [ "[Lcom.example.jedisserializefrombytestojson.User;", [ { "@class": "com.example.jedisserializefrombytestojson.User", "id": "1", "name": "austin1", "age": 25 }, { "@class": "com.example.jedisserializefrombytestojson.User", "id": "2", "name": "austin2", "age": 25 } ]]复制代码
- JSONObject类型
Key: redisTemplateJSONObjectKeyValue:{ "@class": "com.alibaba.fastjson.JSONObject", "name": "austin", "id": "123", "age": 25}复制代码
- JSONArray类型
Key: redisTemplateJSONArrayKeyValue: [ "com.alibaba.fastjson.JSONArray", [ { "@class": "com.alibaba.fastjson.JSONObject", "name": "austin1", "id": "1", "age": 25 }, { "@class": "com.alibaba.fastjson.JSONObject", "name": "austin2", "id": "1", "age": 25 } ]]复制代码
运行redisTemplateSerializeTest测试类,结果发现该方式序列化和反序列化都没有问题,果然是通用性序列化方式:
我们来思考下,在将一个对象序列化成一个字符串,怎么保证字符串反序列化成对象的类型呢?Jackson通过 Default Typing,会在字符串多冗余一个类型,这样反序列化就知道具体的类型了。
从结果发现,使用GenericJackson2JsonRedisSerializer序列化方式,String类型、对象、对象数组、JSONObject、JSONArray序列化和反序列化都没有问题,value值序列化后多了@class属性,反序列化的对象的类型就可以从这里获取到。@class属性完美解决了反序列化后的对象类型,所以实际项目中,目前很多采用 GenericJackson2JsonRedisSerializer序列化方式。
Jackson2JsonRedisSerializer
org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
观察redis数据的存储格式:
key- value:
- 字符串类型
Key: redisTemplateStringKeyValue: "austin"复制代码
- 对象类型
Key: redisTemplateUserObjectKeyValue:{ "id": "123", "name": "austin", "age": 25}复制代码
与上面GenericJackson2JsonRedisSerializer序列化方式结果不同的是,value没有@class属性。
- 对象数组类型
Key: redisTemplateUserArrayObjectKeyValue: [ { "id": "1", "name": "austin1", "age": 25 }, { "id": "2", "name": "austin2", "age": 25 }]复制代码
与上面GenericJackson2JsonRedisSerializer序列化方式结果不同的是,value没有"@class": "com.example.jedisserializefrombytestojson.User" 对象类型属性。
- JSONObject类型
Key: redisTemplateJSONObjectKeyValue:{ "name": "austin", "id": "123", "age": 25}复制代码
与上面GenericJackson2JsonRedisSerializer序列化方式结果不同的是,value没有"@class": "com.alibaba.fastjson.JSONObject"属性。
- JSONArray类型
Key: redisTemplateJSONArrayKeyValue: [ { "name": "austin1", "id": "1", "age": 25 }, { "name": "austin2", "id": "1", "age": 25 }]复制代码
与上面GenericJackson2JsonRedisSerializer序列化方式结果不同的是,value没有 "com.alibaba.fastjson.JSONArray" 对象类型属性。
Jackson2JsonRedisSerializer与GenericJackson2JsonRedisSerializer序列化结果不同的是,前者并没有@class或者@type类型属性,这种序列化方式可能会导致获取redis数据反序列化成POJO对象时候出错,导致反序列化失败,所以一般也很少使用该方式。
比如在对象强制转换的情况,会报错:
报错信息很明显,不能直接将JSONObject对象强制转换成User对象,不能通过方式获取转换:
//该方式强转会报错User userGet = (User) redisTemplate.opsForValue().get(redisTemplateUserObjectKey);复制代码
而正确的方式应该是:
2、JedisConnectionFactory如何获取Redis
Spring对Redis的支持是通过Spring Data Redis实现的,JedisConnectionFactory为我们提供了Redis的一种Java客户端Jedis。本文主要为大家介绍使用工厂类获取Jedis的两种方式,以及使用过程中存在的问题,希望能为大家提供一些思路。
工具/材料
IntelliJ IDEA
操作方法
首先我们需要编辑Spring的配置文件application.properties,添加Redis的相关配置,这些配置在代码中需要注入,用来生成JedisConnectionFactory的Bean。
接下来我们写一个配置类,该配置类上需要添加@Configuration注解,我们在这个类中通过@Value注解注入application.properties配置文件中的部分需要的属性,其中{}用于接收属性值,在属性名冒号后面的值是默认值,若读取不到该属性则使用默认值。我们在该类中创建JedisConnectionFactory的Bean,在这个Bean中设置读取到的属性值。
接下来我们创建一个RedisServer的类,主要用于获取Redis以及实现部分Redis操作的方法。在该类中我们可以使用@Autowired注解注入JedisConnectionFactory的Bean。下图中获取Redis客户端Jedis的方法是我们推荐的方法,使用该方法我们既获取到了Jedis实例又使用的连接池,将Jedis实例交由连接池管理,不用太担心并发操作导致的Redis不可用的情况。最后再附上Jedis操作存储和获取数据的方法。
另外,我们还有再介绍一种并不推荐的写法,如下图所示。这种方法每次都创建一个新的Redis连接并且没有关闭连接,在大量并发操作时会带来性能上的开销,由于对连接数没有限制,可能会耗尽Redis的连接,导致Redis连接报错。
配置完成后我们来测试一下Jedis是否能正常使用,创建一个RedisController类,在该类中注入JedisServer,使用JedisServer提供的存储和读取方法,然后启动服务。
服务启动后我们在postman中进行测试,首先调用setRedis请求将数据存入Redis中,然后再调用getRedis请求获取数据,如下图所示。
JedisConnectionFactory在Spring Data Redis 2.0后就不再推荐上述这种配置方式了,当我们的spring-boot-starter-parent版本设置为2.x时,我们可以看到代码中的设置已经被废弃了。
Spring Data Redis 2.0推荐使用Standalone、Sentinel、RedisCluster这三种模式的环境配置类,以便于更加灵活的适配更多的业务场景,我们一般自己测试Redis通常使用的都是单机版的,那么以单机版为例,JedisConnectionFactory的配置应写为如下的方式。
特别提示
本文只是介绍了一种Redis客户端的使用方式,还是推荐大家使用spring-boot集成Redis做开发,因为spring-boot开箱即用的特性可以大大减少开发工作量。
本文关键词:jedisconnectionfactory配置,jedisconnectionfactory redis集群。这就是关于《JedisConnectionFactory如何获取Redis,jedisconnectionfactory配置(Redis之RedisTemplate的序列化方式深入解读)》的所有内容,希望对您能有所帮助!更多的知识请继续关注《犇涌向乾》百科知识网站:http://www.029ztxx.com!
版权声明: 本站仅提供信息存储空间服务,旨在传递更多信息,不拥有所有权,不承担相关法律责任,不代表本网赞同其观点和对其真实性负责。如因作品内容、版权和其它问题需要同本网联系的,请发送邮件至 举报,一经查实,本站将立刻删除。