一、springboot整合redis
如果redis连接不上可参考 https://blog.csdn.net/HBliucheng/article/details/112603127
1,pom引入ga坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
在spring2.x之后,原来使用的jedis被替换成了lettuce
jedis:采用直连,多个线程操作的话,是不安全的
lettuce:采用netty,实例可以在多个线程中进行共享,不存在线程不安全的情况
2,application.yml配置
连接超时时间可以自行设置
spring:
redis:
host: 192.168.119.3
port: 6379
# connect-timeout: 3000
3,注入redisTemplate,只用redisTemplate可以操作不同的数据类型,api和rendis命令一样的
redis常用命令可参考 https://blog.csdn.net/HBliucheng/article/details/111600127
opsForValue操作String类型
opsForList操作list类型
opsForSet操作set类型
opsForHash操作hash类型
opsForZset操作zset类型
opsForGeo操作geo类型
opsForHyperLogLog操作HyperLogLog类型
当然还有 StringRedisTemplate操作String类型
具体类和方法不做赘述,下面会提供redisUtils来操作redis。这是目前大部分公司的做法
二、redis序列化
1,redis为什么需要序列化
序列化最终的目的是为了对象可以跨平台存储,和进行网络传输。而我们进行跨平台存储和网络传输的方式就是IO,而我们的IO支持的数据格式就是字节数组
2,redis序列化方式对比
redis的默认方式是JdkSerializationRedisSerializer
JdkSerializationRedisSerializer: 使用JDK提供的序列化功能。
优点是反序列化时不需要提供类型信息(class),但缺点是需要实现Serializable接口,还有序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。
Jackson2JsonRedisSerializer: 使用Jackson库将对象序列化为JSON字符串。
优点是速度快,序列化后的字符串短小精悍,不需要实现Serializable接口。
但缺点也非常致命,那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象)。 通过查看源代码,发现其只在反序列化过程中用到了类型信息。
问题:使用默认的JDK序列化方式,在RDM工具中查看k-v值时会出现“乱码”,不方便查看
推荐使用 Jackson2JsonRedisSerializer
3,使用默认的序列化方式 JdkSerializationRedisSerializer
** 所有对象都需要序列化**
当对象不序列化时会报错
POJO类
package com.example.redisdemo.pojo;
import lombok.*;
import java.io.Serializable;
/**
* @author LiuCheng
* @data 2021/1/14 13:55
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
private String name;
private int age;
}
测试类,启动发现会报错
@Test
void test3(){
User user = new User("张三", 12);
redisTemplate.opsForValue().set("user",user);
System.out.println(redisTemplate.opsForValue().get("user"));
}
所以所有对象类存入redis时需要序列化,加上序列化后(实现 Serializable )再运行下test
package com.example.redisdemo.pojo;
import lombok.*;
import java.io.Serializable;
/**
* @author LiuCheng
* @data 2021/1/14 13:55
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User implements Serializable {
private String name;
private int age;
}
再次运行 ,正常运行,结果也能取出来
4,自定义序列化方式序列化 Jackson2JsonRedisSerializer。自定义redisTemplate*
package com.example.redisdemo.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @author LiuCheng
* @data 2021/1/14 14:25
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 老方法已过期舍弃
// objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
objectMapper.enable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key 采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
//hash 的key采用String 的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// hash 的value 采用jackson方式序列化
template.setHashValueSerializer(jackson2JsonRedisSerializer);
// value采用String的序列化方式
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
POJO类(未实现Serializable 接口)
package com.example.redisdemo.pojo;
import lombok.*;
import java.io.Serializable;
/**
* @author LiuCheng
* @data 2021/1/14 13:55
*/
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
private String name;
private int age;
}
测试类
此处有个小bug,在String类型中放入key后,后在Hash中放入相同的key会报错,只需要删除key后再次放入即可
https://blog.csdn.net/HBliucheng/article/details/112610780
@Test
void test3(){
User user = new User("张三", 12);
redisTemplate.opsForValue().set("user",user);
System.out.println(redisTemplate.opsForValue().get("user"));
// 移除key否则下面再次添加user时会报错
redisTemplate.delete("user");
redisTemplate.opsForHash().put("user","2",user);
System.out.println(redisTemplate.opsForHash().get("user", "2"));
}
运行结果
redisUtils工具类 https://blog.csdn.net/HBliucheng/article/details/112614392