快速入门
导入依赖
<!--jedis--><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version></dependency><!--单元测试--><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.7.0</version><scope>test</scope></dependency>
测试代码
package com.example;import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;public class JedisTest {private Jedis jedis;@BeforeEachvoid setUp() {jedis = new Jedis("192.168.168.168", 6379);jedis.auth("123456");jedis.select(0);}@Testvoid test() {String name = jedis.get("name");System.out.println(name);}@AfterEachvoid tearDown() {if(jedis != null){jedis.close();}}
}
jedis连接池
Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此推荐大家使用Jedis连接池代替Jedis的直连方式。
package com.example.utils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;public class JedisConnectionFactory {private static JedisPool jedisPool;//在类加载时执行static {JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxTotal(8);//最大连接数poolConfig.setMaxIdle(8);//最大空闲连接数poolConfig.setMinIdle(0);//最小空闲连接数poolConfig.setMaxWaitMillis(1000);//最大等待时间 (单位:毫秒)jedisPool = new JedisPool(poolConfig, "192.168.168.168", 6379, 1000, "123456");}//连接超时时间 1000毫秒public static Jedis getJedis() {return jedisPool.getResource();}
}
修改后这样获取jedis对象
@BeforeEachvoid setUp() {jedis = JedisConnectionFactory.getJedis();jedis.auth("123456");jedis.select(0);}
SpringDataRedis
SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis,官网地址:Spring Data Redis
- 提供了对不同Redis客户端的整合(Lettuce和Jedis)
- 提供了RedisTemplate统一API来操作Redis
- 支持Redis的发布订阅模型
- 支持Redis哨兵和Redis集群
- 支持基于Lettuce的响应式编程
- 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
- 支持基于Redis的JDKCollection实现
快速入门
导入依赖
<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>
配置redis
spring:data:redis:host: 192.168.168.168port: 6379password: 123456database: 0lettuce:pool:max-active: 8max-idle: 8min-idle: 0max-wait: 100ms
测试
package com.example;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;@SpringBootTest
public class RedisTemplateTest {@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void test01() {redisTemplate.opsForValue().set("name","lihua");System.out.println(redisTemplate.opsForValue().get("name"));}
}
自定义序列化
jdk序列化(默认的序列化方式)的问题
进行如上测试后,发现并没有修改key为name的值为lihua,而是出现了这样的结果
原因如下
RedisTemplate可以接收任意Object作为值写入Redis:
只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:
缺点:
- 可读性差
- 内存占用较大
***************************************************
自定义序列化方式为json序列化
首先写一个RedisTemplate的配置
package com.example.config;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.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;@Configuration
public class RedisTemplateConfig {@Bean//RedisConnectionFactory是spring内置的,在项目启动时会自动装配,因此作为参数传入即可public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {//创建RedisTemplate对象RedisTemplate<String, Object> template = new RedisTemplate<>();//设置连接工厂template.setConnectionFactory(factory);//创建JSON序列化工具GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();//设置key的序列化 RedisSerializer是redis的一个序列化器template.setKeySerializer(RedisSerializer.string());template.setHashKeySerializer(RedisSerializer.string());//设置value的序列化template.setValueSerializer(jsonRedisSerializer);template.setHashValueSerializer(jsonRedisSerializer);//返回return template;}
}
在springboot项目启动时,这个bean就会被加载
重新测试
@Testpublic void test01() {redisTemplate.opsForValue().set("name","zhaosi");System.out.println(redisTemplate.opsForValue().get("name"));}
测试结果如下
符合我们的预期
*********************************
也可以存入自定义对象
@Testpublic void test02() {User u1 = new User(1, "laoda", 24);redisTemplate.opsForValue().set("user:001", u1);}@Testpublic void test03() {User user = (User) redisTemplate.opsForValue().get("user:001");System.out.println(user);}
测试结果如下
整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。 (我们将用StringRedisTemplate进行改进)
SpringRedisTemplate
为了节省内存空间,我们可以不使用JSON序列化器来处理value,而是统一使用String序列化器(这样value就不用存储对象的字节码文件了),要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。
因为存入和读取时的序列化及反序列化都是我们自己实现的,SpringDataRedis就不会将class信息写入Redis了。
这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式。
导入jackson依赖
<!--Jackson依赖--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency>
省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用就好了
@SpringBootTest
public class StringRedisTemplateTest {@Autowiredprivate StringRedisTemplate stringRedisTemplate;private static final ObjectMapper mapper = new ObjectMapper();@Testpublic void test() throws JsonProcessingException {User u1 = new User(2, "赵四", 25);//手动序列化String json = mapper.writeValueAsString(u1);System.out.println("序列化后的json字符串:"+json);//写入数据stringRedisTemplate.opsForValue().set("user:002",json);//获取数据String jsonUser = stringRedisTemplate.opsForValue().get("user:002");//反序列化User user = mapper.readValue(jsonUser, User.class);System.out.println("反序列化得到的结果:"+user);}
}
可以看到,里面是没有对象的字节码的