在我之前的项目中,使用Redis是我们团队自己封装了一个Redis操作类,但是这只是在Spring提供的RedisTemplate上做了一层封装而已,当时使用不是很熟练,都是一边在网上查资料,一边使用;这篇文章会介绍两种使用方式,一种是Jedis而另外一种是RedisTemplate;
Jedis
Jedis 是 Redis 的 Java 客户端,专为性能和易用性而设计。
要使用Jedis首先需要导入依赖:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.0</version>
</dependency>
字符串使用代码:
Jedis jedis = new Jedis("127.0.0.1", 6379);
// jedis.auth("xxx"); // 输入密码,没有密码,可以不设置
// 添加一个元素
jedis.set("mystr", "redis");
// 获取元素
String myStr = jedis.get("mystr");
System.out.println(myStr); // 输出:redis
// 添加多个元素(key,value,key2,value2)
jedis.mset("db", "redis", "lang", "java");
// 获取多个元素
List<String> mlist = jedis.mget("db", "lang");
System.out.println(mlist); // 输出:[redis, java]
// 给元素追加字符串
jedis.append("db", ",mysql");
// 打印追加的字符串
System.out.println(jedis.get("db")); // 输出:redis,mysql
// 当 key 不存在时,赋值键值
Long setnx = jedis.setnx("db", "db2");
// 因为 db 元素已经存在,所以会返回 0 条修改
System.out.println(setnx); // 输出:0
// 字符串截取
String range = jedis.getrange("db", 0, 2);
System.out.println(range); // 输出:red
// 添加键值并设置过期时间(单位:毫秒)
String setex = jedis.setex("db", 1000, "redis");
System.out.println(setex); // 输出:ok
// 查询键值的过期时间
Long ttl = jedis.ttl("db");
System.out.println(ttl); // 输出:1000
hash类型使用示例:
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 把 Key 值定义为变量
final String REDISKEY = "myhash";
// 插入单个元素
jedis.hset(REDISKEY, "key1", "value1");
// 查询单个元素
Map<String, String> singleMap = jedis.hgetAll(REDISKEY);
System.out.println(singleMap.get("key1")); // 输出:value1
// 查询所有元素
Map<String, String> allMap = jedis.hgetAll(REDISKEY);
System.out.println(allMap.get("k2")); // 输出:val2
System.out.println(allMap); // 输出:{key1=value1, k1=val1, k2=val2, k3=9.2, k4=v4...}
// 删除单个元素
Long delResult = jedis.hdel(REDISKEY, "key1");
System.out.println("删除结果:" + delResult); // 输出:删除结果:1
// 查询单个元素
System.out.println(jedis.hget(REDISKEY, "key1")); // 输出:返回 null
列表的使用示例:
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 声明 Redis key
final String REDISKEY = "list";
// 在头部插入一个或多个元素
Long lpushResult = jedis.lpush(REDISKEY, "Java", "Sql");
System.out.println(lpushResult); // 输出:2
// 获取第 0 个元素的值
String idValue = jedis.lindex(REDISKEY, 0);
System.out.println(idValue); // 输出:Sql
// 查询指定区间的元素
List<String> list = jedis.lrange(REDISKEY, 0, -1);
System.out.println(list); // 输出:[Sql, Java]
// 在元素 Java 前面添加 MySQL 元素
jedis.linsert(REDISKEY, ListPosition.BEFORE, "Java", "MySQL");
System.out.println(jedis.lrange(REDISKEY, 0, -1)); // 输出:[Sql, MySQL, Java]
jedis.close();
}
除了这些简单的使用方式外,Jedis还支持连接池的形式使用,以及可以用哨兵模式和集群模式,有关详细使用方式可以从官网获取:
Jedis官网:https://github.com/redis/jedis
spring data redis : https://docs.spring.io/spring-data/redis/docs/current/reference/html/
RedisTemplate
RedisTemplate应该是我们接触比较多的,它提供了多种数据类型操作的API,以及自动化连接池管理,所以它很受青睐。
导入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置连接相关:
RedisTemplate是一个高度封装的类,封装了许多数据类型的操作,同时还提供了连接池自动化关联。
redis:
#数据库索引
database: 0
host: 172.16.10.165
port: 10111
password: 123456
# cluster:
# nodes:
# - 172.16.10.165:6390
# - 172.16.10.165:6391
# - 172.16.10.165:6392
# - 172.16.10.165:6393
# - 172.16.10.165:6394
jedis:
pool:
#最大连接数
max-active: 100
#最大阻塞等待时间(负数表示没限制)
max-wait: 6000ms
#最大空闲
max-idle: 8
#最小空闲
min-idle: 1
time-between-eviction-runs: 2000ms
#连接超时时间
timeout: 10000ms
简单使用示例:基于spring boot
@Resource
private RedisTemplate redisTemplate;
@GetMapping("/world")
public void hello(){
redisTemplate.opsForValue().set("aaa","redisTemplate");
Object hello = redisTemplate.opsForValue().get("aaa");
System.out.println(hello.toString());
}
但是直接使用会有一个问题:
可以看到在redis中我们存入的值并不是我们预想的,这是因为序列化问题导致的,框架对于数据的存储是基于字节的;
序列化:
默认情况下RedisTemplate默认使用的是java本地的序列化与反序列化,但是一般都不会去使用默认的序列化方式,因为可读性比较差;所以一般在工程中会使用其它的序列化方式,怎么使用:
导入jackson依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.4</version>
</dependency>
配置序列化方式:
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisAutoConfig {
public RedisAutoConfig() {
}
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(connectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
return redisTemplate;
}
}
RedisTemplate API:
RedisTemplate提供了多种数据类型操作的API,我下面列举了几种常用的操作方法:
//list类型
//向redis的某个key下面的list列表里面插入一个list列表,不会去重。
List<OrgRelationInfo> remainOrgNodes = new ArrayList<>();
redisTemplate.opsForList().leftPushAll(CACHE_KEY, remainOrgNodes);
//从redis中取出某一个key下面的list列表, 0表示从列表的第0个元素开始取,-1表示直取到倒数第一个元素,也就是整个列表的所有元素都取出来。
List<OrgRelationInfo> lastRemainOrgNodeList = redisTemplate.opsForList().range(CACHE_NAME + CACHE_REMAIN_KEY_PREFIX, 0, -1);
//Hash类型
// 向redis中某个key下面插入key,hash的Map。
Map<Long, UserRelationInfo> value = new HashMap<>();
userHashRedisTemplate.opsForHash().putAll(KEY, value );
//从redis中某个key下面删除掉某个hashkey所在的value。
userHashRedisTemplate.opsForHash().delete(key, sourceOrgId);
//从redis中某个key下面得到这个key对应的hashkey的value值。前一个key只能是String类型,hashKey可以声明为自己需要的类型。
userHashRedisTemplate.opsForHash().get(Key, hashKey);
//从redis中得到某个key下面的所有的hashkey和hashvalue值。
Map<Object, Object> userOrgMap = userHashRedisTemplate.opsForHash().entries(getUserNodeCacheKey(syncUserNode.getSourceId()));
//set类型
//向redis的某个key下面的set列表里面插入一个元素,回去重,且无序。
userRoleSetRedisTemplate.opsForSet().add(KEY, cloudtOrgRoleInfo);
//从redis的某个key下面得到set集合的所有元素,返回的也是一个Set集合。
cloudtOrgRoleSet = userRoleSetRedisTemplate.opsForSet().members(KEY);
//从redis的某个key下面的set集合中删除掉一个元素。
userRoleSetRedisTemplate.opsForSet().remove( KEY, subDeleteOrgRoleUserArray[i]);