同福

SpringBoot通过Jedis操作Redis数据库【20211116】

介绍

介绍

今天开始我们来学习Java操作Redis数据库的技巧,Java操作Redis是借助Jedis来实现的。Jedis是Java连接操作Redis的驱动库。

Java的生态非常成熟,基本上是无框架不项目,无论做任何功能都一定会基于一个框架来开发。福哥选择的就是非常大众的非常普及的SpringBoot框架,今天的教程也是基于这个SpringBoot框架的。因为今天的主题是使用Jedis操作Redis数据库,所以还不熟悉SpringBoot框架的童鞋们请自行恶补一下,福哥前面的文章也有介绍SpringBoot框架的,大家可以找来学习。

安装

配置

在application.properties里面设置连接redis的配置参数。

spring.redis.host=192.168.2.88
spring.redis.port=6379
spring.redis.password=tongfu.net

依赖

在pom.xml里面添加jedis的库包,这里面包括jedis库包和redis连接器库包。

<!-- redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.1.7.RELEASE</version>
</dependency>

<!-- jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.3.0</version>
</dependency>

配置

Redis可以存储非常多的数据类型,常用的是字符串类型(String)和对象类型(Object),而Redis的键都是字符串类型,所以我们在声明RedisTemplate的时候就需要指定数据类型。

String类型

字符串类型比较简单,存储的是字符串,取出来的也是字符串。

所以,如果是使用字符串类型的RedisTemplate的话,什么都不需要配置,直接注入就可以用了。

Object类型

对象类型就比较复杂了,对象可以是Map,也可以是实体对象,但是存储到Redis里面的其实是一个编码后的字符串,所以这里面就存在这编码与解码的操作,我们需要告诉RedisTemplate如何进行编码和解码。

所以,如果是对象类型的RedisTemlate我们需要建立配置对象去完成编码和解码的相关设置。

String类型

对象注入

在控制器对象里面注入RedisTemplate类,就可以直接使用这个RedisTemplate类的属性来操作Redis数据库了,不要太爽!

@Autowired
RedisTemplate<String, String> stringStringRedisTemplate;

测试

测试一

写入一段文字,再取出来,没有问题~

key = "redisTemplateString";
value = "福哥测试一下RedisTemplate<String, String>哦~";
stringStringRedisTemplate.opsForValue().set(key, value);
value = stringStringRedisTemplate.opsForValue().get(key);

home/topic/2021/1125/11/e674da62bac4f2fb9a2821572d04f81a.png

测试二

写入一段文字,设置过期时间是6秒之后,再等待6秒,这时候取出来的就是null了~

key = "redisTemplateString";
value = "福哥测试一下带有效期的RedisTemplate<String, String>哦~";
stringStringRedisTemplate.opsForValue().set(key, value);
stringStringRedisTemplate.expire(key, 6, TimeUnit.SECONDS);
try {
    TimeUnit.SECONDS.sleep(6);
} catch (InterruptedException e) {
    e.printStackTrace();
}
value = stringStringRedisTemplate.opsForValue().get(key);

home/topic/2021/1125/11/42983a2b9e4db12088c86edf793f00b4.png

Object类型

配置类

这个配置类就是告诉RedisTemplate如何处理Object数据,因为Object是泛型,什么结构都有可能,需要指明序列化方法才行。

建立一个配置类,设置@Configuration注解。

@Configuration
public class ConfigRedis {

    @Bean
    @Primary
    public RedisTemplate<String, Object> stringObjectRedisTemplate(
            RedisConnectionFactory factory
    ) {
        RedisTemplate<String, Object> rt;
        Jackson2JsonRedisSerializer<Object> jjs;
        StringRedisSerializer ss;

        rt = new RedisTemplate<String, Object>();
        rt.setConnectionFactory(factory);
        jjs = new Jackson2JsonRedisSerializer<Object>(Object.class);
        ss = new StringRedisSerializer();
        rt.setKeySerializer(ss);
        rt.setValueSerializer(jjs);
        rt.setHashKeySerializer(ss);
        rt.setHashValueSerializer(jjs);
        rt.setEnableDefaultSerializer(true);
        rt.setDefaultSerializer(jjs);

        return rt;
    }
}

对象注入

现在就可以在控制器对象里面注入RedisTemplate类,就可以直接使用这个RedisTemplate类的属性来操作Redis数据库了!

@Autowired
RedisTemplate<String, Object> stringObjectRedisTemplate;

测试

测试一

写入一个Map对象,再取出来,没有问题!

key = "redisTemplateObject";
value = new LinkedHashMap();
value.put("id", 35);
value.put("name", "鬼谷子叔叔");
stringObjectRedisTemplate.opsForValue().set(key, value);
value = (Map) stringObjectRedisTemplate.opsForValue().get(key);

home/topic/2021/1125/18/bb7efe86f518bc9b886b47579b331b77.png

测试二

写入一个Map对象,设置过期时间是6秒之后,再等待6秒,这时候取出来的就是null了~

key = "redisTemplateObject";
value = new LinkedHashMap();
value.put("id", 35);
value.put("name", "鬼谷子叔叔");
stringObjectRedisTemplate.opsForValue().set(key, value);
stringObjectRedisTemplate.expire(key, 6, TimeUnit.SECONDS);
try {
    TimeUnit.SECONDS.sleep(6);
} catch (InterruptedException e) {
    e.printStackTrace();
}
value = (Map) stringObjectRedisTemplate.opsForValue().get(key);

home/topic/2021/1125/18/6ed88407b1d1492e44e2a4039874b32b.png

实体对象

前面我们使用Map接收了从Redis取出来的数据,那么能不能把从Redis取出来的数据直接赋值到实体对象上面呢?

答案是肯定的:可以!

类型强转

但是如果试图简单地通过类型强转的方式去达到这一个目的,结果就会比较悲催了~

key = "redisTemplateEntity";
value = new User();
value.setId(35);
value.setName("鬼谷子叔叔");
stringObjectRedisTemplate.opsForValue().set(key, value);
value = (User) stringObjectRedisTemplate.opsForValue().get(key);

home/topic/2021/1125/19/afbd707f5399dc84ee8d00fe0730c8e6.png

大概的意思是不能通过强转方式把LinkedHashMap转换成一个实体对象User。

JSON

第一种方法就是把从Redis里的字符串取出来,通过JSON解码的方式转换成实体对象。

key = "redisTemplateEntity";
value = new User();
value.setId(35);
value.setName("鬼谷子叔叔");
stringObjectRedisTemplate.opsForValue().set(key, value);
String orgValue = stringStringRedisTemplate.opsForValue().get(key);
JSONObject jsonObject = JSONObject.fromObject(orgValue);
value = (User) JSONObject.toBean(jsonObject, User.class);

home/topic/2021/1125/19/1ae987b2589e6c287296bf9294548b92.png

Reflect

第二种方法就是把从Redis里的Map对象取出来,通过反射的方式手动映射到实体对象上面。

优点:这种方式的优点是可以精确地处理实体对象的每一个属性的映射方式。

缺点:缺点也很明显就是太繁琐了,不够优美。

福哥还是推荐使用JSON的方式实现,Reflect方式福哥就先比给示例了,网上搜索“Map转实体对象”到处都是教程,选一个你喜欢的照着码代码就可以了!

注意事项

使用RedisTemplate对象操作Redis数据库有一些注意事项,大家一定要认真看哦~~

  • 一定要保证数据库服务的健康状态以及数据源参数的可用性,否则会一旦连接失败就会造成项目无法启动的风险。

  • 无论的读取数据还是插入数据又或者是更新数据,最好将逻辑放入try ... catch语句里面,避免程序异常。

总结

今天福哥给童鞋们演示了使用RedisTemplate库连接Redis数据库进行各种常规操作的技巧,这里面都是一些简单的基础操作,一般的场景足够应付了~

后面福哥会找时间专门给童鞋们讲解Redis数据库的各种数据类型在Java里面的使用技巧,包括但不限于List(列表)、Set(集合)、Hash(哈希)等等,大家可以先行自己研究研究。