简介
jedis用于创建和管理连接,并提供了对redis数据库的操作方法。Jedis相当于JDBC中的Connection,JedisPool相当于DBCP或者C3P0,而JedisCluster更像是Spring中的JDBCTemplate(将连接池和连接都给封装起来了,只提供给我们直接操作redis的api)。
JedisPool和JedisCluster在构造连接池对象的时候,需要传入JedisPoolConfig,host,port等。这些配置信息我们可以统一地定义在jedis.properties文件中,方便后续维护。但jedis有个不足,就是不能读取properties文件,需要我们手动取值设置。
使用例子
需求
使用jedis连接池对redis进行String、Set、Sorted Set、List、Hash和Key的操作。(这里仅测试单机版,集群不涉及)
工程环境
JDK:1.8.0_201 maven:3.6.1 IDE:Spring Tool Suites4 for Eclipse redis:3.2.100(windows64)
主要步骤
- 读取jedis.properties文件,创建并设置JedisPoolConfig;
- 根据配置参数构造JedisPool;
- 调用JedisPool的getResource方法获取Jedis对象;
- 使用Jedis进行CRUD操作。
创建项目
项目类型Maven Project,打包方式jar
引入依赖
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.3</version> </dependency>
编写jedis.properties
路径:resources目录下
#############基本参数#############
#ip地址
redis.host=127.0.0.1
#端口号
redis.port=6379
#如果有密码
redis.password=root
#客户端超时时间单位是毫秒 默认是2000
redis.timeout=3000
#############资源数控制参数#############
#资源池的最大连接数。默认值8
redis.pool.maxTotal=8
#资源池允许最大空闲连接数。默认值8。建议=maxTotal
redis.pool.maxIdle=8
#资源池确保最少空闲连接数。默认0。
redis.pool.minIdle=0
#是否开启jmx监控,可用于监控。默认true。建议开启
redis.pool.jmxEnabled=true
#############借还参数#############
#当资源池用尽后,调用者是否要等待。默认值为true。建议默认。只有当为true时,下面的maxWaitMillis才会生效。
redis.pool.blockWhenExhausted=true
#当资源池连接用尽后,调用者的最大等待时间(单位毫秒)。默认-1:表示永不超时。不建议使用默认值。
redis.pool.maxWaitMillis=3000
#向资源池借用连接时是否做连接有效性检查(ping),无效连接会被移除。默认false。业务量很大时候建议false。
redis.pool.testOnBorrow=true
#向资源池归还连接时是否做连接有效性测试(ping),无效连接会被移除。默认false。业务量很大时候建议false。
redis.pool.testOnReturn=false
#############空闲资源监控#############
#是否开启空闲资源监测。默认false。建议true。
redis.pool.testWhileIdle=true
#空闲资源的检测周期(单位为毫秒)。默认-1:不检测。建议设置,周期自行选择。
redis.pool.timeBetweenEvictionRunsMillis=30000
#资源池中资源最小空闲时间(单位为毫秒),达到此值后空闲资源将被移除。
#默认值1000*60*30 = 30分钟。建议默认,或根据自身业务选择。
redis.pool.minEvictableIdleTimeMillis=300000
#做空闲资源检测时,每次的采样数。默认3。
#可根据自身应用连接数进行微调,如果设置为-1,就是对所有连接做空闲监测。
redis.pool.numTestsPerEvictionRun=3
编写JedisUtils
这个工具类的主要作用是加载配置文件、初始化连接池、获取连接等。
路径:cn.sdd.jedis
/** * @ClassName: JedisUtils * @Description: jedis工具类,用于获取连接 * @author: sdd * @date: 2018年9月1日 下午8:47:26 */ public class JedisUtils { private static ThreadLocal<Jedis> tl = new ThreadLocal<Jedis>(); private static Object obj = new Object(); //连接池对象 private static JedisPool jedisPool; static { init(); } /** * @Title: getJedis * @Description: 获取连接对象的方法,线程安全 * @author: sdd * @date: 2019年8月31日 下午9:22:29 * @return: Jedis */ public static Jedis getJedis() throws Exception{ //从当前线程中获取连接对象 Jedis jedis = tl.get(); //判断为空的话,创建连接并绑定到当前线程 if(jedis == null) { synchronized (obj) { if(tl.get() == null) { jedis = jedisPool.getResource(); tl.set(jedis); } } } return jedis; } /** * @Title: returnJedis * @Description: 交还jedis,校验如果jedis失效就将其移出 * @author: sdd * @date: 2018年9月1日 下午9:13:57 * @return: void */ public static void returnJedis() { Jedis jedis = tl.get(); if(jedis!=null) { if(!jedis.isConnected()) { tl.remove(); jedis.close(); } } } /** * @Title: init * @Description: 加载配置文件,并初始化jedisPool * @author: sdd * @date: 2018年9月1日 下午8:48:39 * @return: void */ private static void init() { //加载配置文件 InputStream in = JedisUtils.class.getClassLoader().getResourceAsStream("jedis.properties"); Properties properties = new Properties(); try { properties.load(in); } catch (IOException e) { System.err.println("加载配置文件失败,创建连接池失败"); e.printStackTrace(); return; } //设置配置对象 JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxTotal(Integer.parseInt(properties.getProperty("redis.pool.maxTotal"))); jedisPoolConfig.setMaxIdle(Integer.parseInt(properties.getProperty("redis.pool.maxIdle"))); jedisPoolConfig.setMinIdle(Integer.parseInt(properties.getProperty("redis.pool.minIdle"))); jedisPoolConfig.setMaxWaitMillis(Integer.parseInt(properties.getProperty("redis.pool.maxWaitMillis"))); jedisPoolConfig.setTestOnBorrow(Boolean.parseBoolean(properties.getProperty("redis.pool.testOnBorrow"))); jedisPoolConfig.setTestOnReturn(Boolean.parseBoolean(properties.getProperty("redis.pool.testOnReturn"))); //创建jedis连接池 jedisPool = new JedisPool(jedisPoolConfig, properties.getProperty("redis.host"), Integer.parseInt(properties.getProperty("redis.port")), Integer.parseInt(properties.getProperty("redis.timeout")), properties.getProperty("redis.password") ); } }
编写测试类
路径:test目录下的cn.sdd.jedis,分别测试操作String、Set、Sorted Set、List、Hash和Key。
测试String
/** * @Title: testKey * @Description: 测试操作String的方法 * @author: sdd * @date: 2018年9月1日 下午9:30:43 * @return: void * @throws Exception */ @Test public void testString() throws Exception { //获取Jedis对象 Jedis jedis = JedisUtils.getJedis(); String key = "jedis-demo:testString"; //添加键值对 jedis.set(key, "test001"); //获取键值对 System.out.println(jedis.get(key)); //删除键值对 jedis.del(key); //判断键值对是否存在 System.out.println(jedis.exists(key)); //归还连接 JedisUtils.returnJedis(); }
测试List
注意:list类型的本质是双向链表,jedis提供的api中不支持通过指定value来更新和删除元素。另外list的第一位是从0开始,而-1表示最后一位,-2表示倒数第二位。
/** * @Title: testList * @Description: 测试操作List的方法 * @author: sdd * @date: 2018年9月1日 下午9:30:43 * @return: void * @throws Exception */ @Test public void testList() throws Exception { //获取Jedis对象 Jedis jedis = JedisUtils.getJedis(); String key = "jedis-demo:testlist5"; //添加元素 jedis.lpush(key, "test001","test002","test003","test004"); //修改元素:只能根据索引删除 jedis.lset(key, 0, "testList001"); //删除第一个元素:只能删除第一个或最后一个 jedis.lpop(key); //遍历元素 List<String> list = jedis.lrange(key, 0, -1); Iterator<String> iterator = list.iterator(); while(iterator.hasNext()) { System.out.println(iterator.next()); } //归还连接 JedisUtils.returnJedis(); }
测试Set
注意:set的本质是哈希表,元素是唯一的,jedis提供的api中并不支持按索引或值更新元素。
/** * @Title: testSet * @Description: 测试操作Set的方法 * @author: sdd * @date: 2018年9月1日 下午9:30:43 * @return: void * @throws Exception */ @Test public void testSet() throws Exception { //获取Jedis对象 Jedis jedis = JedisUtils.getJedis(); String key = "jedis-demo:testSet"; //添加元素 jedis.sadd(key, "test001","test002","test004","test003"); //更新元素:不能更新元素 //删除元素 jedis.srem(key, "test001"); //判断元素是否存在 System.out.println(jedis.sismember(key, "test001")); //遍历元素 Set<String> smembers = jedis.smembers(key); Iterator<String> iterator = smembers.iterator(); while(iterator.hasNext()) { System.out.println(iterator.next()); } //归还连接 JedisUtils.returnJedis(); }
测试Sorted Set
/** * @Title: testSortedSet * @Description: 测试操作Sorted Set的方法 * @author: sdd * @date: 2018年9月1日 下午9:30:43 * @return: void * @throws Exception */ @Test public void testSortedSet() throws Exception { //获取Jedis对象 Jedis jedis = JedisUtils.getJedis(); String key = "jedis-demo:testSortedSet"; //添加元素 jedis.zadd(key, 1D, "test001"); jedis.zadd(key, 2D, "test002"); jedis.zadd(key, 4D, "test004"); jedis.zadd(key, 3D, "test003"); //更新元素 jedis.zadd(key, 5D, "test001"); //删除元素 jedis.zrem(key, "test002"); //查找指定元素的score System.out.println(jedis.zscore(key,"test003")); //查找指定指定元素的排名 System.out.println(jedis.zrank(key,"test003")); //遍历元素 Set<String> smembers = jedis.zrange(key, 0, -1); Iterator<String> iterator = smembers.iterator(); while(iterator.hasNext()) { System.out.println(iterator.next()); } //归还连接 JedisUtils.returnJedis(); }
测试Hash
/** * @Title: testHash * @Description: 测试操作Hash的方法 * @author: sdd * @date: 2018年9月1日 下午9:30:43 * @return: void * @throws Exception */ @Test public void testHash() throws Exception { //获取Jedis对象 Jedis jedis = JedisUtils.getJedis(); String key = "jedis-demo:testHash"; //添加元素 jedis.hset(key, "id", "1"); jedis.hset(key, "name", "zzs"); jedis.hset(key, "age", "18"); jedis.hset(key, "address", "北京"); //更新元素 jedis.hset(key, "age", "19"); //删除元素 jedis.hdel(key, "id"); //获取指定元素的值 System.out.println(jedis.hget(key, "address")); //遍历元素 Map<String, String> map = jedis.hgetAll(key); for(Entry<String, String> entry : map.entrySet()) { System.out.println(entry.getKey()+"="+entry.getValue()); } //归还连接 JedisUtils.returnJedis(); }
测试Key
/** * @Title: testKey * @Description: 测试操作key的方法 * @author: sdd * @date: 2018年9月1日 下午9:30:43 * @return: void * @throws Exception */ @Test public void testKey() throws Exception { //获取Jedis对象 Jedis jedis = JedisUtils.getJedis(); String key = "jedis-demo:testKey"; //添加键值对 jedis.set(key, "test001"); //设置key的过期时间 jedis.expire(key, 5); Thread.sleep(3000); //查询key的剩余时间 System.out.println(jedis.ttl(key)); //清除key的过期时间 jedis.persist(key); System.out.println(jedis.ttl(key)); //归还连接 JedisUtils.returnJedis(); }