一、常见的几种 Java 客户端
- Jedis:以 Redis 命令作为方法的名称,便于学习,简单实用,但其实例是线程不安全的,多线程下需要基于连接池来使用。
- lettce:基于 Netty 实现,支持同步、异步和响应式编程方式,并且线程是安全的,支持 Redis 的多种模式。
- Redisson:是一个基于 Redis 实现的分布式、可伸缩的 Java 数据结构集合。
我们在之后会学习 Jedis,以及 Spring 将 Jedis 和 lettce 整合后的 Spring Data Redis。
二、Jedis
① 第一步,我们要先导入 Jedis 的对应依赖:
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version>
</dependency>
② 第二步,我们要创建 Jedis 的实例并设置对应参数:
//1.建立连接
jedis = new Jedis("127.0.0.1", 6379);
//2.设置密码
jedis.auth("123456");
//3.选择库
jedis.select(0);
③ 注意,在最后需要将连接关闭
//关闭连接
if (jedis != null) {jedis.close();
}
建立连接后,我们就可以根据我们之前在 Redis 中用到的方法名来快速上手,如操作 String 类型的键值对:
如上操作,直接调用 set 和 get 方法即可。
还如操作 hash 类型时:
也是只用调用对应名称的方法即。
● Jedis 连接池
前面说过,Jedis 是线程不安全的,所以我们需要建立连接池来确保线程的安全性。我们可以通过建立一个工具类来初始化连接池:
public class JedisConnectionFactory {//连接池对象private static final JedisPool jedisPool;static {//配置连接池JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxTotal(8);//最大连接数poolConfig.setMaxIdle(8);//最大空闲连接poolConfig.setMinIdle(0);//最小空闲连接poolConfig.setMaxWaitMillis(1000);//等待时长//创建连接池对象jedisPool = new JedisPool(poolConfig,"127.0.0.1", 6379, 1000, "123456");}public static Jedis getJedis(){return jedisPool.getResource();}
}
此处我们使用静态代码块进行初始化,是因为静态代码块会在类执行时加载,并且只会执行一次,确保了线程安全,同时减少了资源的复用。
之后我们在使用时,只需调用该工具类中的 getJedis( ) 方法即可获取到连接池。
//1.建立连接
jedis = JedisConnectionFactory.getJedis();
//2.设置密码
jedis.auth("123456");
//3.选择库
jedis.select(0);
其次,在我们最后关闭连接时,其 close( ) 方法底层会进行判断,若是连接池会将连接池进行归还,而并非销毁。
三、SpringDataRedis
SpringData 是 Spring 中数据操作的模块,包含对各种数据库的集成,其中对 Redis 额集成模块就是 SpringDataRedis。其封装了各种对 Redis 的操作,并且对不同数据类型的操作封装到了不同的类型。
① 第一步,引入依赖。因 springboot 已默认整合了 SpringDataRedis 。
<!-- 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>
② 配置 SpringDataRedis 的配置文件 application.yaml
spring:data:redis:host: 127.0.0.1port: 6379password: 123456jedis:pool:max-active: 8max-idle: 8min-idle: 0max-wait: 100ms
其中可以自己选择使用 jedis 或是 lettuce,但因其默认使用 lettuce 所以不用导 lettuce 的依赖,而 jedis 需要手动导入依赖。jedis 的连接池也只在配置后才会生效。
③ 注入 RedisTemplate
@Autowired
private RedisTemplate redisTemplate;
注入后调用其中方法可以看到将不同数据类型的操作进行了分离。
测试后可以正常输出获取的值,运行成功。
而其会将数据存为如下格式,这是因为其会将传入的内容作为对象进行序列化处理。
在底层存在 key、value、hashKey、hashValue 四种类型的序列化器。
且默认使用 jdk 的序列化器,导致出现了这种可读性差,占用空间大的问题。
所以我们需要改变这种序列化方式,修改 RedisTemplate 即可:
引入 jackson 的依赖:
<!-- jackson -->
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId>
</dependency>
注册一个配置类并声明一个 Bean 如下进行配置:
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){//1.创建RedisTemplate对象RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();//2.设置连接工厂redisTemplate.setConnectionFactory(redisConnectionFactory);//3.创建Java序列化工具GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();//4.设置key的序列化器redisTemplate.setKeySerializer(genericJackson2JsonRedisSerializer);redisTemplate.setHashKeySerializer(genericJackson2JsonRedisSerializer);//5.设置value的序列化器redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);//6.返回对象return redisTemplate;}
}
将自动注入的 RedisTemplate 加上泛型后即可
再次运行后可以看到已经恢复了正常。
但在我们写入的是一个对象时,会将其自动序列化为一个 json 格式。但其将 User 类的字节码同样写入了进去,这样会占用额外的内存,浪费空间。
想要解决这个问题,我们只能统一的使用 String 序列化器,缺点是只能存储 String 类型的 key 和 value,想要存储对象只能手动的完成对象的序列化和反序列化
但 Spring 默认提供了一个 StringRedisTemplate 类,它的 key 和 value 的序列化方式默认就是 String 方式,所以我们可以直接使用它而不用再手动编写。
@Autowired
private StringRedisTemplate redisTemplate;
再次传入对象时,可以看到以及不会再出现问题。
【完】