依赖下载
前往maven仓库搜索jedis:
选择4版本:
然后引入或者下载依赖即可。
这里直接提供了maven的一个jedis地址:
<!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.4.3</version> </dependency>
在pom.xml中引入依赖:
配置SSH转发
以xshell为例子:
右键你所选择的会话。选择属性:
然后添加:
然后点击连接。
查看是否生效:
使用netstat命令来访问 8888端口:
- win + r 输入cmd打开命令行。
- 输入: netstat -ano |findstr 8888
说明转发成功。
如果什么都不显示,则表示配置失败。
此时此刻,在后续的本地windows编程中,咱们的java代码就可以通过127.0.0.1:8888来访问我们的redis服务器了。同时外面的客户端是无法直接访问redis的6379端口了。
接下来可以正式编辑代码了。
连接到redis服务器
在java目录中创建一个案例,如下:
import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; public class RedisDemo { public static void main(String[] args) { // 连接到redis 服务器. JedisPool jedisPool = new JedisPool("tcp://127.0.0.1:8888"); // 从redis池中取出一个连接来 try (Jedis jedis = jedisPool.getResource()) { // Redis各种命令就对应到Jedis对象的各种方法,调用方法,就相当于执行命令. String pong = jedis.ping(); System.out.println(pong); } } }
- 首先需要创建一个jedis池,也就是JedisPool类,然后在这个pool中取出连接,来进行执行命令。
- 使用jedisPool中的getResource方法来获取一个jedis连接,返回值为Jedis类型数据,这个Jedis类型的数据就是建立好的一个链接
- 通过这个Jedis连接来进行编写代码,最简单的一个代码用来验证是否连接上了,如上:jedis.ping(),如果返回值为pong,那么说明连接成功,如代码:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. PONG Process finished with exit code 0
最开始安装Redis的时候,要配置绑定的ip,以及关闭保护模式。下面来看看如何操作:
- 找到Redis的配置文件:redis.conf,然后打开
- 找到bind选项:
这里默认绑定的是127.0.0.1,此时只能本机和本机访问,不能跨主机访问。应该将其改为图所示的0.0.0.0 - 关闭保护模式,首先找到redis.conf配置文件中的protected-mode
这里默认是yes,如果是yes的话就是开启保护模式,跨主机也是不能访问的。将其设置为no。
警告:当前的使用java代码和ssh转发进行的redis服务器访问操作仅限于开发阶段,实际情况就需要根据实际情况来修改ip。
客户端的使用
下面就将介绍jedis中的通用命令:
- get/set
- exists
- del
- keys
- expire /ttl
- type
- ......
接下来的介绍不会覆盖到所有的命令,这里只是介绍到比较重要的、具有代表性的命令进行演示。
get / set
import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import javax.swing.*; public class RedisDemo { public static void test1(Jedis jedis) { System.out.println("jedis的get和set的使用"); // 先清空数据库(避免上一组数据对本次测试的影响) jedis.flushAll(); // 此命令就相当于Redis中的flushall // 使用set jedis.set("key","111"); jedis.set("key2","222"); // 进行get System.out.println("key: " + jedis.get("key")); System.out.println("key2: "+jedis.get("key2")); } public static void main(String[] args) { // 连接到redis 服务器. JedisPool jedisPool = new JedisPool("tcp://127.0.0.1:8888"); // 从redis池中取出一个连接来 try (Jedis jedis = jedisPool.getResource()) { // Redis各种命令就对应到Jedis对象的各种方法,调用方法,就相当于执行命令. test1(jedis); } } }
注意看,在编写set的时候,你会发现,这里的set有很多重载的方法,例如:
除了指定keyvalue 的方法,还可以设置一个参数,这个参数的类型是SetParams。
首先我们先new一个SetParams,并创建其对象。
可以看见里面提供了很多方法:
- 其中有一个ex的方法可以用于设置超时时间,单位是秒,这里不做过多讲解。
- nx():用于对不存在的数据进行操作,只会添加数据,不会更新数据
- xx():用于已经存在的数据,才能够进行修改。
public static void test2(Jedis jedis) { System.out.println("exists 和 del的使用"); jedis.flushAll(); // 此命令就相当于Redis中的flushall // 首先set两个key jedis.set("key1","111"); jedis.set("key2","222"); System.out.println(jedis.exists("key1")); // 已经设置,打印true System.out.println(jedis.exists("key2")); // 已经设置,打印true System.out.println(jedis.exists("key3")); // 没有设置,打印false long ret = jedis.del("key1"); // 成功删除key1这一个健,返回1 // del 返回long类型表示成功返回多少个元素. System.out.println(ret); // 判定这个被删除的key1是否存在 boolean retEx = jedis.exists("key1"); // 已经被删除,返回false. System.out.println(retEx); // 如果要删除多个key: jedis.del("key1","key2","key3", ... ) }
执行test1方法,就会出现:
因为设置了xx参数,代表只会对已经存在的数据进行修改,但是此时的set操作当前的key是不存在的,所以get返回一个空。
exists / del
实例:
public static void test3(Jedis jedis) { System.out.println("keys* 的使用"); jedis.flushAll(); // 此命令就相当于Redis中的flushall // 设置四个key jedis.set("key1","1"); jedis.set("key2","2"); jedis.set("key3","3"); jedis.set("key4","4"); // 使用keysm,参数为pattern,通过特定格式的字符串来匹配符合要求的key,其中最简单的就是*,表示匹配任意结果 Set<String> set = jedis.keys("*"); // 这里使用set表示,是因为set里面的key是不能重复的 System.out.println(set); }
Jedis的方法exists,如果key已经存在,那么返回值为boolean类型的true,如果不存在则返回false。del则是删除已经存在的key,返回值为long类型,表示删除key的个数。
当然del还支持多个key同时删除:
jedis.del("key1","key2","key3", ... )
keys
public static void test4(Jedis jedis) { System.out.println("expire / ttl* 的使用"); jedis.flushAll(); // 此命令就相当于Redis中的flushall jedis.set("key","111"); jedis.expire("key",10); // expire的第一个参数是key,第二个参数是long类型.表示秒 // ttl 判断一个key还有多少过期时间,返回类型为long long time = jedis.ttl("key"); System.out.println(time); // 休眠三秒 try { Thread.sleep(Long.parseLong("3000")); } catch (InterruptedException e) { throw new RuntimeException(e); } // 再次ttl查看多少秒 System.out.println(jedis.ttl("key")); }
调用test3(),输出:
expire /ttl
public static void test4(Jedis jedis) { System.out.println("expire / ttl* 的使用"); jedis.flushAll(); // 此命令就相当于Redis中的flushall jedis.set("key","111"); jedis.expire("key",10); // expire的第一个参数是key,第二个参数是long类型.表示秒 // ttl 判断一个key还有多少过期时间,返回类型为long long time = jedis.ttl("key"); System.out.println(time); // 休眠三秒 try { Thread.sleep(Long.parseLong("3000")); } catch (InterruptedException e) { throw new RuntimeException(e); } // 再次ttl查看多少秒 System.out.println(jedis.ttl("key")); }
输出:
这里有延迟,说明服务器有延迟。
- expire:给存活的key设置一个过期时间,有两个参数,第一个参数是key对象,第二个 参数是long类型的数字,表示存活多少秒
- ttl:查看一个key的存活时间,返回类型为long类型,表示还剩多少秒。
type
public static void test5(Jedis jedis) { System.out.println("type 的使用"); jedis.flushAll(); // 此命令就相当于Redis中的flushall // type: 查看一个key的value是什么类型 jedis.set("key","111"); String type = jedis.type("key"); System.out.println(type); jedis.lpush("list","111","222","333"); System.out.println(jedis.type("list")); }
字符串命令
- get/set
- mget /mset
- getrange和setrange
- append
- incr 、decr
mget / mset
public static void test1(Jedis jedis) { System.out.println("mget,mset"); jedis.flushAll(); jedis.mset("key1","111","key2","222","key3","333"); // 返回值为 List<String> List<String> list = jedis.mget("key1","key2","key3","key100"); System.out.println("values:" + list); }
输出:
如果没有找到,那么使用null来表示。
getrange /setrange
public static void test2(Jedis jedis) { System.out.println("mget,mset"); jedis.flushAll(); jedis.set("key","0123456789"); // 有三个参数,第一个参数用来指定key,第二个和第三个参数用来指定范围,类型都是long,这里的下标可以理解为字符串的charAt() System.out.println(jedis.getrange("key", 0, 4)); System.out.println(jedis.getrange("key",1,8)); jedis.setrange("key",9,"xxx"); System.out.println(jedis.get("key")); }
append
public static void test3(Jedis jedis) { System.out.println("append"); jedis.flushAll(); jedis.set("key","abcdef"); jedis.append("key","ghijk"); String val = jedis.get("key"); System.out.println(val); }
输出:
incr / decr
public static void test4(Jedis jedis) { System.out.println("incr / decr"); jedis.flushAll(); jedis.set("key","100"); long ret = jedis.incr("key"); System.out.println(ret); ret = jedis.decr("key"); System.out.println(ret); }
输出:
- 他们两个的返回值都是执行命令之后的结果。
- 除了incr和decr之外,还有很多,例如:
这些就不做过多的讲解,可以自己参考上面的例子进行演示。
列表list
- lpush / lpop / lrange
- rpush / rpop
- blpop / brpop
- llen
push / pop / lrange
public static void test1(Jedis jedis) { System.out.println("lpush 和 lrange"); jedis.flushAll(); // 头插 jedis.lpush("key","111","222","333","444"); // 尾插 jedis.rpush("key","000"); List<String> list = jedis.lrange("key",0,-1); System.out.println(list); // 弹出444和000 jedis.lpop("key"); jedis.rpop("key"); list = jedis.lrange("key",0,-1); System.out.println(list); }
输出:
blpop/brpop
首先创建一个延迟100秒的brpop并执行:
public static void test2(Jedis jedis) { System.out.println("brpop"); jedis.flushAll(); // 返回结果是一个二元组,一个是从哪个key对应的list中删除,另外一个是删除的是什么 List<String> list = jedis.brpop(100,"key"); System.out.println(list); }
首先输出:
然后在设置的100s内,打开redis客户端,set一个key:
此时idea控制台输出:
["key","111"]
blpop同理。
llen
求列表的长度:
public static void test3(Jedis jedis) { System.out.println("llen"); jedis.flushAll(); jedis.lpush("key","111","222","333"); long len = jedis.llen("key"); System.out.println(len); }
输出:
- llen返回值为long类型。
- 返回值表示列表中元素的个数。
集合set
- sadd, smembers
- sismember
- scard
- spop
- sinter, sinterstore
sadd
public class JedisSet { public static void test1(Jedis jedis) { System.out.println("sadd"); jedis.flushAll(); jedis.sadd("key","1","2","3","4"); Set<String> set = jedis.smembers("key"); System.out.println(set); } public static void main(String[] args) { JedisPool jedisPool = new JedisPool("tcp://127.0.0.1:8888"); try(Jedis jedis = jedisPool.getResource()) { test1(jedis); } } }
输出:
sismember
public static void test2(Jedis jedis) { System.out.println("sadd"); jedis.flushAll(); long ret = jedis.sadd("key","1","2","3","4"); System.out.println(jedis.sismember("key", "1")); System.out.println(jedis.sismember("key", "10")); }
scard
public static void test3(Jedis jedis ){ System.out.println("scard"); jedis.flushAll(); long ret = jedis.sadd("key","1","2","3","4"); long nums = jedis.scard("key"); System.out.println(nums); }
spop
public static void test4(Jedis jedis) { System.out.println("spop"); jedis.flushAll(); long ret = jedis.sadd("key","1","2","3","4"); String res = jedis.spop("key"); System.out.println(res); }
输出:
sinter
public static void test5(Jedis jedis) { System.out.println("sinter"); jedis.flushAll(); jedis.sadd("key1","1","2","3"); jedis.sadd("key2","2","3","4"); Set<String> set = jedis.sinter("key1","key2"); System.out.println(set); }
sinterstore
public static void test6(Jedis jedis) { System.out.println("sinterstore"); jedis.flushAll(); jedis.sadd("key1","1","2","3"); jedis.sadd("key2","2","3","4"); long nums = jedis.sinterstore("key3","key1","key2"); System.out.println(nums); System.out.println(jedis.smembers("key3")); }
hash
- hset / hget
- hexists
- hdel
- hkeys
- hvals
- hmget / hmset
hset / hget
import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import java.util.HashMap; import java.util.Map; public class JedisHash { public static void testHgetAndHset(Jedis jedis) { System.out.println("hset和hget"); jedis.flushAll(); // 每次都只设置一次 key的filed和value jedis.hset("key","f1","v1"); jedis.hset("key","f2","v2"); jedis.hset("key","f3","v3"); jedis.hset("key","f4","v4"); // 一次性设置多个key的field Map<String, String> map = new HashMap<>(); map.put("f5","v5"); map.put("f6","v6"); jedis.hset("key",map); // 获取 String res = jedis.hget("key","f1"); System.out.println(res); // 尝试获取不存在的 res = jedis.hget("key","f100"); System.out.println(res); } public static void main(String[] args) { JedisPool jedisPool = new JedisPool("tcp://127.0.0.1:8888"); try(Jedis jedis = jedisPool.getResource()) { testHgetAndHset(jedis); } } }
输出:
hexists
public static void testHexists(Jedis jedis) { System.out.println("hexists"); jedis.flushAll(); jedis.hset("key","f1","v1"); jedis.hset("key","f2","v2"); jedis.hset("key","f3","v3"); System.out.println(jedis.hexists("key","f1")); System.out.println(jedis.hexists("key","f2")); System.out.println(jedis.hexists("key","f100")); }
hdel
public static void testHdel(Jedis jedis) { System.out.println("hdel"); jedis.flushAll(); jedis.hset("key","f1","v1"); jedis.hset("key","f2","v2"); jedis.hset("key","f3","v3"); // 删除key中的f3 jedis.hdel("key","f3"); // 使用hexists查看是否存在 System.out.println(jedis.hexists("key", "f3")); // 同时hdel可以同时删除多个 long ret = jedis.hdel("key","f1","f2"); System.out.println(jedis.hexists("key", "f1")); System.out.println(jedis.hexists("key", "f2")); System.out.println("一共被删除" + ret + "个field"); }
hkeys / hvals
public static void testHkeysAndHvals(Jedis jedis) { System.out.println("hkeys and hvals"); jedis.flushAll(); jedis.hset("key","f1","v1"); jedis.hset("key","f2","v2"); jedis.hset("key","f3","v3"); // 使用hkeys获取所有的key System.out.println("获取所有的key"); Set<String> set = jedis.hkeys("key"); System.out.println(set); // 使用hvals获取所有的val System.out.println("获取所有的val"); List<String> list = jedis.hvals("key"); System.out.println(list); }
有序集合zset
- zadd
- zrange
- zcard
- zrem
- zscore
- zrank
zadd
public static void testZaddAndZrange(Jedis jedis) { System.out.println("zadd / zrange"); jedis.flushAll(); // 一次性添加一个元素 jedis.zadd("key", 10.0,"zhangsan"); // 一次性添加多个元素 Map<String,Double> map = new HashMap<>(); map.put("lisi",11.3); map.put("wangwu",13.5); jedis.zadd("key",map); // 使用zrange查看 List<String> list = jedis.zrange("key",0, -1); System.out.println(list); // 携带分数score:zrangeWithScores List<Tuple> listWithScores = jedis.zrangeWithScores("key", 0, -1); System.out.println(listWithScores); // 获取listWithScores中的元素 String member = listWithScores.get(0).getElement(); double score = listWithScores.get(0).getScore(); System.out.println("member:" + member + ",score:" + score); }
- Tuple是Jedis或者说是Redis依赖中所携带的类,不是java本身自带的库.
Jedis中的Tuple类是一个用于存储键值对的简单数据结构。它包含两个泛型字段:key和value。key字段用于存储键,而value字段用于存储与键关联的值。Tuple类主要用于在Redis中存储和操作键值对数据。
以下是一个简单的示例:
import redis.clients.jedis.Tuple; public class JedisTupleExample { public static void main(String[] args) { // 创建一个Tuple对象 Tuple<String, String> tuple = new Tuple<>("name", "张三"); // 获取键和值 String key = tuple.getKey(); String value = tuple.getValue(); System.out.println("Key: " + key); System.out.println("Value: " + value); } }
在这个示例中,我们创建了一个包含键"name"和值"张三"的Tuple对象。然后,我们使用getKey()和getValue()方法分别获取键和值,并将它们打印到控制台。
下面是Tuple的原码:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package redis.clients.jedis.resps; import java.util.Arrays; import java.util.Objects; import redis.clients.jedis.util.ByteArrayComparator; import redis.clients.jedis.util.SafeEncoder; public class Tuple implements Comparable<Tuple> { private byte[] element; private Double score; public Tuple(String element, Double score) { this(SafeEncoder.encode(element), score); } public Tuple(byte[] element, Double score) { this.element = element; this.score = score; } public int hashCode() { int prime = true; int result = 1; result = 31 * result; if (null != this.element) { byte[] var3 = this.element; int var4 = var3.length; for(int var5 = 0; var5 < var4; ++var5) { byte b = var3[var5]; result = 31 * result + b; } } long temp = Double.doubleToLongBits(this.score); result = 31 * result + (int)(temp ^ temp >>> 32); return result; } public boolean equals(Object obj) { if (obj == null) { return false; } else if (obj == this) { return true; } else if (!(obj instanceof Tuple)) { return false; } else { Tuple other = (Tuple)obj; return !Arrays.equals(this.element, other.element) ? false : Objects.equals(this.score, other.score); } } public int compareTo(Tuple other) { return compare(this, other); } public static int compare(Tuple t1, Tuple t2) { int compScore = Double.compare(t1.score, t2.score); return compScore != 0 ? compScore : ByteArrayComparator.compare(t1.element, t2.element); } public String getElement() { return null != this.element ? SafeEncoder.encode(this.element) : null; } public byte[] getBinaryElement() { return this.element; } public double getScore() { return this.score; } public String toString() { return '[' + SafeEncoder.encode(this.element) + ',' + this.score + ']'; } }
里面提供了两个比较关键的数据一个是element,也就是member,另外一个就是score,也就是分数.
zcard
public static void testZcard(Jedis jedis) { System.out.println("zcard"); jedis.flushAll(); Map<String,Double> map = new HashMap<>(); map.put("lisi",11.3); map.put("wangwu",13.5); map.put("zhangsan", 10.5); jedis.zadd("key",map); long ret = jedis.zcard("key"); System.out.println(ret); }
zrem
public static void testZrem(Jedis jedis) { System.out.println("zrem"); jedis.flushAll(); Map<String,Double> map = new HashMap<>(); map.put("lisi",11.3); map.put("wangwu",13.5); map.put("zhangsan", 10.5); jedis.zadd("key",map); long n = jedis.zrem("key","zhangsan"); System.out.println("删除的个数:" + n); System.out.println(jedis.zrangeWithScores("key", 0, -1)); }
zscore
public static void testZscore(Jedis jedis) { System.out.println("zscore"); jedis.flushAll(); Map<String,Double> map = new HashMap<>(); map.put("lisi",11.3); map.put("wangwu",13.5); map.put("zhangsan", 10.5); jedis.zadd("key",map); double ret = jedis.zscore("key","lisi"); System.out.println(ret); ret = jedis.zscore("key","wangwu"); System.out.println(ret); ret = jedis.zscore("key","zhangsan"); System.out.println(ret); }
zrank
public static void testZrank(Jedis jedis) { System.out.println("zrank"); jedis.flushAll(); Map<String,Double> map = new HashMap<>(); map.put("lisi",11.3); map.put("wangwu",13.5); map.put("zhangsan", 10.5); jedis.zadd("key",map); long rankLisi = jedis.zrank("key","lisi"); long rankwangwu = jedis.zrank("key","wangwu"); long rankzhangsan = jedis.zrank("key","zhangsan"); System.out.println("lisi分数:" + jedis.zscore("key","lisi") + ", 排名:" +rankLisi); System.out.println("wangwu分数:" + jedis.zscore("key","wangwu") + ", 排名:" +rankwangwu); System.out.println("zhangsan分数:" + jedis.zscore("key","zhangsan") + ", 排名:" +rankzhangsan); }
如果指定一个不存在的member,会出现异常:
Exception in thread "main" java.lang.NullPointerException at JedisZset.testZrank(JedisZset.java:96) at JedisZset.main(JedisZset.java:110)