Loading... # redis初级api (springboot) ## 依赖 ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` ## 配置 ``` spring.redis.host=192.168.106.99 spring.redis.port=6379 ``` ## 使用 redis提供了high和low两种实例,high即springboot封装好的template,封装了redis的调用,low即通过template也可以获取redis的底层连接,调用原生api。high用起来比较方便,low可以自己添加逻辑,比较灵活。 **获取template** ``` @Autowired private RedisTemplate redisTemplate; ``` **opsForValue()表示对string类型的操作** ``` public void testRedis() { redisTemplate.opsForValue().set("hello", "china"); System.out.println(redisTemplate.opsForValue().get("hello")); } ``` **输出** ``` china ``` 可以看到,成功输出结果正确,然后到redis中执行```keys *``` 发现储存的key是\xac\xed\x00\x05t\x00\x05hello,显然不是我们正常要保存的key,redis还提供了另一个template: ``` @Autowired private StringRedisTemplate stringRedisTemplate; ``` 更改一下代码 ``` stringRedisTemplate.opsForValue().set("hello", "china"); System.out.println(stringRedisTemplate.opsForValue().get("hello")); ``` **输出** ``` china ``` 再看存入的key发现是hello,因为redis是二进制安全的,存入的数据是序列化之后的byte数组,也就是说序列化方式不一样,存入的数据就不一样,获取时,反序列化的方式也不一样,RedisTemplate会调用java默认的序列化方式,而StringRedisTemplate会调用字符串的序列化方式,redis支持很多语言,大多时候存取用的环境都不一样,显然不能用java的序列化方式。 **low实例** ``` RedisConnection conn = redisTemplate.getConnectionFactory().getConnection(); conn.set("hello".getBytes(), "aaa".getBytes()); System.out.println(new String(conn.get("hello".getBytes()))); ``` low方式通过RedisTemplate获取RedisConnection,该方式需要自己将数据转换成字节数组 **输出** ``` aaa ``` 查看存入的key是hello,也就是说low方式不存在序列化的问题。 ``` HashOperations<String, Object, Object> hash = stringRedisTemplate.opsForHash(); hash.put("key1", "name", "zhangsan"); hash.put("key1", "age", 22); System.out.println(hash.entries("key1")); ``` 上面这段代码执行会报java.lang.ClassCastException,因为age存入的是一个int类型,而StringRedisTemplate会用String的序列化,导致执行失败,修改一下代码: ``` HashOperations<String, Object, Object> hash = stringRedisTemplate.opsForHash(); hash.put("key1", "name", "zhangsan"); hash.put("key1", "age", "22"); System.out.println(hash.entries("key1")); ``` 发现执行成功了,但是我们存入的age是一个字符串。执行```HINCRBY key1 age 1```,对age进行加1操作,发现成功了,表示StringRedisTemplate存入的数据会默认被redis转换为相应的类型。 上面代码中,通过put(),插入数据比较麻烦,通常我们需求是直接给出一个对象,插入之后转换成hash类型。 **新建一个Person类** ``` public class Person { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } ``` **创建person对象** ``` Person p = new Person(); p.setName("zhangsan"); p.setAge(16); ``` 我们发现```stringRedisTemplate.opsForHash().putAll()```方法可以可以一次性插入,但是该方法需要传入一个key和一个Map,那我们就需要创建一个Map,然后将对象转换成Map,手工转换相当麻烦。所以需要用到Jackson2HashMapper类,该类的构造器需要接收一个ObjectMapper对象,所以,要添加依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> </dependency> ``` **注入对象** ``` @Autowired private ObjectMapper objectMapper; ``` **转换map** ``` Jackson2HashMapper jm = new Jackson2HashMapper(objectMapper, false); ``` false表示非扁平化 ``` stringRedisTemplate.opsForHash().putAll("key2", jm.toHash(p)); Map map = stringRedisTemplate.opsForHash().entries("key2"); Person per = objectMapper.convertValue(map, Person.class); System.out.println(per.getName()); ``` 抛出java.lang.ClassCastException,因为age是int类型,显然不能轻易修改对象的数据类型,那么只能从序列化层面入手 ``` stringRedisTemplate.setHashValueSerializer(); ``` 该方法需要传入一个序列化对象,可以new一个RedisSerializer接口然后自己写实现,也可以用封装好的实现,比如new StringRedisSerializer()就是String的序列化实现,但是String明显不行,这里需要使用Jackson2JsonRedisSerializer: ``` Person p = new Person(); p.setName("zhangsan"); p.setAge(16); stringRedisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class)); Jackson2HashMapper jm = new Jackson2HashMapper(objectMapper, false); stringRedisTemplate.opsForHash().putAll("key2", jm.toHash(p)); Map map = stringRedisTemplate.opsForHash().entries("key2"); Person per = objectMapper.convertValue(map, Person.class); System.out.println(per.getName()); ``` 执行成功,查看数据```hgetall key2```发现数据大致没问题,但是"zhangsan"多了一级双引号,实际上这没什么问题,获取数据序列化会自动去除这个双引号,每次都要设置一次序列化比较麻烦,我们希望StringRedisTemplate处理hash时的默认序列化方案就是Jackson2JsonRedisSerializer: **新建一个自定义template** ``` @Configuration public class MyTemplate { @Bean public StringRedisTemplate myTemplate(RedisConnectionFactory fc) { StringRedisTemplate tp = new StringRedisTemplate(fc); tp.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class)); return tp; } } ``` **注入** ``` @Autowired @Qualifier("myTemplate") private StringRedisTemplate stringRedisTemplate; ``` **使用** ``` Person p = new Person(); p.setName("zhangsan"); p.setAge(16); Jackson2HashMapper jm = new Jackson2HashMapper(objectMapper, false); stringRedisTemplate.opsForHash().putAll("key2", jm.toHash(p)); Map map = stringRedisTemplate.opsForHash().entries("key2"); Person per = objectMapper.convertValue(map, Person.class); System.out.println(per.getName()); ``` 执行成功。 **发布/订阅** **发布** ``` stringRedisTemplate.convertAndSend("pub", "hello"); ``` pub是通道,hello为发布内容。 **订阅** ``` RedisConnection cc = stringRedisTemplate.getConnectionFactory().getConnection(); cc.subscribe((message, bytes) -> { byte[] body = message.getBody(); System.out.println(new String(body)); , "pub".getBytes()); while(true){ } ``` 获取low实例,调用subscribe()方法,该方法需要传入一个MessageListener实现,通道名,方法不会阻塞,异步执行,监听到onMessage时会触发,因此测试时用死循环阻止程序结束。用```publish pub hello```命令发布一条信息,可以看到,信息的成功输出。 Last modification:December 18th, 2019 at 08:25 pm © 允许规范转载
文章已具雏形,需进一步聚焦核心问题。