redis基础(1)https://developer.aliyun.com/article/1530751
四,在java中操作redis
Redis的Java客户端很多,官方推荐的有三种:.
- Jedis
- Lettuce
- Redisson
Spring对Redis客户端进行了整合,提供了Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即spring-boot-starter-data-redis
jedis
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.7.0</version> </dependency> <dependency> <groupid>org.junit.jupiter</groupId> <artifactId>junit-jupiter</ artifactId> <version>5.7.0</version> <scope>test</ scope> </dependency>
使用Jedis操作Redis的步骤:
- 获取连接
private Jedis jedis; @BeforeEach void setUp() { //建立连接 jedis = new Jedis ( "192.168.150.101",6379); //设置密码 jedis.auth ( "123321"); //选择库 jedis.select(0); }
- 执行操作
@Test void testString() { //插入数据,方法名称就是redis命令名称,非常简单 String result = jedis.set( "name","张三"); System.out.println( "result " +result) ; //获取数据 String name = jedis.get( "name" ) ; system.out.println ( "name = " + name) ; }
- 关闭连接
@AfterEach void tearDown() { //释放资源 if (jedis != null) { jedis.close(); } }
Jedis连接池
public class JedisconnectionFactory { private static final JedisPool jedisPool; static { JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();//最大连接 jedisPoolConfig.setMaxTotal(8);//最大空闲连接 jedisPoolConfig.setMaxIdle(8);//最小空闲连接 jedisPoolConfig.setMinIdle(0);//设置最长等待时间,ms jedisPoolConfig.setMaxwaitMillis(200); jedisPool = new JedisPool(jedisPoolConfig,"192.168.150.101",6379, 1000,"123321"); } //获取Jedis对象 public static Jedis getJedis(){ return jedisPool.getResource(); }
Spring Data Redis
SpringData是Spring中数据操作的模块包含对各种数据库的集成,其中对Redis的集成就是SpringData Redis
- 提供了对不同Redis客户端的整合(Lettuce和Jedis)
- 提供了RedisTemplate统一API来操作Redis
- 支持Redis的发布订阅模型
- 支持Redis哨兵和Redis集群支持基于Lettuce的响应式编程
- 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
- 支持基于Redis的JDKcollection实现
导入坐标
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>\ <!--连接池依赖--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</ artifactId> </ dependency>
Spring Data Redis中提供了一个高度封装的类: RedisTemplate,针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:
ValueOperations:简单K-V操作
SetOperations: set类型数据操作
ZSetOperations: zset类型数据操作
HashOperations:针对map类型的数据操作
ListOperations:针对list类型的数据操作
spring: redis: host: localhost port: 6379 #passworld : 123456 database: 0 jedis: pool: max-active: 8 #最大连接数 max-wait: 1ms #连接池最大阻塞等待时间 max-idle: 4 #连接池最大空闲时间 min-idle: 0 #连接池中的最小空闲连接
测试
@SpringBootTest(classes = ReggieApplication.class) @RunWith(SpringRunner.class) public class test{ @Autowired private RedisTemplate redisTemplate; @Test public void test() { ValueOperations valueOperations = redisTemplate.opsForValue(); valueOperations.set("city","beijing"); } }
需要配置一下
不然会序列化成这样
自定义序列化
RedisTemplate可以接收任意Object作为值写入Redis:
只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:
缺点:
- 可读性差
- 内存占用较大
一般来说序列化string类型用String序列化器,用对象类型的时候用JSON序列化器
@Configuration public class RedisConfig extends CachingConfigurerSupport { @Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); //默认的Key序列化器为:JdkSerializationRedisSerializer redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setConnectionFactory(connectionFactory); return redisTemplate; } }
我们可以自定义RedisTemplate的序列化方式,代码如下:
@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){ // 创建RedisTemplate对象 RedisTemplate<String, Object> template = new RedisTemplate<>(); // 设置连接工厂 template.setConnectionFactory(connectionFactory); // 创建JSON序列化工具 GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer(); // 设置Key的序列化 template.setKeySerializer(RedisSerializer.string()); template.setHashKeySerializer(RedisSerializer.string()); // 设置Value的序列化 template.setValueSerializer(jsonRedisSerializer); template.setHashValueSerializer(jsonRedisSerializer); // 返回 return template; } }
这里采用了JSON序列化来代替默认的JDK序列化方式。最终结果如图:
整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。
StringRedisTemplate
为了节省内存空间,我们可以不使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。
也就是我们手动转JSON存入redis而不是JSON序列化器帮我们转
因为存入和读取时的序列化及反序列化都是我们自己实现的,SpringDataRedis就不会将class信息写入Redis了。
这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式。
省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用:
@Autowired private StringRedisTemplate stringRedisTemplate; // JSON序列化工具 private static final ObjectMapper mapper = new ObjectMapper(); @Test void testSaveUser() throws JsonProcessingException { // 创建对象 User user = new User("虎哥", 21); // 手动序列化 String json = mapper.writeValueAsString(user); // 写入数据 stringRedisTemplate.opsForValue().set("user:200", json); // 获取数据 String jsonUser = stringRedisTemplate.opsForValue().get("user:200"); // 手动反序列化 User user1 = mapper.readValue(jsonUser, User.class); System.out.println("user1 = " + user1); }
操控string类型的数据
@SpringBootTest(classes = ReggieApplication.class) @RunWith(SpringRunner.class) public class test{ @Autowired private RedisTemplate redisTemplate; @Test public void test() { ValueOperations valueOperations = redisTemplate.opsForValue(); valueOperations.set("city","beijing"); String city = (String) valueOperations.get("city"); System.out.println(city); //设置过期时间 valueOperations.set("key1","value1",101, TimeUnit.MILLISECONDS); //不存在则设置 valueOperations.setIfAbsent("city124", "苏州"); } }