个人Blog:dykang.top
Redis的Java 客户端
Jedis
引入依赖
<dependencies>
<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>
</dependency>
</dependencies>
使用
private Jedis jedis;
//建立连接
@BeforeEach
void setUp(){
jedis = new Jedis("localhost", 6379);
jedis.select(0);
}
//存数据取数据
@Test
public void testString(){
String se = jedis.set("k", "19");
System.out.println("se = " + se);
String s = jedis.get("k");
System.out.println("s = " + s);
}
//关闭连接
@AfterEach
void closeCon(){
if (jedis!=null)
{
jedis.close();
}
}
Jedis的连接池
private static final JedisPool jedisPool;
static {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
//最大连接数
jedisPoolConfig.setMaxTotal(8);
//最大空闲数 可以预备8个空闲连接,直接使用
jedisPoolConfig.setMaxIdle(8);
//最小空闲数
jedisPoolConfig.setMinIdle(0);
//最大等待时间 没有可用的jedis连接,等待这些时间之后就会报错
jedisPoolConfig.setMaxWaitMillis(1000);
jedisPool = new JedisPool(jedisPoolConfig,"localhost",6379);
}
//获取
public static Jedis getJedis(){
Jedis jedis = jedisPool.getResource();
return jedis;
}
利用连接池对象创建jedis,不需要关闭jedis资源,底层代码会自动将jedis连接放回连接池
public void close() {
if (this.dataSource != null) {
JedisPoolAbstract pool = this.dataSource;
this.dataSource = null;
if (this.isBroken()) {
pool.returnBrokenResource(this);
} else {
pool.returnResource(this);
}
} else {
super.close();
}
}
SpringDataRedis
介绍
特征:
封装的API
入门
引入依赖
<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>
commons-pool2 jedis 和lettuce底层都是pool连接池,所以需要引入连接池的依赖
配置yml
spring:
redis:
host: localhost
database: 0
port: 6379
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: 1000ms
使用lettuce连接池,因为redis起步依赖引入的是lettuce依赖
注入RedisTemplate
@Autowired
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
redisTemplate.opsForValue().set("name","虎哥");
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
RedisSerializer
key推荐使用string类型
value推荐使用Json类型
/**
* Redis序列化配置
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory){
//创建RedisTemplate对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
//设置连接工厂
template.setConnectionFactory(connectionFactory);
//创建Json序列化工具
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
//设置Key的序列化
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
//设置Value的序列化
template.setValueSerializer(genericJackson2JsonRedisSerializer);
template.setHashValueSerializer(genericJackson2JsonRedisSerializer);
return template;
}
}
有时候会需要加这个依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializer有什么区别?
-
泛型支持:
-
GenericJackson2JsonRedisSerializer
支持泛型,可以在序列化时保留对象的实际类型信息。这对于处理复杂的对象结构很有用,因为它可以确保在反序列化时正确地还原对象的类型。这个特性对于存储和检索具有继承关系的对象非常有用。(通过反射) -
Jackson2JsonRedisSerializer
不支持泛型,它在反序列化时会将对象都转换为指定的目标类,因此在处理继承关系的对象时可能会失去类型信息。
-
-
默认构造函数:
-
GenericJackson2JsonRedisSerializer
需要提供要序列化和反序列化的类的引用作为构造函数的参数,因为它要确保能够正确地处理泛型类型。(必须加get set 无参有参构造方法) -
Jackson2JsonRedisSerializer
则可以使用默认构造函数,只需要设置目标类即可,因为它不处理泛型。
-
在选择使用哪个取决于你的需求。如果你的对象结构相对简单,而且不需要在反序列化时保留实际类型信息,那么Jackson2JsonRedisSerializer
可能足够了。如果你的对象结构更复杂,包含了继承关系,并且需要在反序列化时保留实际类型信息,那么 GenericJackson2JsonRedisSerializer
可能更适合。
序列化:对象到JSON
反序列化:JSON到对象
StringRedisTemplate
因为Json序列化器会将原先的数据类型(类的字节码)同时保存到了redis中,占用redis的空间。因此我们将手动序列化,然后手动完成反序列化,不让原先的数据类型保存到redis中去占用空间
@Autowired
private StringRedisTemplate stringRedisTemplate;
//Spring提供的Json序列化反序列化工具
private static final ObjectMapper objectMapper = new ObjectMapper();
@Test
void testSaveUser() throws JsonProcessingException {
User user = new User("kkk",19);
//手动序列化
String json = objectMapper.writeValueAsString(user);
//存入redis
stringRedisTemplate.opsForValue().set("user:info1",json);
String user1 = stringRedisTemplate.opsForValue().get("user:info1");
//手动反序列化成user对象
User user2 = objectMapper.readValue(user1, User.class);
System.out.println("user2 = " + user2);
}
操作Hash
@Test
void testHash(){
stringRedisTemplate.opsForHash().put("heima:200","name","kzy");
stringRedisTemplate.opsForHash().put("heima:200","age",19);
Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("heima:200");
System.out.println("entries = " + entries);
}