package org.hepx.jgt.cache.memcache;
import net.spy.memcached.MemcachedClient;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* 对SpyMemcached Client的二次封装,提供常用函数的同步与异步操作封装.
* <p/>
* 未提供封装的函数可直接调用getClient()取出Spy的原版MemcachedClient来使用.
*
* @author calvin
*/
public class SpyMemcachedClient implements DisposableBean {
private static Logger logger = LoggerFactory.getLogger(SpyMemcachedClient.class);
private MemcachedClient memcachedClient;
private long shutdownTimeout = 2500;//延迟时间
private long updateTimeout = 2000; //操作超时
private int defaultExpiredTime = 0;//默认不过期,注意:memcache默认是30天,并不是永不过期
@Override
public void destroy() throws Exception {
if (memcachedClient != null) {
memcachedClient.shutdown(shutdownTimeout, TimeUnit.MILLISECONDS);
}
}
/**
* 从缓存中取值
* 转换结果类型并屏蔽异常, 仅返回Null
*
* @param key
* @param <T>
* @return
*/
public <T> T get(String key) {
try {
return (T) memcachedClient.get(key);
} catch (RuntimeException e) {
handleException(e, key);
return null;
}
}
/**
* GetBulk方法, 转换结果类型并屏蔽异常.
*
* @param keys
* @param <T>
* @return
*/
public <T> Map<String, T> getBulk(Collection<String> keys) {
try {
return (Map<String, T>) memcachedClient.getBulk(keys);
} catch (RuntimeException e) {
handleException(e, StringUtils.join(keys, ","));
return null;
}
}
/**
* 异步Set方法, 不考虑执行结果.采用默认过期时间
*
* @param key
* @param value
*/
public void set(String key, Object value) {
memcachedClient.set(key, defaultExpiredTime, value);
}
/**
* 异步Set方法, 不考虑执行结果.
*
* @param key
* @param expiredTime
* @param value
*/
public void set(String key, int expiredTime, Object value) {
memcachedClient.set(key, expiredTime, value);
}
/**
* 安全的Set方法, 保证在updateTimeout秒内返回执行结果, 否则返回false并取消操作。采用默认过期时间
*
* @param key
* @param value
* @return
*/
public boolean safeSet(String key, Object value) {
Future<Boolean> future = memcachedClient.set(key, defaultExpiredTime, value);
try {
return future.get(updateTimeout, TimeUnit.MILLISECONDS);
} catch (Exception e) {
future.cancel(false);
}
return false;
}
/**
* 安全的Set方法, 保证在updateTimeout秒内返回执行结果, 否则返回false并取消操作
*
* @param key
* @param expiredTime
* @param value
* @return
*/
public boolean safeSet(String key, int expiredTime, Object value) {
Future<Boolean> future = memcachedClient.set(key, expiredTime, value);
try {
return future.get(updateTimeout, TimeUnit.MILLISECONDS);
} catch (Exception e) {
future.cancel(false);
}
return false;
}
/**
* 异步 Delete方法, 不考虑执行结果.
*
* @param key
*/
public void delete(String key) {
memcachedClient.delete(key);
}
/**
* 安全的Delete方法, 保证在updateTimeout秒内返回执行结果, 否则返回false并取消操作.
*
* @param key
* @return
*/
public boolean safeDelete(String key) {
Future<Boolean> future = memcachedClient.delete(key);
try {
return future.get(updateTimeout, TimeUnit.MILLISECONDS);
} catch (Exception e) {
future.cancel(false);
}
return false;
}
/**
* 替换缓存中的内容,不考虑执行结果,采用默认过期时间
*
* @param key
* @param value
*/
public void replace(String key, Object value) {
memcachedClient.replace(key, defaultExpiredTime, value);
}
/**
* 替换缓存中的内容,不考虑执行结果
*
* @param key
* @param expiredTime
* @param value
*/
public void replace(String key, int expiredTime, Object value) {
memcachedClient.replace(key, expiredTime, value);
}
/**
* 安全的替换方法,保证在updateTimeout秒内返回执行结果, 否则返回false并取消操作.采用默认过期时间
*
* @param key
* @param value
* @return
*/
public boolean safeReplace(String key, Object value) {
Future<Boolean> future = memcachedClient.replace(key, defaultExpiredTime, value);
try {
return future.get(updateTimeout, TimeUnit.MILLISECONDS);
} catch (Exception e) {
future.cancel(false);
}
return false;
}
/**
* 安全的替换方法,保证在updateTimeout秒内返回执行结果, 否则返回false并取消操作.
*
* @param key
* @param expiredTime
* @param value
* @return
*/
public boolean safeReplace(String key, int expiredTime, Object value) {
Future<Boolean> future = memcachedClient.replace(key, expiredTime, value);
try {
return future.get(updateTimeout, TimeUnit.MILLISECONDS);
} catch (Exception e) {
future.cancel(false);
}
return false;
}
/**
* Incr方法.
*/
public long incr(String key, int by, long defaultValue) {
return memcachedClient.incr(key, by, defaultValue);
}
/**
* Decr方法.
*/
public long decr(String key, int by, long defaultValue) {
return memcachedClient.decr(key, by, defaultValue);
}
/**
* 异步Incr方法, 不支持默认值, 若key不存在返回-1.
*/
public Future<Long> asyncIncr(String key, int by) {
return memcachedClient.asyncIncr(key, by);
}
/**
* 异步Decr方法, 不支持默认值, 若key不存在返回-1.
*/
public Future<Long> asyncDecr(String key, int by) {
return memcachedClient.asyncDecr(key, by);
}
private void handleException(Exception e, String key) {
logger.warn("spymemcached client receive an exception with key:" + key, e);
}
public MemcachedClient getMemcachedClient() {
return memcachedClient;
}
public void setMemcachedClient(MemcachedClient memcachedClient) {
this.memcachedClient = memcachedClient;
}
public void setUpdateTimeout(long updateTimeout) {
this.updateTimeout = updateTimeout;
}
public void setShutdownTimeout(long shutdownTimeout) {
this.shutdownTimeout = shutdownTimeout;
}
public int getDefaultExpiredTime() {
return defaultExpiredTime;
}
public void setDefaultExpiredTime(int defaultExpiredTime) {
this.defaultExpiredTime = defaultExpiredTime;
}
public long getUpdateTimeout() {
return updateTimeout;
}
public long getShutdownTimeout() {
return shutdownTimeout;
}
/* public static void main(String[] args) {
try {
MemcachedClient c = new MemcachedClient(new InetSocketAddress("192.168.1.174", 11211));
c.set("someKey", 60, "aaaa");
String myObject = (String) c.get("someKey");
Thread.sleep(30 * 1000);
System.out.println(myObject);
Thread.sleep(31 * 1000);
String myObject2 = (String) c.get("someKey");
c.shutdown();
System.out.println(myObject2);
} catch (Exception e) {
e.printStackTrace();
}
}*/
}