这篇博客是一篇笔记博客,看的是黑马的瑞吉外卖的视频。【好记性不如烂笔头】
在Spring Boot项目中,可以使用Spring Data Redis来简化Redis操作。
首先需要导入maven坐标
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
|
在Spring Boot中的配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| spring: application: name: spring-redis redis: host: localhost port: 6379 database: 0 jedis: pool: max-active: 8 max-wait: 1ms max-idle: 4 min-idle: 0
|
Spring Data Redis中提供了一个高度封装的类: RedisTemplate,针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:
- ValueOperations 简单的K-V操作
- SetOperations set类型数据操作
- ZSetOperations zset类型数据操作
- HashOperations 针对Map类型的数据操作
- ListOperations 针对list类型的数据操作
说明:RedisTemplate 这个类可以由Spring Boot自动装配的,前提是配置好
在 spring-boot-test-autoconfigure-..
这个jar包中,META-INF目录下有个spring.factories
【它进行了很多自动化配置】文件。Spring Boot项目在运行的时候,就会加载这个文件,在这个文件里找到 org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
,按Ctrl点进去,就可以看到一个配置类。
1 2 3 4 5 6 7 8 9
| @Bean @ConditionalOnMissingBean( //在容器中没有这个Bean时,加载 name = {"redisTemplate"} ) public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; }
|
所以可以直接使用@Autowired注解,直接注入。
1
| private RedisTemplate<String,String> redisTemplate;
|
这是指定了泛型的,也可以不指定泛型,最后再说明这两个之间区别是什么。
代码示范
ValueOperations:简单的K-V操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Test void testString() { ValueOperations<String, String> valueOperations = redisTemplate.opsForValue(); valueOperations.set("country","China"); String country = valueOperations.get("country"); System.out.println(country);
valueOperations.set("name","zhangsan",5, TimeUnit.SECONDS);
valueOperations.setIfAbsent("name","lisi"); String name = valueOperations.get("name"); System.out.println(name); }
|
HashOperations 针对Map类型的数据操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| @Test void testHash(){ HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash(); hashOperations.put("002","name","zhangsan"); hashOperations.put("002","age","23"); hashOperations.put("002","address","xian");
Set<String> keys = hashOperations.keys("002"); for (String key : keys) { String value = hashOperations.get("002", key); System.out.println(key+":"+value); } List<String> values = hashOperations.values("002"); System.out.println(values);
Map<String,String> user = new HashMap<>(); user.put("name","lisi");user.put("age","29");user.put("address","bj"); hashOperations.putAll("001",user);
List<String> list = new ArrayList<>(); list.add("name");list.add("age");list.add("address"); List<String> multiGet = hashOperations.multiGet("001", list); System.out.println(multiGet); Map<String, String> map = hashOperations.entries("001"); System.out.println(map); }
|
ListOperations 针对list类型的数据操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Test void testList(){ ListOperations<String, String> listOperations = redisTemplate.opsForList(); listOperations.leftPush("mylist","1"); listOperations.leftPushAll("mylist","2","3","4","5"); long size = listOperations.size("mylist"); for (long i = 0; i < size; i++) { String value = listOperations.leftPop("mylist"); System.out.println(value); }
List<String> mylist = listOperations.range("mylist", 0, -1); System.out.println(mylist); }
|
1,2,3,4,5依次从左边进
5,4,3,2,1依次从左边出
Redis的list类型类似双端队列
SetOperations set类型数据操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Test void testSet(){ SetOperations<String, String> setOperations = redisTemplate.opsForSet(); setOperations.add("myset","zhangsan","lisi","wangwu"); Set<String> stringSet = setOperations.members("myset"); System.out.println(stringSet); setOperations.remove("myset","lisi","wangwu"); Set<String> myset = setOperations.members("myset"); System.out.println(myset); }
|
ZSetOperations zset类型数据操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Test void testZset(){ ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet(); zSetOperations.add("myzset","a",10); zSetOperations.add("myzset","b",12); zSetOperations.add("myzset","c",9); zSetOperations.add("myzset","a",13); Set<String> myzset = zSetOperations.range("myzset", 0, -1); System.out.println(myzset); zSetOperations.incrementScore("myzset","b",10);
myzset = zSetOperations.range("myzset", 0, -1); System.out.println(myzset); zSetOperations.remove("myzset","b");
myzset = zSetOperations.range("myzset", 0, -1); System.out.println(myzset); }
|
公共操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Test void testcommon(){ Set<String> keys = redisTemplate.keys("*"); System.out.println(keys); Boolean key = redisTemplate.hasKey("name"); System.out.println(key); redisTemplate.delete("myset"); keys = redisTemplate.keys("*"); System.out.println(keys); DataType type = redisTemplate.type("001"); System.out.println(type); }
|
RedisTemplate指定泛型和不指定泛型的区别
其实区别就是在操作redis时,key和value的序列化方式不同。用代码测一下。
指定泛型
1 2 3 4 5 6 7 8 9 10 11 12
| @SpringBootTest class SpringRedisApplicationTests {
@Autowired private RedisTemplate<String,String> redisTemplate;
@Test void test(){ ValueOperations<String, String> valueOperations = redisTemplate.opsForValue(); valueOperations.set("name","zhangsan"); } }
|
在redis存储了一个key为name的数据,value为zhangsan。
然后打开命令行
1 2 3 4
| 127.0.0.1:6379> keys * 1) "name" 127.0.0.1:6379> get name "zhangsan"
|
这很正常吧
不指定泛型
重启redis服务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @SpringBootTest class SpringRedisApplicationTests {
@Autowired private RedisTemplate redisTemplate;
@Test void test(){ ValueOperations valueOperations = redisTemplate.opsForValue(); valueOperations.set("name","zhangsan"); } }
|
在redis存储了一个key为name的数据,value为zhangsan。
然后打开命令行
1 2 3 4
| 127.0.0.1:6379> keys * 1) "\xac\xed\x00\x05t\x00\x04name" #发现不一样的了吧 127.0.0.1:6379> get name (nil) #获取不到
|
这就是序列化方式不一样。
然后再不指定泛型的情况下,配置一下RedisTemplate
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Configuration public class RedisConfig { @Bean public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory factory){ RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(factory);
return redisTemplate; } }
|
重启redis服务,然后在运行以上程序,然后再在命令行试一下
1 2 3 4
| 127.0.0.1:6379> keys * 1) "name" 127.0.0.1:6379> get name "\xac\xed\x00\x05t\x00\bzhangsan"
|
"\xac\xed\x00\x05t\x00\bzhangsan"
出现这个的原因是,没有设置value的序列化。
总结
最后可以看出
private RedisTemplate<String,String> redisTemplate;
泛型的指定可以决定RedisTemplate
的key和value的序列化方式。
__END__