客户端选择
- https://redis.io/clients
- 我们Java开发中一般都选用jedis客户端工具,因为它小巧且功能完整,更为重要的是api和redis的命令基本保持一致
- Jedis同样也是托管在github上,地址:https://github.com/xetorthio/jedis
环境准备
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<encoding>UTF-8</encoding>
</properties>
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
入门案例
package cn.hanjiaxiaozhi;
import org.junit.Test;
import redis.clients.jedis.Jedis;
/**
* Author hanjiaxiaozhi
* Date 2020/7/7 16:29
* Desc 演示jedis客户端操作redis服务器
*/
public class JedisTest {
@Test
public void testJedisHello(){
//1.创建jedis连接对象
Jedis jedis = new Jedis("node01", 6379);
//2.测试是否可以连接redis服务器
String pong = jedis.ping();
System.out.println(pong);
//3.关闭连接
jedis.close();
}
}
jedis连接池
- 上面代码存在的问题:
- 每次使用jedis都得重新创建jedis连接对象,用完之后又关闭了 (开启关闭要时间的)
- 如果在项目中使用的话,会影响性能
- 所以可以使用连接池,提前创建好一些jedis连接对象放在池中, 以后要用的话直接从池中拿, 用完之后再放回池中
@Test
public void testJedisPool(){
//1.创建Jedis连接池参数对象
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
//设置连接池参数
jedisPoolConfig.setMaxTotal(100);//设置最大连接
jedisPoolConfig.setMaxIdle(10);//设置最大空闲连接数
jedisPoolConfig.setMinIdle(5);//设置最小空闲连接数
jedisPoolConfig.setMaxWaitMillis(2000);//最大等待时间
jedisPoolConfig.setTestOnCreate(true);
jedisPoolConfig.setTestOnBorrow(true);
jedisPoolConfig.setTestOnReturn(true);
//setTestOnCreate: 创建一个jedis实时时时候是否检查连接可用性,如果为true,则得到的jedis实例均是可用的
//setTestOnBorrow:获得一个jedis实例的时候是否检查连接可用性
//setTestOnReturn:归还一个jedis实例给pool时,是否检查连接可用性
//上面的3个都设置为true就可以保证拿到手和归还给连接池的jedis对象是可用的
//2.根据连接池参数对象创建连接池对象
JedisPool jedisPool = new JedisPool(jedisPoolConfig, "node01", 6379);
//3.从连接池中获取jedis连接对象
Jedis jedis = jedisPool.getResource();
//4.和之前一样使用
String pong = jedis.ping();
System.out.println(pong);
//5.使用完之后将jedis连接对象归还到池中
jedis.close();//表面上是关闭,本质上是归还到连接池中
}
抽取jedis工具类
package cn.hanjiaxiaozhi;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Author hanjiaxiaozhi
* Date 2020/7/7 16:43
* Desc 封装jedis工具类
* 工具类一般都是使用类名.方法名就可以使用
* 也就是说不需要创建对象就可以使用,那么该类最好设计成一个抽象类,因为抽象类别人不能直接new
* 然后里面的方法设置为静态方法即可,这样别人就可以直接使用类名.方法名
*/
public abstract class JedisUtil {
//将连接池对象提取出来,只需要在类初始化的时候创建一次即可
private static JedisPool jedisPool;
//static静态代码块只会在类被加载(第一次被使用的时候执行)
static{
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(100);//设置最大连接
jedisPoolConfig.setMaxIdle(10);//设置最大空闲连接数
jedisPoolConfig.setMinIdle(5);//设置最小空闲连接数
jedisPoolConfig.setMaxWaitMillis(2000);//最大等待时间
jedisPoolConfig.setTestOnCreate(true);
jedisPoolConfig.setTestOnBorrow(true);
jedisPoolConfig.setTestOnReturn(true);
jedisPool = new JedisPool(jedisPoolConfig, "node01", 6379);
}
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
各种数据类型测试
- 并且jedis的API和redis的命令基本一致,所以只写一个String类型的代码即可剩下的类型自己完全可以照葫芦画瓢,留作作业
@Test
public void testString(){
//1.使用JedisUtil从连接池中获取jedis对象
Jedis jedis = JedisUtil.getJedis();
//2.执行Redis操作String类型的命令对应的API(基本都是一样)
jedis.set("k1", "v1");
String v1 = jedis.get("k1");
System.out.println(v1);//v1
jedis.set("count","0");
jedis.incr("count");
jedis.incr("count");
jedis.incrBy("count",8);
String count = jedis.get("count");
System.out.println(count);//10
}
- 剩下的类型
/**
* jedis操作: string类型数据
*/
@Test
public void stringOperator() throws Exception {
//1. 创建jedis的对象
Jedis jedis = JedisUtils.getJedis();
//2. 执行相关操作:
//2.1 向redis中存值
jedis.set("age", "19");
//2.2 向redis中获取值
String age = jedis.get("age");
System.out.println(age);
//2.3 删除值
jedis.del("age");
jedis.set("age", "19");
//2.4 为age进行+1操作
Long incr = jedis.incr(age);
System.out.println(incr);
//2.5 为age进行-1操作
Long decr = jedis.decr("age");
System.out.println(decr);
//2.6 拼接字符串: 如果key存在就是拼接, 如果不存在就会重新创建
jedis.append("hobby", "篮球");
String hobby = jedis.get("hobby");
System.out.println(hobby);
//2.7 为key 设置有效时长
//为已有的key设置有效时间
Long expire = jedis.expire("hobby", 5);
System.out.println(expire);//返回1 表示设置成功, 返回0 表示该key不存在
while (jedis.exists("hobby")) {
System.out.println(jedis.ttl("hobby"));//返回-1 表示永久有效, -2 key不存在
Thread.sleep(1000);
}
//为新建的key设置有效时间
jedis.setex("date", 10, "2020");
while (jedis.exists("date")) {
System.out.println(jedis.ttl("date"));
Thread.sleep(1000);
}
//3. 释放资源
jedis.close();
}
/**
* 操作list类型的数据
*/
@Test
public void listOperate() {
//1. 创建jedis对象
Jedis jedis = JedisUtils.getJedis();
//执行操作前删清空集合中的数据,否则会一直往里面添加
jedis.del("list1");
jedis.del("list2");
//2. 执行list相关的操作
//2.1 添加数据: 从左侧添加
jedis.lpush("list1", "a", "b", "c", "d");
//2.2 弹出数据: 从右侧弹出数据
String rElement = jedis.rpop("list1");
System.out.println(rElement);
//2.3 添加数据: 从右侧添加
jedis.rpush("list2", "a", "b", "c", "d");
//2.4 弹出数据: 从左侧弹出
String lElement = jedis.lpop("list2");
System.out.println(lElement);
//2.5 查看整个list中某个范围间的数据: start: 开始 end: 结束 0~-1 表示查询全部
List<String> list = jedis.lrange("list1", 0, -1);
System.out.println(list);
//2.6 获取元素中个数
Long llen = jedis.llen("list2");
System.out.println(llen);
//2.7 在 b元素之前插入0
jedis.linsert("list1", BinaryClient.LIST_POSITION.BEFORE, "b", "0");
//2.8 在 c元素的后面插入1
jedis.linsert("list1", BinaryClient.LIST_POSITION.AFTER, "c", "1");
//2.9 将最后一个元素弹出并将其添加某个list的头部(也可以是自己)
jedis.rpoplpush("list1", "list1");
list = jedis.lrange("list1", 0, -1);
System.out.println(list);
//3. 释放资源
jedis.close();
}
/**
* set类型数据操作
*/
@Test
public void setOperate() {
//1. 创建jedis的对象
Jedis jedis = JedisUtils.getJedis();
//2. 执行set相关操作
//2.1 添加数据
jedis.sadd("set1", "a", "b", "c", "d");
jedis.sadd("set2", "a", "e", "f", "d");
//2.2 获取数据
Set<String> setList = jedis.smembers("set1");
System.out.println(setList);
//2.3 删除set中的指定的值
jedis.srem("set1", "b", "d");
//2.4 判断某个袁术在set集合中是否存在
Boolean is = jedis.sismember("set1", "b");
System.out.println(is);
//2.5 求两个set的集合 [交 并 差]
// sdiff: 差集 sinter: 交集 sunion:并集
Set<String> sinter = jedis.sinter("set1", "set2"); //求交集
System.out.println(sinter);
//2.6 查看set集合中一共有多少个数据
Long size = jedis.scard("set1");
System.out.println(size);
//3. 释放资源
jedis.close();
}
/*
* 使用jedis来操作redis --> sortedSet集合
* soredSet 特点: 有序 去重复
* sortedSet的的应用场景:排行榜
*/
@Test
public void zSetOperator() {
//1. 创建jedis对象
Jedis jedis = JedisUtils.getJedis();
//2. 执行sortedSet的相关的操作
//2.1 添加数据
jedis.zadd("math", 98.2, "老王");
jedis.zadd("math", 59.9, "小明");
jedis.zadd("math", 79, "老张");
jedis.zadd("math", 59.2, "小李");
//2.2 获取某个成员的分数
Double zscore = jedis.zscore("math", "老张");
System.out.println(zscore);
//2.3 查看sortedSet中某个元素的排名: 从小到大
Long zrank = jedis.zrank("math", "小李");
System.out.println(zrank);
//2.4 查看sortedSet中的元素: 从大到小
Set<Tuple> zrevrange = jedis.zrevrangeWithScores("math", 0, -1);
for (Tuple tuple : zrevrange) {
String element = tuple.getElement();
double score = tuple.getScore();
System.out.println(element + " " + score);
}
//2.4 查看sortedSet中的元素: 从小到大
Set<Tuple> zrange = jedis.zrangeWithScores("math", 0, -1);
for (Tuple tuple : zrange) {
String element = tuple.getElement();
double score = tuple.getScore();
System.out.println(element + " " + score);
}
//2.5 删除某个元素
jedis.zrem("math", "老张");
//3. 释放资源
jedis.close();
}
/**
* 操作hash类型数据
*/
@Test
public void hashOperate() throws Exception {
//1. 创建jedis对象
Jedis jedis = JedisUtils.getJedis();
//2.执行操作hash的相关API
//2.1 添加数据
jedis.hset("user007", "name", "隔壁老王");
jedis.hset("user007", "age", "30");
jedis.hset("user007", "birthday", "1988年9.15");
//2.2 获取数据
String name = jedis.hget("user007", "name");
String age = jedis.hget("user007", "age");
String birthday = jedis.hget("user007", "birthday");
System.out.println(name);
System.out.println(age);
System.out.println(birthday);
//2.3 一次性获取多个hash中的key的值
List<String> values = jedis.hmget("user007", "name", "age");
System.out.println(values);
//2.4 获取hash所有的数据
Map<String, String> map = jedis.hgetAll("user007");
for (String key : map.keySet()) {
System.out.println(key + " " + map.get(key));
}
//2.5 获取map中所有的key 和 所有的value
Set<String> hkeys = jedis.hkeys("user007");
List<String> hvals = jedis.hvals("user007");
System.out.println(hkeys);
System.out.println(hvals);
//2.6 删除map中的某个key
jedis.hdel("user007", "name", "age"); //删除map的name和age
//2.7 删除整个map
jedis.del("user007");
//3. 释放资源
jedis.close();
}