com.github.fartherp.framework.cache.redis.RedisClient Maven / Gradle / Ivy
/*
* Copyright (c) 2017. CK. All rights reserved.
*/
package com.github.fartherp.framework.cache.redis;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.ReflectionUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Protocol;
import redis.clients.util.SafeEncoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* redis客户端
* Author: CK
* Date: 2015/12/1
*/
public class RedisClient implements InitializingBean, DisposableBean {
/**
* 日志类
*/
private final Log LOGGER = LogFactory.getLog(getClass());
/**
* redis 操作成功返回的常量
*/
private static final String OPERATION_SUCCESS = "OK";
/**
* 缓存名称
*/
private String cacheName = "default";
/**
* redis server ip
*/
private String redisServer;
/**
* redis server authenticate key
*/
private String redisAuthKey;
/**
* {@link JedisPool} instance
*/
private JedisPool jedisPool;
/**
* redis端口
*/
private int port = Protocol.DEFAULT_PORT;
/**
* If the pool in ObjectPool is exhausted (no available idle instances and
* no capacity to create new ones), this method will either block
* (WHEN_EXHAUSTED_BLOCK == 1), throw a NoSuchElementException
* (WHEN_EXHAUSTED_FAIL == 0), or grow (WHEN_EXHAUSTED_GROW == 2 - ignoring
* maxActive). The length of time that this method will block when
* whenExhaustedAction == WHEN_EXHAUSTED_BLOCK is determined by the maxWait
* property.
*/
private byte whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;
/**
* 实际对象池实例
*/
private GenericObjectPool realPool;
public void afterPropertiesSet() throws Exception {
GenericObjectPoolConfig poolConfig = PoolConfigUtils.genericObjectPoolConfig();
jedisPool = new JedisPool(poolConfig, redisServer, port, PoolConfigUtils.timeout, redisAuthKey);
realPool = getRealPoolInstance();
}
/**
* 获取实际的对象池实例
*
* @return 实际的对象池实例
*/
protected GenericObjectPool getRealPoolInstance() {
Field internalPoolField = ReflectionUtils.findField(JedisPool.class, "internalPool", GenericObjectPool.class);
if (internalPoolField != null) {
internalPoolField.setAccessible(true);
return (GenericObjectPool) ReflectionUtils.getField(internalPoolField, jedisPool);
}
return null;
}
/**
* get value
* return null if key did not exist
*
* @param key cache key
* @return cache value
* @throws Exception in case of access redis server exception
*/
public Object get(String key) throws Exception {
byte[] data = null;
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
data = jedis.get(SafeEncoder.encode(key));
} catch (Exception e) {
// do jedis.quit() and jedis.disconnect()
this.jedisPool.returnBrokenResource(jedis);
throw e;
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
return this.deserialize(data);
}
/**
* do ping action
*
* @return ping result
* @throws Exception in case of access redis server exception
*/
public String ping() throws Exception {
String res = null;
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
res = jedis.ping();
} catch (Exception e) {
// do jedis.quit() and jedis.disconnect()
this.jedisPool.returnBrokenResource(jedis);
throw e;
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
return res;
}
/**
* value set
* The string can't be longer than 1073741824 bytes (1 GB).
*
* @param key cache key
* @param value value
* @param expiration expiration time 超时时间
* @return false if redis did not execute the option
* @throws Exception in case of access redis server exception
*/
public boolean set(String key, Object value, Integer expiration) throws Exception {
String result = "";
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
if (expiration > 0) {
result = jedis.setex(SafeEncoder.encode(key), expiration, serialize(value));
} else {
result = jedis.set(SafeEncoder.encode(key), serialize(value));
}
LOGGER.info("set key:" + key + " value:" + value);
return OPERATION_SUCCESS.equalsIgnoreCase(result);
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
this.jedisPool.returnBrokenResource(jedis);
throw e;
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
}
/**
* set a value without expiration
*
* @param key cache key
* @param value cache value
* @return false if redis did not execute the option
* @throws Exception in case of access redis server exception
*/
public boolean set(String key, Object value) throws Exception {
return this.set(key, value, -1);
}
/**
* add if not exists
*
* @param key cache key
* @param value cache value
* @param expiration expiration time
* @return false if redis did not execute the option
* @throws Exception in case of access redis server exception
*/
public boolean add(String key, Object value, Integer expiration) throws Exception {
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
// 操作setnx与expire成功返回1,失败返回0,仅当均返回1时,实际操作成功
Long result = jedis.setnx(SafeEncoder.encode(key), serialize(value));
if (expiration > 0) {
result = result & jedis.expire(key, expiration);
}
if (result == 1L) {
LOGGER.info("add key:" + key + " value:" + value);
} else {
LOGGER.info("add key: " + key + " failed, key has already exists! ");
}
return result == 1L;
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
this.jedisPool.returnBrokenResource(jedis);
throw e;
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
}
/**
* add if not exists
*
* @param key cache eky
* @param value cache value
* @return false if redis did not execute the option
* @throws Exception in case of access redis server exception
*/
public boolean add(String key, Object value) throws Exception {
return this.add(key, value, -1);
}
/**
* Test if the specified key exists.
*
* @param key cache key
* @return true if exist
* @throws Exception in case of access redis server exception
*/
public boolean exists(String key) throws Exception {
boolean isExist = false;
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
isExist = jedis.exists(SafeEncoder.encode(key));
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
this.jedisPool.returnBrokenResource(jedis);
throw e;
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
return isExist;
}
/**
* Remove the specified keys.
*
* @param key cache key
* @return false if redis did not execute the option
*/
public boolean delete(String key) {
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
jedis.del(SafeEncoder.encode(key));
LOGGER.info("delete key:" + key);
return true;
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
this.jedisPool.returnBrokenResource(jedis);
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
return false;
}
/**
* to add expire time in seconds
*
* @param key cache key
* @param seconds expiration in seconds
* @return false if redis did not execute the option
*/
public boolean expire(String key, int seconds) {
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
jedis.expire(SafeEncoder.encode(key), seconds);
LOGGER.info("expire key:" + key + " time after " + seconds + " seconds.");
return true;
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
this.jedisPool.returnBrokenResource(jedis);
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
return false;
}
/**
* Delete all the keys of all the existing databases, not just the currently
* selected one.
*
* @return false if redis did not execute the option
*/
public boolean flushall() {
String result = "";
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
result = jedis.flushAll();
LOGGER.info("redis client name: " + this.getCacheName() + " flushall.");
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
this.jedisPool.returnBrokenResource(jedis);
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
return OPERATION_SUCCESS.equalsIgnoreCase(result);
}
/**
* do destroy jedis pool
*
* @see #jedisPool
*/
public void shutdown() {
try {
this.jedisPool.destroy();
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
}
}
/**
* Get the bytes representing the given serialized object.
*
* @param o target value
* @return byte array
*/
protected byte[] serialize(Object o) {
if (o == null) {
// throw new NullPointerException("Can't serialize null");
return new byte[0];
}
byte[] rv = null;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(o);
os.close();
bos.close();
rv = bos.toByteArray();
} catch (IOException e) {
throw new IllegalArgumentException("Non-serializable object", e);
}
return rv;
}
/**
* Get the object represented by the given serialized bytes.
*
* @param in byte array
* @return result after deserialized
*/
protected Object deserialize(byte[] in) {
Object rv = null;
try {
if (in != null) {
ByteArrayInputStream bis = new ByteArrayInputStream(in);
ObjectInputStream is = new ObjectInputStream(bis);
rv = is.readObject();
is.close();
bis.close();
}
} catch (IOException e) {
LOGGER.warn("Caught IOException decoding %d bytes of data", e);
} catch (ClassNotFoundException e) {
LOGGER.warn("Caught CNFE decoding %d bytes of data", e);
}
return rv;
}
/**
* add value to set
*
* @param key cache key of set
* @param field element key
* @param fieldValue value
* @throws Exception in case of access redis server exception
*/
public void hput(String key, String field, Serializable fieldValue) throws Exception {
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
jedis.hset(SafeEncoder.encode(key), SafeEncoder.encode(field), serialize(fieldValue));
LOGGER.info("hset key:" + key + " field:" + field);
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
this.jedisPool.returnBrokenResource(jedis);
throw e;
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
}
/**
* get value by element key from set
*
* @param key cache key of set
* @param field element key
* @return value
*/
public Object hget(String key, String field) {
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
byte[] value = jedis.hget(SafeEncoder.encode(key), SafeEncoder.encode(field));
LOGGER.info("hget key:" + key + " field:" + field);
return deserialize(value);
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
this.jedisPool.returnBrokenResource(jedis);
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
return null;
}
/**
* delete element from set
*
* @param key cache key of set
* @param field element key
* @return true if success
* @throws Exception in case of access redis server exception
*/
public boolean hdel(String key, String field) throws Exception {
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
long value = jedis.hdel(SafeEncoder.encode(key), SafeEncoder.encode(field));
LOGGER.info("hget key:" + key + " field:" + field);
return value == 1;
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
this.jedisPool.returnBrokenResource(jedis);
throw e;
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
}
/**
* get keys from set
*
* @param key cache key
* @return keys from set
* @throws Exception in case of access redis server exception
*/
public Set hKeys(String key) throws Exception {
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
Set hkeys = jedis.hkeys(SafeEncoder.encode(key));
LOGGER.info("hkeys key:" + key);
if (CollectionUtils.isEmpty(hkeys)) {
return new HashSet(1);
} else {
Set keys = new HashSet(hkeys.size());
for (byte[] bb : hkeys) {
keys.add(SafeEncoder.encode(bb));
}
return keys;
}
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
this.jedisPool.returnBrokenResource(jedis);
throw e;
} finally {
if (jedis != null) {
this.jedisPool.returnResource(jedis);
}
}
}
/**
* get values from set
*
* @param key cache key
* @return value list
* @throws Exception in case of access redis server exception
*/
public List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy