基于memcache的远程缓存工具类如下:
温馨提示:此代码粘贴不可用,依赖于公司扩展的memcached包
先上文件包结构:
cache --远程缓存
checkutils --检查数据正确性
hex --一种对整形字符做转换加密的算法
MemcachedServiceImpl --提供Memcached缓存实现
NoneCacheServiceImpl --没有缓存的实现
RemoteCacheService --需要被实现的远程集中式缓存接口
RemoteCacheUtils --web存放远程缓存工具类
testMain --测试主类
memcached.xml --连接memcached的配置文件
1.测试主类:
public class testMain {
public static void main(String[] args) {
Student student=null;
String key="fghjkltyui";
LocalCacheUtils.init();
if (!CheckUtils.isEmpty(RemoteCacheUtils.get(key))) {
//有缓存数据
student = (Student) RemoteCacheUtils.get(key);
System.out.println(student.getName());
}else {
//没缓存数据,则student模拟数据库创建数据
Student stu=new Student();
stu.setAge(26);
stu.setName("台湾");
stu.setId("1");
//数据库查到数据后,添加缓存
if (!CheckUtils.isEmpty(stu)) {
RemoteCacheUtils.put(key,stu);
}
}
}
2.数据校验工具类
public class CheckUtils {
/**
*
* TODO 检查checkName对应的值str是否为空,会抛出非法数据异常
* @param str
* @param checkName
* @return void
*/
public static void valueIsEmpty(String str, String checkName){
if(StringUtils.isBlank(str)){
StringBuffer sb = new StringBuffer();
sb.append(checkName).append(" must be specified");
throw new IllegalArgumentException(sb.toString());
}
}
/**
* TODO 检查key对应的value是否为空
* @param value
* @param msg
* @return void
* @author min.zhang
* @date: 2017年4月1日 下午5:21:11
*/
public static void checkIsNULL(Object value , String msg){
if(value == null){
throw new RuntimeException(msg + " is not null");
}
}
/**
* 判断参数是否非NULL,空字符串,空数组,空的Collection或Map(只有空格的字符串也认为是空串)
* @param obj
* @return
*/
@SuppressWarnings("rawtypes")
public static boolean isEmpty(Object obj){
if (obj == null){
return true;
}
if (obj instanceof String && obj.toString().trim().length()==0){
return true;
}
if (obj.getClass().isArray() && Array.getLength(obj)==0){
return true;
}
if (obj instanceof Collection && ((Collection)obj).isEmpty()){
return true;
}
if (obj instanceof Map && ((Map)obj).isEmpty()){
return true;
}
return false;
}
}
3.远程缓存接口
/**
*
* 描述: 远程集中式缓存接口
* @author min.zhang
* @date: 2017年4月1日 下午4:46:10
*/
public interface RemoteCacheService {
/**
* 保存数据
*
* @param key
* 键
* @param value
* 值 对象
*/
public void put(String key, Object value);
/**
* 保存指定有效期的数据
*
* @param key
* 键
* @param value
* 值对象
* @param expireDate
* 有效期
*/
public void put(String key, Object value, Date expireDate);
/**
* 保存指定有效期的数据
*
* @param key
* 键
* @param value
* 值对象
* @param timeToLive
* 有效期为距离当前时间指定的秒数
*/
public void put(String key, Object value, int timeToLive);
/**
* 保存指定客户端的数据
*
* @param name
* 指定客户端
* @param key
* 键
* @param value
* 值对象
*/
public void putClient(String name, String key, Object value);
/**
* 保存指定客户端的有效期数据
*
* @param name
* 指定客户端
* @param key
* 键
* @param value
* 值对象
* @param expireDate
* 有效期
*/
public void putClient(String name, String key, Object value, Date expireDate);
/**
* 保存指定客户端的有效期数据
*
* @param name
* 指定客户端
* @param key
* 键
* @param value
* 值对象
* @param timeToLive
* 有效期为距离当前时间指定的秒数
*/
public void putClient(String name, String key, Object value, int timeToLive);
/**
* 获取缓存数据
*
* @param key
* 键
* @return 缓存对象
*/
public Object get(String key);
/**
* 获取指定类型的缓存数据
*
* @param clazz
* 指定类型
* @param key
* 键
* @return 指定类型的缓存对象
*/
public <T> T get(Class<T> clazz, String key);
/**
* 获取指定客户端的缓存数据
*
* @param name
* 指定客户端
* @param key
* 键
* @return 指定客户端的缓存对象
*/
public Object getClient(String name, String key);
/**
* 获取指定客户端 指定类型的缓存数据
*
* @param name
* 指定客户端
* @param clazz
* 指定类型
* @param key
* 键
* @return 指定客户端指定类型的缓存对象
*/
public <T> T getClient(String name, Class<T> clazz, String key);
/**
* 移出缓存数据
*
* @param key
* 键
*/
public void remove(String key);
/**
* 移出指定客户端缓存数据
*
* @param name
* 指定客户端
* @param key
* 键
*/
public void removeClient(String name, String key);
/**
* 清空默认客户端缓存内的数据
*
*/
public void clear();
/**
* 清空指定客户端缓存内的数据
*
* @param name
* 指定客户端
*/
public void clearClient(String name);
/**
* 设置默认客户端
*
* @param name
* 指定客户端
*/
public void setDefaultClient(String name);
public void destory();
}
4.实现缓存接口
/**
* 加上缓存,实现缓存接口的类--提供memcached缓存的实现
* 描述: MemcachedServiceImpl
* @author min.zhang
* @date: 2017年4月1日 下午4:55:22
*/
public class MemcachedServiceImpl implements RemoteCacheService {
private static ICacheManager<IMemcachedCache> manager;
private IMemcachedCache cache;
/**
* 构造函数
*
* @param clientCacheName
* 默认客户端名称
* @throws RemoteCacheException
*/
public MemcachedServiceImpl(String clientCacheName) {
initCacheManager();
cache = manager.getCache(clientCacheName);
}
/**
*
* TODO 初始化缓存管理器
* @return void
* @author min.zhang
*/
public synchronized static void initCacheManager(){
if(manager==null){
manager = CacheUtil.getCacheManager(IMemcachedCache.class,
MemcachedCacheManager.class.getName());
manager.setConfigFile("cache/Memcache.xml");
// manager.setResponseStatInterval(5*1000);
manager.start();
}
}
/**
* 停止缓存管理器
*/
public void destory() {
if (manager != null) {
manager.stop();
}
}
/**
* 检查是否设置默认的客户端
*
* @param cache
* 默认客户端缓存
*/
private IMemcachedCache checkDefaultClient(IMemcachedCache cache) {
if (cache == null) {
throw new RuntimeException("默认客户端未定义");
}
return cache;
}
/**
* 设置默认客户端
*
* @param name
* 默认客户端
*/
public void setDefaultClient(String name) {
cache = this.getClientByName(name);
}
/**
* 获取指定客户端缓存
*
* @param name
* 客户端名称
* @return 缓存对象
* @throws RemoteCacheException
* 客户端缓存未找到异常
*/
private IMemcachedCache getClientByName(String name) {
IMemcachedCache clientCache = manager.getCache(name);
if (clientCache == null) {
throw new RuntimeException("指定的客户端" + name +" 不存在");
}
return clientCache;
}
@Override
public void put(String key, Object value) {
this.checkDefaultClient(cache).put(key, value);
}
@Override
public void put(String key, Object value, Date expireDate) {
this.checkDefaultClient(cache).put(key, value, expireDate);
}
@Override
public void put(String key, Object value, int timeToLive) {
this.checkDefaultClient(cache).put(key, value, timeToLive);
}
@Override
public void putClient(String name, String key, Object value) {
this.getClientByName(name).put(key, value);
}
@Override
public void putClient(String name, String key, Object value, Date expireDate) {
this.getClientByName(name).put(key, value, expireDate);
}
@Override
public Object getClient(String name, String key) {
return this.getClientByName(name).get(key);
}
@Override
public void putClient(String name, String key, Object value, int timeToLive) {
this.getClientByName(name).put(key, value, timeToLive);
}
@Override
public Object get(String key) {
return this.checkDefaultClient(cache).get(key);
}
@Override
/**
* 得到默认客户端的key对应的类型为clazz的value
*/
public <T> T get(Class<T> clazz, String key) {
T classResult = null;
Object obj = this.checkDefaultClient(cache).get(key);
if(obj != null){
if(obj.getClass().equals(clazz)){
classResult = (T)obj;
}else{
throw new ClassCastException(obj.getClass().getSimpleName()+" 不能强转为: "+clazz.getSimpleName());
}
}
return classResult;
}
@Override
/**
* 得到指定客户端的key对应的类型为clazz的value
*/
public <T> T getClient(String name, Class<T> clazz, String key) {
T classResult = null;
Object obj = this.getClientByName(name).get(key);
if(obj != null){
if(obj.getClass().equals(clazz)){
classResult = (T)obj;
}else{
throw new ClassCastException(obj.getClass().getSimpleName()+" 不能强转为: "+clazz.getSimpleName());
}
}
return classResult;
}
@Override
public void remove(String key) {
this.checkDefaultClient(cache).remove(key);
}
@Override
public void removeClient(String name, String key) {
this.getClientByName(name).remove(key);
}
@Override
public void clear() {
this.checkDefaultClient(cache).clear();
}
@Override
public void clearClient(String name) {
this.getClientByName(name).clear();
}
}
5.远程缓存工具类
/**
*
* 描述: 远程缓存工具类
* @author min.zhang
* @date: 2017年4月1日 下午4:51:01
*/
public class RemoteCacheUtils {
//key最大长度
private final static Integer KEY_LENGTH = 3;
private static Logger logger = LoggerFactory.getLogger(RemoteCacheUtils.class);
//是否初始化
private static boolean initialized = false;
private static RemoteCacheService service = new NoneCacheServiceImpl();
private RemoteCacheUtils(){
super();
}
//组件是否完成了初始化
public static boolean initialized(){
return initialized && (service!=null);
}
//组件初始化
public synchronized static void init(){
if(initialized()){
return;
}
service = new MemcachedServiceImpl("defaultClient");
initialized = true;
}
/**
* 保存数据
*
* @param key
* 键
* @param value
* 值对象
*/
public static void put(String key, Object value) {
try{
CheckUtils.valueIsEmpty(key, "key");
CheckUtils.checkIsNULL(value, "value");
//此处对key的长度做了校验,key做了加密解密操作,略过
key = checkKeyLength(key);
//key = key;
service.put(key, value);
}catch (Exception e) {
logger.debug("有错误", e);
}catch (Throwable e) {
logger.error(" putting cache find out an error, key:"+key+" value:"+value, e);
}
}
/**
*
* TODO 长度超过的对key做了封装
* @param key
* @return
* @return String
* @author min.zhang
* @date: 2017年4月5日 下午1:56:51
*/
private static String checkKeyLength(String key){
//当key的长度超出了指定的长度时,进行MD5压缩
if(key.getBytes().length> KEY_LENGTH)
key =md5Digest(key);
return key ;
}
/**
* 使用MD5算法计算摘要,并对结果进行hex转换
* @param data 源数据
* @return 摘要信息
*/
public static String md5Digest(String str){
try {
byte[] data = str.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
return Hex.toHex(md.digest(data));
} catch (Exception e){
throw new RuntimeException("digest fail!", e);
}
}
/**
* 获取缓存数据
*
* @param key
* 键
* @return Object缓存对象
*/
public static Object get(String key) {
try {
CheckUtils.valueIsEmpty(key, "key");
return service.get(key);
} catch (Throwable e) {
logger.error(" getting cache find out an error, key:" + key, e);
}
return null;
}
}
6.配置文件
<?xml version="1.0" encoding="UTF-8"?>
<memcached>
<!-- name:Cache的唯一标识;
socketpool:关联到后面的socketpool配置;
errorHandler:可选,用来处理出错情况-->
<client name="defaultClient" compressEnable="true" defaultEncoding="UTF-8" socketpool="defaultPool">
<errorHandler>com.alisoft.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler>
</client>
<!--
failover:设置故障转移
maintSleep:后台线程管理SocketIO池的检查间隔时间,如果设置为0,则表明不需要后台线程维护SocketIO线程池,默认需要管理
socketTO:Socket操作超时配置,单位ms;
aliveCheck:表示在使用Socket以前是否先检查Socket状态
-->
<socketpool name="defaultPool" failover="true" initConn="1" minConn="1" maxConn="10" maintSleep="0"
nagle="false" socketTO="3000" aliveCheck="true">
<servers>cache.bass.3g:12801</servers>
</socketpool>
</memcached>