* Copyright (c) 2005-2010 springside.org.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
*
* $Id: SpyMemcachedClient.java 1222 2010-09-14 16:44:57Z calvinxiu $
*/
package com.anjuke.one.ssf.memcached;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Future;
import net.spy.memcached.AddrUtil;
import net.spy.memcached.CASResponse;
import net.spy.memcached.CASValue;
import net.spy.memcached.ConnectionFactoryBuilder;
import net.spy.memcached.ConnectionFactoryBuilder.Locator;
import net.spy.memcached.ConnectionFactoryBuilder.Protocol;
import net.spy.memcached.FailureMode;
import net.spy.memcached.HashAlgorithm;
import net.spy.memcached.MemcachedClient;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.log4j.Logger;
import org.apache.myfaces.shared_impl.util.StringUtils;
import org.springframework.beans.factory.DisposableBean;
import com.anjuke.one.constant.Const;
import ajk.com.util.CustomPropertyPlaceholderConfigurer;
/**
* 对SpyMemcached Client的二次封装,提供常用的Get/GetBulk/Set/Delete/Incr/Decr函数的封装.
*
* 未提供封装的函数可直接调用getClient()取出Spy的原版MemcachedClient来使用.
*
*/
public class SpyMemcachedClient implements DisposableBean {
private static Logger logger = Logger.getLogger(SpyMemcachedClient.class);
private static SpyMemcachedClient spyMemcachedClient=new SpyMemcachedClient();
protected MemcachedClient memcachedClient;
/**
* 配置项
* 支持多节点, 以","分割.
* eg. "localhost:11211,localhost:11212"
*/
private static String memcachedNodes = "192.168.1.147:11211";
private boolean isBinaryProtocol = false;
private boolean isConsistentHashing = true;
private static long operationTimeout = 1000; //default value in Spy is 1000ms
static{
Properties configProperties = new Properties();
try{
URL urlP = CustomPropertyPlaceholderConfigurer.getElectResource().getURL();
InputStream is = urlP.openStream();
configProperties.load(is);
is.close();
}catch(Exception ex){
ex.printStackTrace();
}
if(configProperties.get("memcachedNodes") != null)
{
memcachedNodes=configProperties.get("memcachedNodes").toString();
}
if(configProperties.get("operationTimeout") != null)
{
operationTimeout=NumberUtils.toLong(configProperties.get("operationTimeout").toString());
}
try {
spyMemcachedClient.init();
} catch (Exception e) {
e.printStackTrace();
}
}
public void init() throws Exception {
ConnectionFactoryBuilder cfb = new ConnectionFactoryBuilder();
cfb.setFailureMode(FailureMode.Redistribute);
cfb.setDaemon(true);
cfb.setProtocol(isBinaryProtocol ? Protocol.BINARY : Protocol.TEXT);
if (isConsistentHashing) {
cfb.setLocatorType(Locator.CONSISTENT);
cfb.setHashAlg(HashAlgorithm.KETAMA_HASH);
}
cfb.setOpTimeout(operationTimeout);
try {
memcachedClient = new MemcachedClient(cfb.build(), AddrUtil.getAddresses(memcachedNodes));
spyMemcachedClient.memcachedClient=memcachedClient;
} catch (IOException e) {
logger.error("MemcachedClient initilization error: ", e);
throw e;
}
}
/**
* Get方法, 转换结果类型并屏蔽异常,仅返回Null.
*/
public static String get(String key) {
try {
return (String)spyMemcachedClient.memcachedClient.get(key);
} catch (RuntimeException e) {
logger.warn("Get from memcached server fail,key is " + key, e);
return null;
}
}
/**
* Get方法.取出可能包含空白符的Key
* @param expiredTime 过期时间 单位秒
*/
public static String getContainWhiteSpaceKey(String key)
{
key=StringUtils.replace(key," ",Const.WHITE_SPACE_R);
return get(key);
}
public static Object getObject(String key) {
if (spyMemcachedClient != null && key != null && key.trim().length() > 0)
return spyMemcachedClient.get(key);
else
return null;
}
/**
* Set方法.
* @param expiredTime 过期时间 单位秒
*/
public static Future<Boolean> set(String key, int expiredTime, Object value) {
Future<Boolean> result = null;
try{
result = spyMemcachedClient.memcachedClient.set(key, expiredTime, value);
}catch(Exception ex){
ex.printStackTrace();
logger.error(ex.toString());
//throw ex
}
return result;
}
/**
* Set方法.放入可能包含空白符的Key
* @param expiredTime 过期时间 单位秒
*/
public static Future<Boolean> setContainWhiteSpaceKey(String key, int expiredTime, Object value)
{
key=StringUtils.replace(key, " ",Const.WHITE_SPACE_R);
return set(key, expiredTime, value);
}
/**
* Delete方法.
*/
public static Future<Boolean> delete(String key) {
return spyMemcachedClient.memcachedClient.delete(key);
}
/**
* Delete方法.删除可能包含空白符的Key
*/
public static Future<Boolean> deleteContainWhiteSpaceKey(String key)
{
key=StringUtils.replace(key, " ",Const.WHITE_SPACE_R);
return delete(key);
}
/**
* 配合Check and Set的Get方法,转换结果类型并屏蔽异常.
*/
@SuppressWarnings("unchecked")
public <T> CASValue<T> gets(String key) {
try {
return (CASValue<T>) memcachedClient.gets(key);
} catch (RuntimeException e) {
logger.warn("Get from memcached server fail,key is" + key, e);
return null;
}
}
/**
* GetBulk方法, 转换结果类型并屏蔽异常.
*/
@SuppressWarnings("unchecked")
public <T> Map<String, T> getBulk(String... keys) {
try {
return (Map<String, T>) memcachedClient.getBulk(keys);
} catch (RuntimeException e) {
logger.warn("Get from memcached server fail,keys are " + Arrays.toString(keys), e);
return null;
}
}
/**
* GetBulk方法, 转换结果类型并屏蔽异常.
*/
@SuppressWarnings("unchecked")
public <T> Map<String, T> getBulk(Collection<String> keys) {
try {
return (Map<String, T>) memcachedClient.getBulk(keys);
} catch (RuntimeException e) {
logger.warn("Get from memcached server fail,keys are " + keys, e);
return null;
}
}
/**
* Check and Set方法.
*/
public CASResponse cas(String key, long casId, Object value) {
return memcachedClient.cas(key, casId, value);
}
/**
* 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);
}
public void setBinaryProtocol(boolean isBinaryProtocol) {
this.isBinaryProtocol = isBinaryProtocol;
}
public void setConsistentHashing(boolean isConsistentHashing) {
this.isConsistentHashing = isConsistentHashing;
}
@Override
public void destroy() throws Exception {
if (memcachedClient != null) {
memcachedClient.shutdown();
}
}
// Memcached访问函数 //
public MemcachedClient getMemcachedClient() {
return memcachedClient;
}
/**
* SpyMemcachedClient 获取实例
* @return
*/
public static SpyMemcachedClient getSpyMemClient()
{
return spyMemcachedClient;
}
}
##################################################################
package com.anjuke.one.constant;
/**
* 系统常量存放
*
* @author Aliyador create in 2011-7-22
*/
public class Const
{
//memcache key 空白替换
public static final String WHITE_SPACE_R="_V-_5_";
/**keyword 分隔符号*/
public static final String SEPARATORFLG="&";
/**关键字长度(目前暂定为三个关键字长度,包括分隔符长度)*/
public static final int KEYWORDCOUNT=150;
}
##########################################################################
package ajk.com.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.core.io.Resource;
/**
* @ClassName: CustomPropertyPlaceholderConfigurer.java
* @Description: 过滤不存在的Resource (顺序修改为从上至下)
* @author SonicWu
* @date Dec 12, 2009 12:48:58 PM
*/
public class CustomPropertyPlaceholderConfigurer extends
PropertyPlaceholderConfigurer {
private static Resource electResource;
@Override
public void setLocations(Resource[] locations) {
List<Resource> existResourceList = new ArrayList<Resource>();
for (int i = 0; i < locations.length; i++) {
Resource resource = locations[i];
if(resource.exists())
existResourceList.add(resource);
}
//优先顺序为由上至下
Collections.reverse(existResourceList);
if (!existResourceList.isEmpty())
electResource = existResourceList.get(existResourceList.size() - 1);
Resource[] existResource = new Resource[existResourceList.size()];
super.setLocations(existResourceList.toArray(existResource));
}
public static Resource getElectResource() {
return electResource;
}
}