java操作Redis(jedis和lettuce)
一.使用Jedis
1.初始化项目
创建Maven项目并导入jedis依赖和我们需要使用的fastjson依赖
依赖可在Maven仓库中搜索找到:https://search.maven.org/
1 <!--jedis依赖--> 2 <dependency> 3 <groupId>redis.clients</groupId> 4 <artifactId>jedis</artifactId> 5 <version>3.2.0</version> 6 </dependency> 7 <!--fastjson--> 8 <dependency> 9 <groupId>com.alibaba</groupId> 10 <artifactId>fastjson</artifactId> 11 <version>1.2.62</version> 12 </dependency>
2.编程
1.测试连通
连接远程服务器上的redis时,需要在配置文件中修改为相关配置使得允许远程连接,若需要密码授权也需要进行配置。
运行输出 PONG,表示连通成功。
2.操作redis
jedis操作redis的方法就是redis的原生指令,几乎没有任何改变。
3.事务
1 package com.kuang; 2 3 import com.alibaba.fastjson.JSONObject; 4 import redis.clients.jedis.Jedis; 5 import redis.clients.jedis.Transaction; 6 7 /** 8 * @Description: 9 * @author: ZYQ 10 * @date: 2020/10/18 17:18 11 */ 12 public class tesetTX { 13 public static void main(String[] args) { 14 Jedis jedis = new Jedis("120.78.198.135", 6379); 15 jedis.auth("dhsqj.1982"); 16 17 JSONObject jsonObject = new JSONObject(); 18 jsonObject.put("hello", "world"); 19 jsonObject.put("name", "kuangshen"); 20 String result = jsonObject.toJSONString(); 21 22 //开启事务 23 Transaction multi = jedis.multi(); 24 try { 25 //入队 此时还未执行 26 multi.set("name", result); 27 multi.set("age", result); 28 //执行 29 multi.exec(); 30 System.out.println(jedis.get("name")); 31 System.out.println(jedis.get("age")); 32 } catch (Exception e) { 33 multi.discard(); 34 e.printStackTrace(); 35 } finally { 36 jedis.close(); 37 } 38 } 39 }
二.使用lettuce
1.初始化项目
新建SpringBoot项目,选择redis依赖
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-data-redis</artifactId> 4 </dependency>
2.编写配置文件
在SpringBoot2.x之后,redis依赖的底层实现用lettuce替换掉了jedis
jedis:采用的直连,多个线程操作的话,是不安全的;想要避免不安全,使用jedis pool连接池。更像BIO模式
lettuce:采用netty,实例可以在多个线程中共享,不存在线程不安全的情况;可以减少线程数量。更像NIO模式
源码分析:
简单配置一下
spring.redis.host=120.78.198.135
spring.redis.port=6379
spring.redis.password=dhsqj.1982
3.进行测试
1 package com.example.demo; 2 3 import org.junit.jupiter.api.Test; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.boot.test.context.SpringBootTest; 6 import org.springframework.data.redis.connection.RedisConnection; 7 import org.springframework.data.redis.core.RedisTemplate; 8 9 @SpringBootTest 10 class DemoApplicationTests { 11 12 @Autowired 13 private RedisTemplate redisTemplate; 14 15 @Test 16 void contextLoads() { 17 18 /** 19 * 获取redis的连接对象象 20 */ 21 // RedisConnection connection = redisTemplate.getConnectionFactory().getConnection(); 22 // connection.flushDb(); 23 24 /** 25 * opsForValue 操作String 26 * opsForList 操作list 27 * opsForSet 操作Set 28 * opsForHash 操作Hash 29 * opsForZset 操作Zset 30 * opsForGeo 31 * opsForHyperLogLog 32 */ 33 redisTemplate.opsForValue().set("mykey", "kuangshen"); 34 System.out.println(redisTemplate.opsForValue().get("mykey")); 35 } 36 37 }
发现仅在控制台上可以看到正确的结果,而在redis客户端中查看到的序列化之后的结果是这样的
点击redisTemplate查看源码
找到序列化默认的方式为jdk序列化方式,这种方式会将字符进行转义,也就是上上图看到的转义之后的结果
通过redisTemplate上的conditionalOnMissingBean注解,表明我们可以通过自定义redisTemplate。
可以在自定义的redisTemplate中书写序列化方法来覆盖默认的序列化方法,从而解决这个转义问题。
在未自定义redisTemplate之前,我们再进行测试来加深了解缘由
在pojo包中编写一个最基础的User对象,此时未进行序列化
在测试类中,尝试直接将对象存储在redis中,发现报错,异常说明对象需要序列化。
解决方法:在User类中实现序列化接口 Serializable 即可,默认的redisTemplate具有jdk序列化的具体实现,因此在redis中查看到的键值对依然为转义的结果。
接下来我们尝试将对象转化成json数据格式进行存储并读取
发现结果如下,因为目前我们还没有覆盖默认的序列化方法
测试完毕,此时对redisTemplate序列化这方面有了一定的了解。接下来我们去自定义redisTemplate
1 package com.example.demo.config; 2 3 import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 import com.fasterxml.jackson.annotation.JsonTypeInfo; 5 import com.fasterxml.jackson.annotation.PropertyAccessor; 6 import com.fasterxml.jackson.databind.ObjectMapper; 7 import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; 8 import org.springframework.context.annotation.Bean; 9 import org.springframework.context.annotation.Configuration; 10 import org.springframework.data.redis.connection.RedisConnectionFactory; 11 import org.springframework.data.redis.core.RedisTemplate; 12 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 13 import org.springframework.data.redis.serializer.StringRedisSerializer; 14 15 /** 16 * @Description: 17 * @author: ZYQ 18 * @date: 2020/10/18 22:17 19 */ 20 @Configuration 21 public class RedisConfig { 22 23 @Bean 24 public RedisTemplate<String, Object> template(RedisConnectionFactory factory) { 25 RedisTemplate<String, Object> template = new RedisTemplate<>(); 26 template.setConnectionFactory(factory); 27 //配置具体的序列化方法 28 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); 29 ObjectMapper om = new ObjectMapper(); 30 om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 31 om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); 32 jackson2JsonRedisSerializer.setObjectMapper(om); 33 34 //String的序列化 35 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); 36 //key采用String的序列化方式 37 template.setKeySerializer(stringRedisSerializer); 38 //hash的key也采用String的序列化方式 39 template.setHashKeySerializer(stringRedisSerializer); 40 //value采用jackson序列化方式 41 template.setValueSerializer(jackson2JsonRedisSerializer); 42 //hash的value采用jackson序列化方式 43 template.setHashValueSerializer(jackson2JsonRedisSerializer); 44 template.afterPropertiesSet(); 45 return template; 46 } 47 }
在测试中注入自定义的redisTemplate
@Autowired @Qualifier("template") private RedisTemplate redisTemplate;
测试方法
注意:
1.pojo类可以不实现 Serialization 接口,自定义的jackson序列化会帮我们做好
2.pojo类必须有无参构造方法,否则会抛出异常
运行后可以在redis客户端中发现键值对符合我们的需求了
4.总结
不管是jedis还是lettuce,其操作方法书写起来都很简单但繁琐,我们可以自己去写一个工具类来包装一下常用的方法,使得代码更简洁。