目录
1.jedis
步骤一:导入对应的依赖
步骤二:测试
2.spring-date-redis 技术
步骤一:坐标
步骤二:application.properties中加入redis相关配置
步骤三:操作说明
注意:
1.两者数据各自存,各自取,数据不互通。 RedisTemplate不能取StringRedisTemplate存入的数据 StringRedisTemplate不能取RedisTemplate存入的数据
2.序列化策略不同:
步骤四:具体应用
1.为了更好的使用,需要导入fastjson工具包
专用字符串key value均是String
专用对象
自定义-基础版
自定义-实际应用版
业务层优化:
序列化策略:
改变序列化策略
spring-data-redis提供如下几种序列化策略
1.jedis
是Redis官方推荐的java连接开发工具
步骤一:导入对应的依赖
<!--导入jedis的包-->
<dependencies>
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
步骤二:测试
直接连接:1.实例化一个Jedis对象(Ip,端口) 2.调用ping()方法 3.指令和命令行指令完全一致
import redis.clients.jedis.Jedis;
public class TestPing {
public static void main(String[] args) {
// 1、 new Jedis 对象即可
Jedis jedis = new Jedis("127.0.0.1",6379);
// jedis
System.out.println(jedis.ping());
}
}
2.spring-date-redis 技术
是将Jedis做了二次封装
说明:
在SpringBoot2.x之后,原来使用的jedis被替换成了lettuce
步骤一:坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
步骤二:application.properties中加入redis相关配置
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=192.168.0.24
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=10
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=1000
步骤三:操作说明
spring data redis中封装了两个模板类,帮助我们实现redis的crud RedisTemplate key value泛型都是object【不具备可读性】 StringRedisTemplate key value泛型都是string
注意:
1.两者数据各自存,各自取,数据不互通。
RedisTemplate不能取StringRedisTemplate存入的数据
StringRedisTemplate不能取RedisTemplate存入的数据
2.序列化策略不同:
RedisTemplate采用JDK的序列化策略(JdkSerializationRedisSerializer)
保存的key和value 都是采用此策略序列化保存的
解释:
存储时,先将数据序列化为字节数组,再存入Redis数据库。
查看Redis会发现,是字节数组的形式类似乱码读取时,
会将数据当做字节数组转化为我们需要的数据,以用来存储对象,
但是要实现Serializable接口
StringRedisTemplate采用String的序列化策略(StringRedisSerializer)
保存的key和value都是采用此策略序列化保存的当存入对象时,
会报错:can not cast into String
存储和读取,都为可读的数据
3.两者的关系是StringRedisTemplate继承RedisTemplate
4.使用场景:
当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可。
但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。
5.五大数据类型封装:
redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForList();//操作List
redisTemplate.opsForSet();//操作Set
redisTemplate.opsForZSet();//操作ZSet
redisTemplate.opsForHash();//操作Hash
步骤四:具体应用
1.为了更好的使用,需要导入fastjson工具包
<!-- fastjson工具包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>com.colobu</groupId>
<artifactId>fastjson-jaxrs-json-provider</artifactId>
<version>0.3.1</version>
</dependency>
专用字符串key value均是String
@Autowired
public StringRedisTemplate stringRedisTemplate;
注意:
都是string,具有可读性
@Test
public void stringRedisTemplate(){
//1.key相关
Set<String> keys = stringRedisTemplate.keys("*");//得到所有的key
for (String key : keys) {
System.out.println(key);
}
//2.各种类型支持
模板使用的方法是把原来的命令稍微修改,不会完全一致【补全eg:incr ---> increment()】
stringRedisTemplate.opsForValue();
stringRedisTemplate.opsForList();//List
stringRedisTemplate.opsForHash();//hash
stringRedisTemplate.opsForSet();//set
stringRedisTemplate.opsForZSet();//zset
//3.举例字符串
stringRedisTemplate.opsForValue().set("name","许老师");
String name = stringRedisTemplate.opsForValue().get("name");
System.out.println(name);
//4.操作list列表
stringRedisTemplate.opsForList().leftPush("myList1","曹丕");
stringRedisTemplate.opsForList().leftPush("myList1","曹植");
stringRedisTemplate.opsForList().leftPushAll("mylistAll","曹操","曹丕","曹植");
List<String> list = stringRedisTemplate.opsForList().range("mylistAll",0,2);
System.out.println(list);
}
专用对象
@Autowired
public RedisTemplate redisTemplate;
注意:
1. redisTemplate默认使用key序列化方式和value的序列化方式都使用的是jdk serializer序列化
所以存对象会乱码,不具备可读性
2.所有返回值为object,需要转型
@Test
public void show2(){
ValueOperations valueOperations = redisTemplate.opsForValue();
valueOperations.set("name","薛老师");
String name = (String) valueOperations.get("name");
System.out.println(name);
redisTemplate.opsForValue();//String
redisTemplate.opsForList();//List
redisTemplate.opsForHash();//hash
redisTemplate.opsForSet();//set
redisTemplate.opsForZSet();//zset
//单一存
Student stu1 = new Student(1,"莫向东","24");
redisTemplate.opsForValue().set("stu1",stu1);
Student ss1 = (Student)redisTemplate.opsForValue().get("stu1");
System.out.println(ss1);
redisTemplate.opsForList().leftPushAll("mylist","睡觉","游戏");
List<String> list = redisTemplate.opsForList().range("mylist",0,-1);
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
System.out.println("打印默认序列策略"+redisTemplate.getDefaultSerializer());
}
自定义-基础版
注意:
需要字节写配置类,优化RedisTemplate的可读性【读官方文档】
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<Object, Object> jsonRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
//1.创建自定义模板类
RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
//2.配置json类型的序列化工具
template.setKeySerializer(new StringRedisSerializer());//这样key会用字符串方式保存
template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
//3.给模板配置工厂
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
@Autowired【按名字装配】
public RedisTemplate jsonRedisTemplate;
@Test
public void show3(){
//保存对象
Student stu = new Student(1,"厉顾城",25);
jsonRedisTemplate.opsForValue().set("stu",stu);
//获取对象 ----
Object s1 = jsonRedisTemplate.opsForValue().get("stu");
String jsonS1 = JSONObject.toJSONString(s1);
Student s11 = JSONObject.parseObject(jsonS1,Student.class);
System.out.println(s11);
Student stu2 = new Student(2,"厉顾城",25);
Student stu1 = new Student(2,"厉顾城",25);
Student stu3 = new Student(2,"厉顾城",25);
List<Student> students = Arrays.asList(stu1, stu2, stu3);
jsonRedisTemplate.opsForValue().set("stus",students);
//必须Object接受,利用ObjectMapper对象转换,如果强制转换会报错
Object data = jsonRedisTemplate.opsForValue().get("stus");
String dataJson = JSONObject.toJSONString(data);
//将JSON类型转为List
List<Student> stus = JSONObject.parseArray(dataJson, Student.class);
System.out.println(stus);
}
自定义-实际应用版
把redis当做缓存中间件搭建应用程序
1.配置类同上
2.在未来还会包装一个工具类,调用工具类来操作redis
1.作了大量的判断
2.更健壮
注意:使用@Component注入容器后,需要装配调方法
类中使用了@Autowired注解
【即:使用了spring注解,这个类必须是spring的一部分(注入容器)不把该类注入容器,此注解不会生效】
业务层优化:
查询:先在redis中查询,没有,再查库,存入redis,返回
注意:保证redis和数据库的数据一致【同步】
@Service
public class StudentService {
@Autowired(required = false)
StudentMapper mapper;
@Autowired
public RedisUtil redisUtil;
public Student findById(Integer id){
String key = "student:id:" + id;
//1.1判断key在redis中是否存在
boolean hasKey = redisUtil.hasKey(key);
if (hasKey) {
//1.2存在缓存则直接获取
Object stu = redisUtil.get(key);
ObjectMapper change = new ObjectMapper();
Student student = change.convertValue(stu,Student.class);
return student;
} else {
//1.3不存在缓存,先从数据库中获取,在保存至redis,最后返回用户
Student student = mapper.getStudentById(id);
if (student != null){
redisUtil.set(key, student);//写入缓存
}
return student;
}
}
public void deleteStudentById(Integer id){
//1.删除数据库
int result = mapper.deleteStudentById(id);
//2.判断数据库中是否删除成功
String key = "student:id:" + id;
if (result != 0) {
//3.判断redis中是否存在
boolean hasKey = redisUtil.hasKey(key);
//4.存在删除,不存在直接跳转
if (hasKey) {
redisUtil.del(key);
System.out.println("删除了缓存中的key:" + key);
}
}
}
}
序列化策略:
改变序列化策略
默认序列化方式存储到redis的数据人工不可读
不同策略序列化的过程有性能高低的
spring-data-redis提供如下几种序列化策略
GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化
Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的
JacksonJsonRedisSerializer: 序列化object对象为json字符串
JdkSerializationRedisSerializer: 序列化java对象
StringRedisSerializer: 简单的字符串序列化