使用Memcached示例 - 书目录

使用Memcached示例

一般常用的缓存当属memcached了,这个就需要自己实现CacheManager和Cache
注意我实现的Cache里面有做一些定制化操作,比如对key的处理

创建MemcachedCache

import com.dooioo.common.jstl.DyFunctions;
import com.dooioo.commons.Strings;
import com.google.common.base.Joiner;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;

import java.util.concurrent.TimeoutException;

/**
 * 功能说明:自定义spring的cache的实现,参考cache包实现
 * 作者:liuxing(2015-04-12 13:57)
 */
public class MemcachedCache implements Cache {

    private static final Logger LOGGER = LoggerFactory.getLogger(MemcachedCache.class);

    /**
     * 缓存的别名
     */
    private String name;
    /**
     * memcached客户端
     */
    private MemcachedClient client;
    /**
     * 缓存过期时间,默认是1小时
     * 自定义的属性
     */
    private int exp = 3600;
    /**
     * 是否对key进行base64加密
     */
    private boolean base64Key = false;
    /**
     * 前缀名
     */
    private String prefix;

    @Override
    public String getName() {
        return name;
    }

    @Override
    public Object getNativeCache() {
        return this.client;
    }

    @Override
    public ValueWrapper get(Object key) {
        Object object = null;
        try {
            object = this.client.get(handleKey(objectToString(key)));
        } catch (TimeoutException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (InterruptedException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (MemcachedException e) {
            LOGGER.error(e.getMessage(), e);
        }

        return (object != null ? new SimpleValueWrapper(object) : null);
    }

    @Override
    public <T> T get(Object key, Class<T> type) {
        try {
            Object object = this.client.get(handleKey(objectToString(key)));
            return (T) object;
        } catch (TimeoutException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (InterruptedException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (MemcachedException e) {
            LOGGER.error(e.getMessage(), e);
        }

        return null;
    }

    @Override
    public void put(Object key, Object value) {
        if (value == null) {
//            this.evict(key);
            return;
        }

        try {
            this.client.set(handleKey(objectToString(key)), exp, value);
        } catch (TimeoutException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (InterruptedException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (MemcachedException e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    @Override
    public ValueWrapper putIfAbsent(Object key, Object value) {
        this.put(key, value);
        return this.get(key);
    }

    @Override
    public void evict(Object key) {
        try {
            this.client.delete(handleKey(objectToString(key)));
        } catch (TimeoutException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (InterruptedException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (MemcachedException e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    @Override
    public void clear() {
        try {
            this.client.flushAll();
        } catch (TimeoutException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (InterruptedException e) {
            LOGGER.error(e.getMessage(), e);
        } catch (MemcachedException e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    public void setName(String name) {
        this.name = name;
    }

    public MemcachedClient getClient() {
        return client;
    }

    public void setClient(MemcachedClient client) {
        this.client = client;
    }

    public void setExp(int exp) {
        this.exp = exp;
    }

    public void setBase64Key(boolean base64Key) {
        this.base64Key = base64Key;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    /**
     * 处理key
     * @param key
     * @return
     */
    private String handleKey(final String key) {
        if (base64Key) {
            return Joiner.on(EMPTY_SEPARATOR).skipNulls().join(this.prefix, DyFunctions.base64Encode(key));
        }

        return Joiner.on(EMPTY_SEPARATOR).skipNulls().join(this.prefix, key);
    }

    /**
     * 转换key,去掉空格
     * @param object
     * @return
     */
    private String objectToString(Object object) {
        if (object == null) {
            return null;
        } else if (object instanceof String) {
            return Strings.replace((String) object, " ", "_");
        } else {
            return object.toString();
        }
    }

    private static final String EMPTY_SEPARATOR = "";

}

创建MemcachedCacheManager

继承AbstractCacheManager

import org.springframework.cache.Cache;
import org.springframework.cache.support.AbstractCacheManager;

import java.util.Collection;

/**
 * 功能说明:memcachedCacheManager
 * 作者:liuxing(2015-04-12 15:13)
 */
public class MemcachedCacheManager extends AbstractCacheManager {

    private Collection<Cache> caches;

    @Override
    protected Collection<? extends Cache> loadCaches() {
        return this.caches;
    }

    public void setCaches(Collection<Cache> caches) {
        this.caches = caches;
    }

    public Cache getCache(String name) {
        return super.getCache(name);
    }

}

初始化

<!-- 启用缓存注解功能,这个是必须的,否则注解不会生效,指定一个默认的Manager,否则需要在注解使用时指定Manager -->
<cache:annotation-driven cache-manager="cacheManager"/>

<!-- memcached缓存管理器 -->
<bean id="cacheManager" class="com.dooioo.ky.cache.MemcachedCacheManager">
    <property name="caches">
        <set>
            <bean class="com.dooioo.ky.cache.MemcachedCache" p:client-ref="ky.memcachedClient" p:name="kyAreaCache" p:exp="86400"/>
            <bean class="com.dooioo.ky.cache.MemcachedCache" p:client-ref="ky.memcachedClient" p:name="kyOrganizationCache" p:exp="3600"/>
        </set>
    </property>
</bean>

使用

@Cacheable(value = "kyAreaCache", key="targetClass + '.' + methodName + '.' + #areaId")
public KyArea findById(String areaId) {
    // 业务代码省略
}

 

内容摘录于:http://liuxing.info/2015/06/18/Spring%20Cache%E4%BD%BF%E7%94%A8/