Cache是个抽象的类,有两个继承的类EhCacheImpl(默认)和MemcachedImpl
- 初始化,在第一次请求时init(),Cache.init()
有两个属性
public static CacheImpl cacheImpl;
public static CacheImpl forcedCacheImpl;
public static void init() {
if(forcedCacheImpl != null) {
cacheImpl = forcedCacheImpl;
return;
}
if (Play.configuration.getProperty("memcached", "disabled").equals("enabled")) {
try {
cacheImpl = MemcachedImpl.getInstance(true);
} catch (Exception e) {
cacheImpl = EhCacheImpl.newInstance();
}
} else {
cacheImpl = EhCacheImpl.newInstance();
}
}
- 基本的一些操作
Cache
public static void add(String key, Object value, String expiration) {
checkSerializable(value);
cacheImpl.add(key, value, Time.parseDuration(expiration));
}
public static boolean safeAdd(String key, Object value, String expiration) {
checkSerializable(value);
return cacheImpl.safeAdd(key, value, Time.parseDuration(expiration));
}
public static void add(String key, Object value) {
checkSerializable(value);
cacheImpl.add(key, value, Time.parseDuration(null));
}
public static void set(String key, Object value, String expiration) {
checkSerializable(value);
cacheImpl.set(key, value, Time.parseDuration(expiration));
}
....
下面来重点讲下EnCacheImpl
属性
private static EhCacheImpl uniqueInstance;
net.sf.ehcache.CacheManager cacheManager;
net.sf.ehcache.Cache cache;
private static final String cacheName = “play”;
//单列模式
初始化
private EhCacheImpl() {
this.cacheManager = CacheManager.create();
this.cacheManager.addCache(cacheName);
this.cache = cacheManager.getCache(cacheName);
}
public static EhCacheImpl newInstance() {
uniqueInstance = new EhCacheImpl();
return uniqueInstance;
}
- 基本的操作
public void add(String key, Object value, int expiration) {
if (cache.get(key) != null) {
return;
}
Element element = new Element(key, value);
element.setTimeToLive(expiration);
cache.put(element);
}
public void clear() {
cache.removeAll();
}
public synchronized long decr(String key, int by) {
Element e = cache.get(key);
if (e == null) {
return -1;
}
long newValue = ((Number) e.getValue()).longValue() - by;
Element newE = new Element(key, newValue);
newE.setTimeToLive(e.getTimeToLive());
cache.put(newE);
return newValue;
}
public void delete(String key) {
cache.remove(key);
}
下面来重点讲解下MemcachedImpl
private static MemcachedImpl uniqueInstance;
net.spy.memcached.MemcachedClient client;
net.spy.memcached.transcoders.SerializingTranscoder tc;
初始化
public static MemcachedImpl getInstance(boolean forceClientInit) throws IOException {
if (uniqueInstance == null) {
uniqueInstance = new MemcachedImpl();
} else if (forceClientInit) {
Thread.interrupted();
uniqueInstance.initClient();
}
return uniqueInstance;
}
初始化
序列化和反序列化
private MemcachedImpl() throws IOException {
tc = new SerializingTranscoder() {
protected Object deserialize(byte[] data) {
try {
return new ObjectInputStream(new ByteArrayInputStream(data)) {
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
return Class.forName(desc.getName(), false, Play.classloader);
}
}.readObject();
} catch (Exception e) {
Logger.error(e, "Could not deserialize");
}
return null;
}
protected byte[] serialize(Object object) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
new ObjectOutputStream(bos).writeObject(object);
return bos.toByteArray();
} catch (IOException e) {
Logger.error(e, "Could not serialize");
}
return null;
}
};
initClient();
}
创建客户端
public void initClient() throws IOException {
System.setProperty("net.spy.log.LoggerImpl", "net.spy.memcached.compat.log.Log4JLogger");
List<InetSocketAddress> addrs;
if (Play.configuration.containsKey("memcached.host")) {
addrs = AddrUtil.getAddresses(Play.configuration.getProperty("memcached.host"));
} else if (Play.configuration.containsKey("memcached.1.host")) {
int nb = 1;
String addresses = "";
while (Play.configuration.containsKey("memcached." + nb + ".host")) {
addresses += Play.configuration.get("memcached." + nb + ".host") + " ";
nb++;
}
addrs = AddrUtil.getAddresses(addresses);
} else {
throw new ConfigurationException("Bad configuration for memcached: missing host(s)");
}
if (Play.configuration.containsKey("memcached.user")) {
String memcacheUser = Play.configuration.getProperty("memcached.user");
String memcachePassword = Play.configuration.getProperty("memcached.password");
if (memcachePassword == null) {
throw new ConfigurationException("Bad configuration for memcached: missing password");
}
// Use plain SASL to connect to memcached
AuthDescriptor ad = new AuthDescriptor(new String[]{"PLAIN"},
new PlainCallbackHandler(memcacheUser, memcachePassword));
ConnectionFactory cf = new ConnectionFactoryBuilder()
.setProtocol(ConnectionFactoryBuilder.Protocol.BINARY)
.setAuthDescriptor(ad)
.build();
client = new MemcachedClient(cf, addrs);
} else {
client = new MemcachedClient(addrs);
}
}
- 基本的操作
public void add(String key, Object value, int expiration) {
client.add(key, expiration, value, tc);
}
public Object get(String key) {
Future<Object> future = client.asyncGet(key, tc);
try {
return future.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
future.cancel(false);
}
return null;
}
public void clear() {
client.flush();
}
public void delete(String key) {
client.delete(key);
}
public Map<String, Object> get(String[] keys) {
Future<Map<String, Object>> future = client.asyncGetBulk(tc, keys);
try {
return future.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
future.cancel(false);
}
return Collections.<String, Object>emptyMap();
}
public long incr(String key, int by) {
return client.incr(key, by, 0);
}
public long decr(String key, int by) {
return client.decr(key, by, 0);
}
public void replace(String key, Object value, int expiration) {
client.replace(key, expiration, value, tc);
}
public boolean safeAdd(String key, Object value, int expiration) {
Future<Boolean> future = client.add(key, expiration, value, tc);
try {
return future.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
future.cancel(false);
}
return false;
}
public boolean safeDelete(String key) {
Future<Boolean> future = client.delete(key);
try {
return future.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
future.cancel(false);
}
return false;
}