Redis在Java中的实现是Jedis,需要导入jedis.jar、commons-net.jar(具体版本自己选择)以及commons-pool2x.jar(commons-pool用于Jedis连接池的创建,如果使用了连接池commons-pool包的版本不能低于2x,这是因为使用了org.apache.commons.pool2下面的类,这个包在2x版本才有)。
一、创建Jedis连接池生成Jedis连接
1、连接池的配置,可以放在单独的properties文件,便于修改
JedisPool.properties:
#服务器IP ADDR=127.0.0.1 #redis端口号 PORT=6379 #访问密码 AUTH= #可用最大连接数 MAX_TOTAL=1000 #最大空闲连接数 MAX_IDLE=100 #最长等待时间 MAX_WAIT=10000 #超时时间 TIMEOUT=60000 #在获取redis连接时,自动检测连接是否有效 TEST_ON_BORROW=true
2、创建生成Jedis连接的类
redis.clients.jedis.JedisPoolConfig:存放配置信息
redis.clients.jedis.JedisPool:加载配置信息创建连接池
RedisClient.java:
import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.InputStream; import java.util.Properties; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class RedisClient { //连接池 private static JedisPool jedisPool; static{ try { InputStream is=new BufferedInputStream(new FileInputStream("src/com/teriste/resources/JedisPool.properties")); Properties properties=new Properties(); properties.load(is); JedisPoolConfig config=new JedisPoolConfig(); config.setMaxTotal(Integer.parseInt(properties.getProperty("MAX_TOTAL"))); config.setMaxIdle(Integer.parseInt(properties.getProperty("MAX_IDLE"))); config.setMaxWaitMillis(Integer.parseInt(properties.getProperty("MAX_WAIT"))); config.setTestOnBorrow(Boolean.getBoolean(properties.getProperty("TEST_ON_BORROW"))); //这里我的redis数据库没有设置密码所以不需要密码参数,否则可以添加密码参数 //jedisPool=new JedisPool(config,ADDR,PORT,TIMEOUT,AUTH); jedisPool=new JedisPool(config,properties.getProperty("ADDR"),Integer.parseInt(properties.getProperty("PORT")),Integer.parseInt(properties.getProperty("TIMEOUT"))); } catch (Exception e) { e.printStackTrace(); } } //获取Redis资源 public synchronized static Jedis getJedis(){ try { if (jedisPool!=null) { Jedis jedis=jedisPool.getResource(); return jedis; }else { return null; } } catch (Exception e) { e.printStackTrace(); } return null; } //释放redis资源 @SuppressWarnings("deprecation") public synchronized static void releaseConn(Jedis jedis){ if (jedisPool!=null) { jedisPool.returnResource(jedis); } } }
二、Jedis操作Redis基本数据类型
import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import redis.clients.jedis.Jedis; import redis.clients.jedis.BinaryClient.LIST_POSITION; import redis.clients.jedis.Tuple; public class TestJedis { public static void main(String[] args) { System.out.println("********操作String类型************"); //操作String类型 operateString(); System.out.println("********操作Hash类型************"); //操作Hash类型 operateHash(); System.out.println("********操作List类型************"); //操作List类型 operateList(); System.out.println("********操作Set类型数据************"); //操作Set类型数据 operateSet(); System.out.println("********操作ZSet类型数据************"); //操作有序集合类型 operateSortedSet(); System.out.println("********Jedis事务处理************"); //Jedis事务处理 jedisTransaction(); } }
操作String类型数据:
/** * String类型基本操作 */ public static void operateString(){ Jedis jedis=RedisClient.getJedis(); try { //清空数据库(谨慎操作),这里只是为了便于观察输出结果 //jedis.flushDB(); //设置键值 jedis.set("test", "testString"); System.out.println("Save test value="+jedis.get("test")); //在键值后追加内容 jedis.append("test", " this is append string"); System.out.println("Append string to test:"+jedis.get("test")); //根据键获取值 String test=jedis.get("test"); System.out.println("find string test:"+test); //删除指定键 jedis.del("test"); System.out.println("delete string test:"+jedis.get("test")); //判断键是否存在 boolean isNotExists=jedis.exists("test"); System.out.println("test is Exists?:"+(isNotExists?"是":"否")); //如果键值是整数可以进行加减操作,否则会报错 jedis.set("testInt", "0"); jedis.incr("testInt"); System.out.println("new testInt:"+jedis.get("testInt")); jedis.del("testInt"); //设置键的生存时间 jedis.set("testtest", "testTTL"); jedis.expire("testtest", 30); Thread.sleep(10000); //获取键的剩余生存时间 System.out.println(jedis.ttl("testtest")); } catch (Exception e) { e.printStackTrace(); } finally{ RedisClient.releaseConn(jedis); } }
输出结果如下:
********操作String类型************ Save test value=testString Append string to test:testString this is append string find string test:testString this is append string delete string test:null test is Exists?:否 new testInt:1 20
操作Hash数据类型:
public static void operateHash(){ Jedis jedis=RedisClient.getJedis(); try { //清空数据库(谨慎操作),这里只是为了便于观察输出结果 //jedis.flushDB(); Map<String, String> map=new HashMap<String, String>(); map.put("name", "张三"); map.put("sex", "男"); map.put("age", "24"); //添加hash类型数据 jedis.hmset("person", map); //获取该键包含的所有键值对 System.out.println("add hash map to jedis:"+jedis.hgetAll("person")); //获取该键包含的指定键值 System.out.println("get key's value:"+jedis.hget("person", "name")); //判断键是否存在 boolean isExists=jedis.hexists("person", "professional"); System.out.println("Key professional is in name?"+(isExists?"是":"否")); //获取该散列包含的键的个数 long hlen=jedis.hlen("person"); System.out.println("key person's length is:"+hlen); //向散列中添加键值 jedis.hset("person", "professional", "软件工程师"); System.out.println("get updated persion:"+jedis.hgetAll("person")); //如果键值是整型,可以加减该键值 jedis.hincrBy("person", "age",2); System.out.println("get updated age:"+jedis.hget("person","age")); //删除散列中的键 jedis.hdel("person", "professional"); isExists=jedis.hexists("person", "professional"); System.out.println("person's professional is exists?"+(isExists?"是":"否")); } catch (Exception e) { e.printStackTrace(); } finally{ RedisClient.releaseConn(jedis); } }
输出结果如下:
********操作Hash类型************ add hash map to jedis:{sex=男, name=张三, age=24} get key's value:张三 Key professional is in name?否 key person's length is:3 get updated persion:{professional=软件工程师, sex=男, name=张三, age=24} get updated age:26 person's professional is exists?否
操作List类型:
public static void operateList(){ Jedis jedis=RedisClient.getJedis(); try { //清空数据库(谨慎操作),这里只是为了便于观察输出结果 //jedis.flushDB(); //先删除之前创建的List避免之前存入的值影响输出结果 jedis.del("redisList"); //从列表左侧增加元素,lpush()方法参数列表是可变参数 jedis.lpush("redisList","Redis","Mysql"); jedis.lpushx("redisList", "Oracle"); //lpushx()和rpushx()方法只能插入已存在的List中,如果键不存在就不进行任何操作 jedis.lpushx("RedisList", "Oracle"); System.out.println("------"+jedis.lrange("redisList", 0, -1)); //从列表右侧插入元素 jedis.rpush("redisList", "Mongodb"); jedis.rpushx("redisList", "DB2"); //linsert()可以在指定值后插入元素,如果该元素有多个,只在第一个后面插入 jedis.linsert("redisList", LIST_POSITION.AFTER, "Mysql", "Mysql"); jedis.linsert("redisList", LIST_POSITION.AFTER, "Mysql", "DB2"); System.out.println(jedis.lrange("redisList", 0, -1)); //lrange()方法可以遍历List中的元素返回list,当开始坐标是0结束坐标是-1时表示遍历整个redisList List<String>redisList=jedis.lrange("redisList", 0, -1); System.out.print("Element in redisList:["); for (int i = 0; i < redisList.size(); i++ ) { System.out.print(redisList.get(i)+" "); } System.out.println("]"); //根据指定索引获取值,索引为正从左往右获取,索引为负从右向左获取 String index2=jedis.lindex("redisList", 2); String index_2=jedis.lindex("redisList", -2); System.out.println("from left to right the index 2 is:"+index2); System.out.println("from right to left the index 2 is:"+index_2); //修改列表指定索引元素,若不存在则报错 jedis.lset("redisList", 1, "updateValue"); System.out.println("update index 1 value:"+jedis.lindex("redisList", 1)); //删除列表左侧头部元素 String lrem=jedis.lpop("redisList"); System.out.println("Remove left top element:"+lrem); //删除列表右侧头部元素 String rrem=jedis.rpop("redisList"); System.out.println("Remove right top element:"+rrem); //去除索引范围外的元素 String ltrim=jedis.ltrim("redisList", 1, 3); System.out.println("trim redisList 1-3 other element:"+ltrim); System.out.println("find redisList:"+jedis.lrange("redisList", 0, -1)); //移出指定值的索引位置,如果count>0从左往右删除count个该元素,如果count=0删除列表中全部该元素,如果count<0从右往左删除count个该元素 jedis.lrem("redisList", 1, "DB2"); System.out.println("remove from left to right DB2 in redisList:"+jedis.lrange("redisList", 0, -1)); } catch (Exception e) { e.printStackTrace(); } finally{ RedisClient.releaseConn(jedis); } }
输出结果如下:
********操作List类型************ ------[Oracle, Mysql, Redis] [Oracle, Mysql, DB2, Mysql, Redis, Mongodb, DB2] Element in redisList:[Oracle Mysql DB2 Mysql Redis Mongodb DB2 ] from left to right the index 2 is:DB2 from right to left the index 2 is:Mongodb update index 1 value:updateValue Remove left top element:Oracle Remove right top element:DB2 trim redisList 1-3 other element:OK find redisList:[DB2, Mysql, Redis] remove from left to right DB2 in redisList:[Mysql, Redis]
操作Set类型数据:
public static void operateSet(){ Jedis jedis=RedisClient.getJedis(); try { //清空数据库(谨慎操作) //jedis.flushDB(); //添加元素,注意与List类型的区别,Set不会存储重复元素,比较适合做博客标签等应用场景 jedis.sadd("redisSet", "Redis"); jedis.sadd("redisSet", "Redis","Mysql"); jedis.sadd("redisSet", "Redis","Mysql","Oracle","DB2"); //查询 Set<String> redisSet=jedis.smembers("redisSet"); System.out.print("Element in set:["); Iterator<String> iterator=redisSet.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next()+" "); } System.out.println("]"); //Set集合元素个数 long slen=jedis.scard("redisSet"); System.out.println("redisSet's size is:"+slen); //判断元素是否存在于集合内 boolean isExists=jedis.sismember("redisSet", "Mysql"); System.out.println("Mysql is in redisSet?"+(isExists?"是":"否")); //集合运算 //并集 jedis.sadd("redisSet2", "Redis","Mysql","SqlServer"); Set<String> unionSet=jedis.sunion("redisSet","redisSet2"); System.out.println("union result:"+unionSet); //并集结果存入redisSet集合 System.out.println("unionSet in Redis:"+jedis.sunionstore("unionSet", "redisSet","redisSet2")); //交集 Set<String> interSet=jedis.sinter("redisSet","redisSet2"); System.out.println("interSet result:"+interSet); //交集结果存入redisSet集合 System.out.println("interSet in Redis:"+jedis.sinterstore("interSet", "redisSet","redisSet2")); //差集 Set<String> diffSet=jedis.sdiff("redisSet","redisSet2"); System.out.println("diffSet result:"+diffSet); //差集结果存入redisSet集合 System.out.println("diffSet in Redis:"+jedis.sdiffstore("diffSet","redisSet","redisSet2")); //自交就相当于去除集合中所以元素 interSet=jedis.sinter("interSet","interSet"); //删除指定集合元素 jedis.srem("redisSet", "Mysql"); //将一个集合中的元素移入另一个集合中 jedis.smove("redisSet", "redisSet2", "DB2"); System.out.println("Element in redisSet is:"+jedis.smembers("redisSet")); System.out.println("Element in redisSet2 is:"+jedis.smembers("redisSet2")); } catch (Exception e) { e.printStackTrace(); } finally{ RedisClient.releaseConn(jedis); } }
输出结果如下:
********操作Set类型数据************ Element in set:[DB2 Mysql Oracle Redis ] redisSet's size is:4 Mysql is in redisSet?是 union result:[SqlServer, DB2, Mysql, Oracle, Redis] unionSet in Redis:5 interSet result:[DB2, Redis, Mysql] interSet in Redis:3 diffSet result:[Oracle] diffSet in Redis:1 Element in redisSet is:[Oracle, Redis] Element in redisSet2 is:[SqlServer, DB2, Redis, Mysql]
操作有序集合类型:
public static void operateSortedSet(){ Jedis jedis=RedisClient.getJedis(); try { //清空数据库(谨慎操作),这里只是为了便于观察输出结果 //jedis.flushDB(); //增加 jedis.zadd("scores", 69,"zhangsan"); jedis.zadd("scores", 83,"lisi"); jedis.zadd("scores", 73,"wanger"); //zadd()方法也有重载的传入map类型,分数是Double类型 Map<String, Double> scoresMap=new HashMap<String, Double>(); scoresMap.put("zhaosi", new Double(59)); scoresMap.put("qianyi", new Double(99)); jedis.zadd("scores",scoresMap); //查询 System.out.println("按照分数从低到高查询zrange:"+jedis.zrange("scores", 0, -1)); System.out.println("按照分数从高到低查询zrange:"+jedis.zrevrange("scores", 0, -1)); //使用Set存储元组遍历元组内分数和元素 Set<Tuple> sortSet=jedis.zrangeWithScores("scores", 0, -1); Iterator<Tuple>iterator=sortSet.iterator(); while(iterator.hasNext()){ Tuple tuple=iterator.next(); System.out.println(tuple.getScore()+":"+tuple.getElement()); } //根据分数范围查询元素(60<=score<=100) Set<String> zrangeByScore=jedis.zrangeByScore("scores", new Double(60), new Double(100)); System.out.print("zrangeByScore(60-100):"); for (Iterator<String> it=zrangeByScore.iterator();it.hasNext();) { System.out.print(it.next()+" "); } System.out.println(); //查询指定zset键的元素个数 long setcount=jedis.zcard("scores"); //查询指定分数范围内(60<=score<=100)zset键的元素个数 long rangeCount=jedis.zcount("scores", 60, 100); //查询指定元素的下标,不存在则返回null long zrank=jedis.zrank("scores", "zhangsan"); //查询指定元素的分数,不存在则返回null Double zscore=jedis.zscore("scores", "zhangsan"); System.out.println("scores's size:"+setcount+"\nrangeCount(60-100):"+rangeCount+"\nzrank(zhangsan):"+zrank+"\nzscore(zhangsan):"+zscore); //修改分数 Double zincrby=jedis.zincrby("scores", 99, "zhangsan"); System.out.println("zincrby:"+zincrby); //删除指定元素 jedis.zrem("scores", "zhangsan"); //根据分数删除 jedis.zremrangeByScore("scores", 60, 80); System.out.println("scores's elements:"+jedis.zrange("scores", 0, -1)); } catch (Exception e) { e.printStackTrace(); } finally{ RedisClient.releaseConn(jedis); } }
输出结果如下:
********操作ZSet类型数据************ 按照分数从低到高查询zrange:[zhaosi, zhangsan, wanger, lisi, qianyi] 按照分数从高到低查询zrange:[qianyi, lisi, wanger, zhangsan, zhaosi] 59.0:zhaosi 69.0:zhangsan 73.0:wanger 83.0:lisi 99.0:qianyi zrangeByScore(60-100):zhangsan wanger lisi qianyi scores's size:5 rangeCount(60-100):4 zrank(zhangsan):1 zscore(zhangsan):69.0 zincrby:168.0 scores's elements:[zhaosi, lisi, qianyi]
Jedis事务处理:
使用MULTI开启事务,EXEC提交事务。
在执行事务期间使用discard可以回滚事务
使用watch可以监视键,如果在事务之前和事务期间都修改同一键值,那么在事务之前的修改生效,事务期间的修改无效。
/** * 执行逻辑:Jedis事务开始后,如果是Jedis内部方法错误,执行exec不影响其他正常语句的执行结果,执行成功的结果仍能提交到数据库。 * 如果是Java语法错误比如被零除,就进入catch异常处理段,执行Jedis的discard()方法回滚所有事务 * @see */ public static void jedisTransaction(){ Jedis jedis=RedisClient.getJedis(); //开始事务,在执行exec之前都属于事务范围内 Transaction tx=jedis.multi(); boolean errFlag=false; try { tx.set("test1", "value1"); tx.set("test2", "value2"); //对字符串进行算术运算,Jedis内部方法异常 tx.incrBy("test1",2); //下面的运行时异常会导致程序进入catch段,然后执行discard()回滚所有事务 //int x=10/0; 可以解注这条语句查看执行结果,别忘了清空数据库测试 System.out.println("提交事务"); //Jedis内部方法异常,提交事务执行成功的结果会存入redis数据库,执行失败的不执行 List<Object> list=tx.exec(); //每条语句执行结果存入list中 for (int i = 0; i < list.size(); i++ ) { System.out.println("list:"+list.get(i)); } } catch (Exception e) { errFlag=true; //discard()方法在发生异常时可以回滚事务 tx.discard(); e.printStackTrace(); } finally{ if (errFlag==true) { System.out.println("发生异常时提交事务"); tx.exec(); } RedisClient.releaseConn(jedis); } }
输出结果如下:
********Jedis事务处理************ 提交事务 list:OK list:OK list:redis.clients.jedis.exceptions.JedisDataException: ERR value is not an integer or out of range