Jedis客户端程序
第一节 Jedis简介
Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java、C、C#、C++、php、Node.js、Go等。在官方网站里列一些Java的客户端,有Jedis、Redisson、Jredis、JDBC-Redis、等其中官方推荐使用Jedis和Redisson。 在企业中用的最多的就是Jedis。Jedis提供了完整Redis命令,而Redisson有更多分布式的容器实现。
第二节 环境准备
- 创建maven普通项目,导入如下依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
- 虚拟机和Redis设置
- 禁用Linux的防火墙:Linux(CentOS7)里执行命令
- systemctl stop/disable firewalld.service
- redis.conf中注释掉bind 127.0.0.1 ,然后 protected-mode 的值设置为no
- 测试JAVA程序和Redis之间的通信
package com.mytest.jedis;
import redis.clients.jedis.Jedis;
public class Demo01 {
@Test
public void TestPing() {
Jedis jedis = new Jedis("192.168.6.101",6379);
String pong = jedis.ping();
System.out.println("连接成功:"+pong);
jedis.close();
}
}
第三节 key相关API
@Test
public void testKeyAPI(){
jedis.set("k1", "v1");
// 添加 键值对并设置过期时间
jedis.setex("k2",100, "v2");
jedis.set("k3", "v3");
// 获取所有的键
Set<String> keys = jedis.keys("*");
System.out.println(keys.size());
for (String key : keys) {
System.out.println(key);
}
// 判断某个键是否存在
System.out.println(jedis.exists("k1"));
// 查看键剩余过期时间
System.out.println(jedis.ttl("k2"));
// 根据键获取值
System.out.println(jedis.get("k1"));
}
第四节 String相关API
// 添加String
System.out.println(jedis.set("k1", "v1"));
// 一次添加多个
System.out.println(jedis.mset("ka","aaa","kb","bbb"));
// 获取
System.out.println(jedis.get("k1"));
// 一次获取多个
System.out.println(jedis.mget("k1","ka","kb"));
// 追加
System.out.println(jedis.append("k1", "vvvvv"));
// 获取长度
System.out.println(jedis.strlen("k1"));
// 不存在时进行设置
System.out.println(jedis.setnx("k1","xxxxx"));
System.out.println(jedis.setnx("k2","10"));
// 增长/减少
System.out.println(jedis.incr("k2"));
System.out.println(jedis.decr("k2"));
System.out.println(jedis.incrBy("k2", 10));
System.out.println(jedis.decrBy("k2", 10));
第五节 List相关API
@Test
public void testList(){
// 放入List
Long lpush = jedis.lpush("klist", "a", "b", "c", "d", "d");
System.out.println(lpush);
// 获取List
List<String> kList = jedis.lrange("klist", 0, -1);
kList.forEach(System.out::println);
// 取值
String klist = jedis.lpop("klist");
}
第六节 Set相关API
@Test
public void testSet(){
// 添加一个set集合
jedis.sadd("skey","a","b","c","d","e");
// 获取制定的set集合
Set<String> skey = jedis.smembers("skey");
skey.forEach(System.out::println);
//判断是否包含
System.out.println(jedis.sismember("skey","a"));
//删除元素
jedis.srem("skey","a","b");
//弹出一个元素
System.out.println(jedis.spop("skey"));
//弹出N个元素
System.out.println(jedis.spop("skey",2));
//从一个set向另一个set移动元素
jedis.smove("skey","bkey","X");
// ……
}
第七节 Hash相关API
// 添加值
jedis.hset("player1","pname","测试a");
jedis.hset("player1","page","14");
jedis.hset("player1","gender","boy");
// 获取值
System.out.println(jedis.hget("player1","pname"));
// 批量添加值
Map<String,String> player2=new HashMap<String,String>();
player2.put("pname","测试b");
player2.put("page","13");
player2.put("gender","boy");
jedis.hmset("player2",player2);
// 查看filed是否存在
System.out.println(jedis.hexists("player1", "pname"));
// 查看集合中所有的field
Set<String> player1fields = jedis.hkeys("player1");
player1fields.forEach(System.out::println);
// 查看集合中所有的value
List<String> player1vals = jedis.hvals("player1");
player1vals.forEach(System.out::println);
// 给制定属性+1
jedis.hincrBy("player1","page",5);
// 如不存在,添加某个属性
jedis.hsetnx("player1","height","156");
System.out.println(jedis.hget("player1","page"));
System.out.println(jedis.hget("player1","height"));
第八节 ZSet相关API
// 准备数据
Map<String ,Double> map=new HashMap<>();
map.put("李四",11d);
map.put("王五",8d);
map.put("赵六",20d);
map.put("刘七",3d);
// 添加元素
jedis.zadd("zkey",10,"张三");
jedis.zadd("zkey",map);
// 升序返回有序
Set<String> zkeys = jedis.zrange("zkey", 0, -1);
zkeys.forEach(System.out::println);
// 降序返回元素
Set<String> zkeys2 = jedis.zrevrange("zkey", 0, -1);
zkeys2.forEach(System.out::println);
System.out.println("===========");
Set<String> zkeys3 = jedis.zrangeByScore("zkey", 10, 20);
zkeys3.forEach(System.out::println);
System.out.println("===========");
Set<String> zkeys4 = jedis.zrevrangeByScore("zkey", 20, 10);
zkeys4.forEach(System.out::println);
// 增加分数
jedis.zincrby("zkey",5,"张三");
jedis.zincrby("zkey",-5,"赵六");
// 删除 元素
jedis.zrem("zkey","张三");
System.out.println(jedis.zcount("zkey",10,20));
System.out.println(jedis.zrank("zkey","李四"));
SpringBoot整合Redis
1 SpringDataRedis介绍
1.1 SpringData-Redis介绍
SpringData模块是SpringBoot中对各种数据操作的单元,集成对各种数据库的简化操作方式,其中对Redis数据库操作的模块叫做spring-data-redis!
- 提供了不同Redis客户端的整合(Jedis和Lettuce)
- 提供了简化操作api对象,RedisTemplate
- 支持Redis高级场景应用(集群,哨兵等配置)
- 支持数据序列化和反序列化存储
- 更方便集成到SpringBoot环境等等
1.2 SpringDataRedis方法分组介绍
SpringDataRedis提供的直接操作api对象为RedisTemplate,我们先了解下,他针对数据操作的方法有哪些!
| 方法名 | 操作数据类型 |
|---|---|
| redisTemplate.opsForValue() | 操作String数据类型 |
| redisTemplate.opsForHash() | 操作Hash数据类型 |
| redisTemplate.opsForList() | 操作List数据类型 |
| redisTemplate.opsForSet() | 操作Set数据类型 |
| redisTemplate.opsForZSet() | 操作ZSet数据类型 |
2 创建工程
5.3 添加依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.5</version>
</parent>
<dependencies>
<!-- 基本启动 starter - autoconfigure - 142配置类 web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<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>
</dependencies>
4 创建配置文件
application.properties
# redis单机连接的基本信息
spring.data.redis.host=120.46.137.83
spring.data.redis.port=6385
# 配置客户端类型(springboot2以后,默认切换到lettuce)
spring.data.redis.client-type=lettuce
# redis连接池配置
# 含义:这个属性指定是否启用 Lettuce 连接池。
spring.data.redis.lettuce.pool.enabled=true
# 含义:这个属性定义了连接池中允许的最大活动连接数。
spring.data.redis.lettuce.pool.max-active=8
# 含义:这个属性定义了连接池中允许的最大空闲连接数。
spring.data.redis.lettuce.pool.max-idle=5
# 含义:这个属性定义了在获取连接时最长的等待时间(以毫秒为单位)。
spring.data.redis.lettuce.pool.max-wait=100
#切换jedis
spring.data.redis.client-type=jedis
spring.data.redis.jedis.pool.enabled=true
spring.data.redis.jedis.pool.max-active=8
RedisTemplate、StringRedisTemplate: 操作redis的工具类
-
要从redis的连接工厂获取链接才能操作redis
-
Redis客户端
-
- Lettuce: 默认
- Jedis:可以使用以下切换
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 切换 jedis 作为操作redis的底层客户端-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
5 创建启动类
package com.mytest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
6 测试Template代码
@SpringBootTest(classes = 启动类.class)
public class SpringBootRedisTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testString(){
redisTemplate.opsForValue().set("name","赵伟风");
String result = (String) redisTemplate.opsForValue().get("name");
System.out.println("result = " + result);
}
}
7 序列化定制
7.1 RedisTemplate序列化需求介绍
- 问题演示和解释
我们发现,代码存储key="name"到了redis变了样,这是因为redis有自带的序列化器转化的时的问题!
序列化器配置位置和默认配置代码:
private @Nullable RedisSerializer<?> defaultSerializer;
private @Nullable ClassLoader classLoader;
//配置序列化器的四个位置
//key - value
private @Nullable RedisSerializer keySerializer = null;
private @Nullable RedisSerializer valueSerializer = null;
private @Nullable RedisSerializer hashKeySerializer = null;
private @Nullable RedisSerializer hashValueSerializer = null;
private RedisSerializer<String> stringSerializer = RedisSerializer.string();
//....
/**
* Constructs a new <code>RedisTemplate</code> instance.
*/
public RedisTemplate() {}
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (defaultSerializer == null) {
//如果没有配置序列化器,使用的是jdk序列化器
//将数据转成byte字节进行存储
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
if (enableDefaultSerializer) {
if (keySerializer == null) {
keySerializer = defaultSerializer;
defaultUsed = true;
}
if (valueSerializer == null) {
valueSerializer = defaultSerializer;
defaultUsed = true;
}
if (hashKeySerializer == null) {
hashKeySerializer = defaultSerializer;
defaultUsed = true;
}
if (hashValueSerializer == null) {
hashValueSerializer = defaultSerializer;
defaultUsed = true;
}
}
//....
initialized = true;
}
JdkSerializationRedisSerializer 是 Spring Data Redis 提供的一种 Redis 数据序列化器,它的主要作用是将 Java 对象序列化为字节流,以便将其存储在 Redis 中,或者从 Redis 中读取字节流并反序列化为 Java 对象。
-
常见序列化器
序列化器名 作用 备注 JdkSerializationRedisSerializer 将数据转化字节流进行存储 默认 GenericJackson2JsonRedisSerializer jackson序列化器,数据进行json方式序列化 导入依赖jackson StringRedisSerializer 字符串形式存储,一般用于key 注意utf-8格式
7.2 RedisTemplate序列化具体配置
@Configuration
public class RedisTemplateConfig {
@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;
}
}
8 RedisTemplate其他方法
测试使用redisTemplate其他的方法!
@SpringBootTest(classes = Main.class)
public class SpringRedisTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testRedis2(){
//字符串操作
redisTemplate.opsForValue().set("name","zwf");
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
List list = new ArrayList<>();
list.add("lucy");
list.add("mary");
redisTemplate.opsForValue().set("abc",list);
System.out.println(redisTemplate.opsForValue().get("abc"));
System.out.println("----------------------------------------------");
//集合操作
redisTemplate.opsForList().rightPushAll("names","1","2","3");
List names = redisTemplate.opsForList().range("names", 0, -1);
System.out.println("names = " + names);
System.out.println("----------------------------------------------");
// 存储哈希表
String hashKey = "myHash";
String field1 = "name";
String value1 = "John";
String field2 = "age";
String value2 = "25";
redisTemplate.opsForHash().put(hashKey, field1, value1);
redisTemplate.opsForHash().put(hashKey, field2, value2);
// 获取哈希表
Object retrievedValue1 = redisTemplate.opsForHash().get(hashKey, field1);
System.out.println("retrievedValue1 = " + retrievedValue1);
Object retrievedValue2 = redisTemplate.opsForHash().get(hashKey, field2);
System.out.println("retrievedValue2 = " + retrievedValue2);
System.out.println("----------------------------------------------");
// 存储集合
String setKey = "mySet";
value1 = "Apple";
value2 = "Banana";
String value3 = "Orange";
redisTemplate.opsForSet().add(setKey, value1);
redisTemplate.opsForSet().add(setKey, value2);
redisTemplate.opsForSet().add(setKey, value3);
// 获取集合
Set<Object> retrievedSet = redisTemplate.opsForSet().members(setKey);
System.out.println("Retrieved set: " + retrievedSet); // Output: Retrieved set: [Apple, Banana, Orange]
System.out.println("----------------------------------------------");
// 添加元素到 Sorted Set
redisTemplate.opsForZSet().add("myZSet", "value1", 1.0);
redisTemplate.opsForZSet().add("myZSet", "value2", 2.0);
redisTemplate.opsForZSet().add("myZSet", "value3", 3.0);
// 获取 Sorted Set 的元素数量
Long size = redisTemplate.opsForZSet().size("myZSet");
System.out.println("Sorted Set size: " + size);
// 获取指定元素的分数
Double score = redisTemplate.opsForZSet().score("myZSet", "value2");
System.out.println("Value2 score: " + score);
// 获取指定范围的元素(按分数排序)
Set<String> range = redisTemplate.opsForZSet().range("myZSet", 0, -1);
System.out.println("Sorted Set range: " + range);
// 移除指定元素
Long removedCount = redisTemplate.opsForZSet().remove("myZSet", "value1");
System.out.println("Removed count: " + removedCount);
}
}