flea-frame-cache使用之Memcached接入

Memcached接入

参考

flea-frame-cache使用之Memcached接入 源代码

依赖

Memcached-Java-Client-3.0.2.jar

<!-- Memcached相关 -->
<dependency>
	<groupId>com.whalin</groupId>
	<artifactId>Memcached-Java-Client</artifactId>
	<version>3.0.2</version>
</dependency>

spring-context-4.3.18.RELEASE.jar

<!-- Spring相关 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>

spring-context-support-4.3.18.RELEASE.jar

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>4.3.18.RELEASE</version>
</dependency>

使用讲解

1. 定义Flea缓存接口

/**
 * <p> 自定义Cache接口类(主要定义了一些增删改查的方法) </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public interface IFleaCache {
    
    

    /**
     * <p> 读缓存 </p>
     *
     * @param key 数据键关键字
     * @return 数据值
     * @since 1.0.0
     */
    Object get(String key);

    /**
     * <p> 写缓存 </p>
     *
     * @param key   数据键关键字
     * @param value 数据值
     * @since 1.0.0
     */
    void put(String key, Object value);

    /**
     * <p> 清空所有缓存 </p>
     *
     * @since 1.0.0
     */
    void clear();

    /**
     * <p> 删除指定数据键关键字对应的缓存 </p>
     *
     * @param key 数据键关键字
     * @since 1.0.0
     */
    void delete(String key);

    /**
     * <p> 获取 记录当前Cache所有数据键关键字 的Set集合 </p>
     *
     * @return 数据键key的集合
     * @since 1.0.0
     */
    Set<String> getCacheKey();

}

2. 定义抽象Flea缓存类 AbstractFleaCache

/**
 * <p> 抽象Flea Cache类 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public abstract class AbstractFleaCache implements IFleaCache {
    
    

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

    private final String name;  // 缓存主要关键字(用于区分)

    private final long expiry;  // 有效期(单位:秒)

    protected CacheEnum cache;  // 缓存类型

    public AbstractFleaCache(String name, long expiry) {
    
    
        this.name = name;
        this.expiry = expiry;
    }

    @Override
    public Object get(String key) {
    
    
        Object value = null;
        try {
    
    
            if (LOGGER.isDebugEnabled()) {
    
    
                LOGGER.debug("AbstractFleaCache##get(String) KEY = {}", key);
            }
            value = getNativeValue(getNativeKey(key));
            if (LOGGER.isDebugEnabled()) {
    
    
                LOGGER.debug("AbstractFleaCache##get(String) VALUE = {}", value);
            }
        } catch (Exception e) {
    
    
            if (LOGGER.isErrorEnabled()) {
    
    
                LOGGER.error("The action of getting [" + cache.getName() + "] cache occurs exception :", e);
            }
        }
        return value;
    }

    @Override
    public void put(String key, Object value) {
    
    
        if (ObjectUtils.isEmpty(value))
            return;
        try {
    
    
            putNativeValue(getNativeKey(key), value, expiry);
            // 将指定Cache的key添加到Set集合,并存于缓存中
            addCacheKey(key);
        } catch (Exception e) {
    
    
            if (LOGGER.isErrorEnabled()) {
    
    
                LOGGER.error("The action of adding [" + cache.getName() + "] cache occurs exception :", e);
            }
        }
    }

    @Override
    public void clear() {
    
    
        Set<String> keySet = getCacheKey();
        if (LOGGER.isDebugEnabled()) {
    
    
            LOGGER.debug("AbstractFleaCache##clear() KEYS = {}", keySet);
        }
        if (CollectionUtils.isNotEmpty(keySet)) {
    
    
            for (String key : keySet) {
    
    
                deleteNativeValue(getNativeKey(key));
            }
            // 删除 记录当前Cache所有数据键关键字 的缓存
            deleteCacheAllKey();
        }
    }

    @Override
    public void delete(String key) {
    
    
        try {
    
    

            deleteNativeValue(getNativeKey(key));
            // 从 记录当前Cache所有数据键关键字 的缓存中 删除指定数据键关键字key
            deleteCacheKey(key);
        } catch (Exception e) {
    
    
            if (LOGGER.isErrorEnabled()) {
    
    
                LOGGER.error("The action of deleting [" + cache.getName() + "] cache occurs exception :", e);
            }
        }
    }

    /**
     * <p> 将指定数据键关键字{@code key}记录到当前Cache所有数据键关键字的缓存中 </p>
     *
     * @param key 指定Cache的数据键关键字
     * @since 1.0.0
     */
    private void addCacheKey(String key) {
    
    
        Set<String> keySet = getCacheKey();
        if (CollectionUtils.isEmpty(keySet)) {
    
    
            keySet = new HashSet<>();
        }
        if (!keySet.contains(key)) {
    
     // 只有其中不存在,才重新设置
            keySet.add(key);
            putNativeValue(name, keySet, CommonConstants.NumeralConstants.ZERO);
        }
    }

    /**
     * <p> 从 记录当前Cache所有数据键关键字 的缓存中 删除指定数据键关键字{@code key} </p>
     *
     * @param key 指定Cache的数据键关键字
     * @since 1.0.0
     */
    private void deleteCacheKey(String key) {
    
    
        Set<String> keySet = getCacheKey();
        if (CollectionUtils.isNotEmpty(keySet)) {
    
    
            // 存在待删除的数据键关键字
            if (keySet.contains(key)) {
    
    
                if (LOGGER.isDebugEnabled()) {
    
    
                    LOGGER.debug("AbstractFleaCache##deleteCacheKey() Delete cache of recording all key, KEY = {}", key);
                }
                if (CommonConstants.NumeralConstants.INT_ONE == keySet.size()) {
    
    
                    deleteCacheAllKey(); // 直接将记录当前Cache所有数据键关键字的缓存从缓存中清空
                } else {
    
    
                    // 将数据键关键字从Set集合中删除
                    keySet.remove(key);
                    // 重新覆盖当前Cache所有数据键关键字的缓存信息
                    putNativeValue(name, keySet, CommonConstants.NumeralConstants.ZERO);
                }
            } else {
    
    
                if (LOGGER.isDebugEnabled()) {
    
    
                    LOGGER.debug("AbstractFleaCache##deleteCacheKey() The CacheKey of [{}] is not exist", key);
                }
            }
        }
    }

    /**
     * <p> 删除 记录当前Cache所有数据键关键字 的缓存 </p>
     *
     * @since 1.0.0
     */
    private void deleteCacheAllKey() {
    
    
        try {
    
    
            if (LOGGER.isDebugEnabled()) {
    
    
                LOGGER.debug("AbstractFleaCache##deleteCacheAllKey() Delete cache of recording all key");
            }
            deleteNativeValue(name);
        } catch (Exception e) {
    
    
            if (LOGGER.isErrorEnabled()) {
    
    
                LOGGER.error("The action of deleting [" + cache.getName() + "] cache occurs exception :", e);
            }
        }
    }

    @Override
    @SuppressWarnings(value = "unchecked")
    public Set<String> getCacheKey() {
    
    
        Set<String> keySet = null;
        Object keySetObj = getNativeValue(name);
        if (ObjectUtils.isNotEmpty(keySetObj) && keySetObj instanceof Set) {
    
    
            keySet = (Set<String>) keySetObj;
        }
        return keySet;
    }

    /**
     * <p> 获取缓存值 </p>
     *
     * @param key 缓存关键字
     * @return 缓存值
     * @since 1.0.0
     */
    public abstract Object getNativeValue(String key);

    /**
     * <p> 添加缓存数据 </p>
     *
     * @param key    缓存关键字
     * @param value  缓存值
     * @param expiry 失效时间(单位:秒)
     * @since 1.0.0
     */
    public abstract void putNativeValue(String key, Object value, long expiry);

    /**
     * <p> 删除指定缓存数据 </p>
     *
     * @param key 缓存关键字
     * @since 1.0.0
     */
    public abstract void deleteNativeValue(String key);

    /**
     * <p> 获取实际存储的缓存键(缓存名 + 缓存关键字) </p>
     *
     * @param key 缓存关键字
     * @return 实际存储的缓存键
     * @since 1.0.0
     */
    protected String getNativeKey(String key) {
    
    
        return name + CommonConstants.SymbolConstants.UNDERLINE + key;
    }

    public String getName() {
    
    
        return name;
    }

    public long getExpiry() {
    
    
        return expiry;
    }

    public String getCacheName() {
    
    
        return cache.getName();
    }

    public String getCacheDesc() {
    
    
        return cache.getDesc();
    }

    public CacheEnum getCache() {
    
    
        return cache;
    }
}

该类实现了IFleaCache接口,同时定义了三个抽象方法 :

    public abstract Object getNativeValue(String key);

    public abstract void putNativeValue(String key, Object value, long expiry);

    public abstract void deleteNativeValue(String key);

这三个抽象方法由子类实现具体的读,写,删除缓存的原始操作

3. 定义MemCached Flea缓存类 MemCachedFleaCache

该类继承AbstractFleaCache,实现Memcached缓存的接入使用;

/**
 * <p> MemCached Flea缓存类 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class MemCachedFleaCache extends AbstractFleaCache {
    
    

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

    private final MemCachedClient memCachedClient;  // MemCached客户端

    /**
     * <p> 带参数的构造方法,初始化MemCached Flea缓存类 </p>
     *
     * @param name            缓存主关键字
     * @param expiry          失效时长
     * @param memCachedClient MemCached客户端
     * @since 1.0.0
     */
    public MemCachedFleaCache(String name, long expiry, MemCachedClient memCachedClient) {
    
    
        super(name, expiry);
        this.memCachedClient = memCachedClient;
        cache = CacheEnum.MemCached;
    }

    @Override
    public Object getNativeValue(String key) {
    
    
        if (LOGGER.isDebugEnabled()) {
    
    
            LOGGER.debug("MemCachedFleaCache##getNativeValue(String) KEY = {}", key);
        }
        return memCachedClient.get(key);
    }

    @Override
    public void putNativeValue(String key, Object value, long expiry) {
    
    
        if (LOGGER.isDebugEnabled()) {
    
    
            LOGGER.debug("MemCachedFleaCache##putNativeValue(String, Object, long) KEY = {}", key);
            LOGGER.debug("MemCachedFleaCache##putNativeValue(String, Object, long) VALUE = {}", value);
            LOGGER.debug("MemCachedFleaCache##putNativeValue(String, Object, long) EXPIRY = {}s", expiry);
        }
        memCachedClient.set(key, value, new Date(expiry * 1000));
    }

    @Override
    public void deleteNativeValue(String key) {
    
    
        if (LOGGER.isDebugEnabled()) {
    
    
            LOGGER.debug("MemCachedFleaCache##deleteNativeValue(String) KEY = {}", key);
        }
        memCachedClient.delete(key);
    }

}

到这一步为止,底层的Flea缓存接口和实现已经完成,但目前还不能使用;

4. 定义Memcached连接池 MemCachedPool

/**
 * <p> MemCached连接池 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class MemCachedPool {
    
    

    private MemCachedConfig memCachedConfig; // MemCached 配置信息

    private SockIOPool sockIOPool; // MemCached SockIOPool

    private MemCachedPool() {
    
    
    }

    /**
     * <p> 获取MemCached连接池实例 (默认) </p>
     *
     * @return MemCached连接池实例对象
     * @since 1.0.0
     */
    public static MemCachedPool getInstance() {
    
    
        MemCachedPool memCachedPool = new MemCachedPool();
        memCachedPool.memCachedConfig = MemCachedConfig.getConfig();
        memCachedPool.sockIOPool = SockIOPool.getInstance();
        return memCachedPool;
    }

    /**
     * <p> 初始化MemCached连接池 </p>
     *
     * @since 1.0.0
     */
    public void initialize() {
    
    
        if (ObjectUtils.isEmpty(memCachedConfig)) {
    
    
            throw new RuntimeException("采用默认初始化,请使用MemCachedPool##getInstance()");
        }
        sockIOPool.setServers(memCachedConfig.getServers());
        sockIOPool.setWeights(memCachedConfig.getWeights());
        sockIOPool.setInitConn(memCachedConfig.getInitConn());
        sockIOPool.setMinConn(memCachedConfig.getMinConn());
        sockIOPool.setMaxConn(memCachedConfig.getMaxConn());
        sockIOPool.setMaintSleep(memCachedConfig.getMaintSleep());
        sockIOPool.setNagle(memCachedConfig.isNagle());
        sockIOPool.setSocketTO(memCachedConfig.getSocketTO());
        sockIOPool.setSocketConnectTO(memCachedConfig.getSocketConnectTO());
        sockIOPool.setHashingAlg(memCachedConfig.getHashingAlg());
        sockIOPool.initialize();
    }
    
    /**
     * <p> 关闭连接池 </p>
     *
     * @since 1.0.0
     */
    public void shutDown() {
    
    
        sockIOPool.shutDown();
    }

    public SockIOPool getSockIOPool() {
    
    
        return sockIOPool;
    }
}

5. 读取配置

flea-frame-cache读取memcached.properties(Memcached配置文件),用作初始化MemCachedPool

# Memcached配置
# Memcached服务器地址
memcached.server=127.0.0.1:31113,127.0.0.1:31114

# Memcached服务器权重分配
memcached.weight=1,1

# 初始化时对每个服务器建立的连接数目
memcached.initConn=20

# 每个服务器建立最小的连接数
memcached.minConn=20

# 每个服务器建立最大的连接数
memcached.maxConn=500

# 自查线程周期进行工作,其每次休眠时间
memcached.maintSleep=60000

# Socket的参数,如果是true在写数据时不缓冲,立即发送出去
memcached.nagle=true

# Socket阻塞读取数据的超时时间
memcached.socketTO=3000

# Socket连接超时时间
memcached.socketConnectTO=3000

# Memcached分布式hash算法
# 0 - native String.hashCode();
# 1 - original compatibility
# 2 - new CRC32 based
# 3 - MD5 Based
memcached.hashingAlg=3

6. 定义抽象Flea缓存管理类 AbstractFleaCacheManager

/**
 * <p> 自定义抽象缓存管理类 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public abstract class AbstractFleaCacheManager {
    
    

    private static final ConcurrentMap<String, AbstractFleaCache> cacheMap = new ConcurrentHashMap<String, AbstractFleaCache>();

    private Map<String, Long> configMap = new HashMap<String, Long>();   // 各缓存的时间Map

    /**
     * <p> 获取所有的Flea缓存 </p>
     *
     * @return 所有的Flea缓存
     * @since 1.0.0
     */
    protected Collection<? extends AbstractFleaCache> loadCaches() {
    
    
        return cacheMap.values();
    }

    /**
     * <p> 根据指定缓存名获取缓存对象 </p>
     *
     * @param name 缓存名
     * @return 缓存对象
     * @since 1.0.0
     */
    public AbstractFleaCache getCache(String name) {
    
    
        if (!cacheMap.containsKey(name)) {
    
    
            synchronized (cacheMap) {
    
    
                if (!cacheMap.containsKey(name)) {
    
    
                    Long expiry = configMap.get(name);
                    if (ObjectUtils.isEmpty(expiry)) {
    
    
                        expiry = CommonConstants.NumeralConstants.ZERO; // 表示永久
                        configMap.put(name, expiry);
                    }
                    cacheMap.put(name, newCache(name, expiry));
                }
            }
        }
        return cacheMap.get(name);
    }

    /**
     * <p> 新创建一个缓存对象 </p>
     *
     * @param name   缓存名
     * @param expiry 失效时间(单位:秒  其中0:表示永久)
     * @return 新建的缓存对象
     * @since 1.0.0
     */
    protected abstract AbstractFleaCache newCache(String name, long expiry);

    /**
     * <p> 设置各缓存失效时间配置Map </p>
     *
     * @param configMap 失效时间配置Map
     * @since 1.0.0
     */
    public void setConfigMap(Map<String, Long> configMap) {
    
    
        this.configMap = configMap;
    }

}

7. 定义Memcached Flea缓存管理类 MemCachedFleaCacheManager

上述MemCachedFleaCache使用, 需要初始化MemCachedPool

/**
 * <p> MemCached Flea缓存管理类 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class MemCachedFleaCacheManager extends AbstractFleaCacheManager {
    
    

    private MemCachedClient memCachedClient;   // MemCached客户端类

    /**
     * <p> 新建一个MemCached Flea缓存管理类 </p>
     *
     * @since 1.0.0
     */
    public MemCachedFleaCacheManager() {
    
    
        memCachedClient = new MemCachedClient();
        initPool();
    }

    /**
     * <p> 新建一个MemCached Flea缓存管理类 </p>
     *
     * @param memCachedClient MemCached客户端
     * @since 1.0.0
     */
    public MemCachedFleaCacheManager(MemCachedClient memCachedClient) {
    
    
        this.memCachedClient = memCachedClient;
        initPool();
    }

    /**
     * 初始化MemCached连接池
     *
     * @since 1.0.0
     */
    private void initPool() {
    
    
        MemCachedPool pool = MemCachedPool.getInstance();
        pool.initialize();
    }

    @Override
    protected AbstractFleaCache newCache(String name, long expiry) {
    
    
        return new MemCachedFleaCache(name, expiry, memCachedClient);
    }

}

好了,到了这一步,Memcached已接入完成,开始自测

8. 缓存自测

 @Test
    public void testMemeCachedFleaCache() {
    
    

        try {
    
    
            AbstractFleaCacheManager manager = new MemCachedFleaCacheManager();
            AbstractFleaCache cache = manager.getCache("fleaparadetail");
            LOGGER.debug("Cache={}", cache);
            //#### 1.  简单字符串
//            cache.put("menu1", "huazie");
//            cache.get("menu1");
//            cache.delete("menu1");
            LOGGER.debug(cache.getCacheName() + ">>>" + cache.getCacheDesc());
        } catch (Exception e) {
    
    
            LOGGER.error("Exception:", e);
        }
    }

进阶练习

1. 定义抽象Spring缓存 AbstractSpringCache

该类与AbstractFleaCache不同之处在于,实现了Spring的Cache接口,用于对接Spring,相关配置后面会介绍一下。

import com.huazie.frame.common.util.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;

import java.util.Set;
import java.util.concurrent.Callable;

/**
 * <p> 抽象Spring缓存类,实现Spring的Cache 和 自定义的 IFleaCache接口 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public abstract class AbstractSpringCache implements Cache, IFleaCache {
    
    

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

    private final String name;  // 缓存主要关键字(用于区分)

    private final IFleaCache fleaCache; // 具体Flea缓存实现

    public AbstractSpringCache(String name, IFleaCache fleaCache) {
    
    
        this.name = name;
        this.fleaCache = fleaCache;
    }

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

    @Override
    public IFleaCache getNativeCache() {
    
    
        return fleaCache;
    }

    @Override
    public ValueWrapper get(Object key) {
    
    
        ValueWrapper wrapper = null;
        if (LOGGER.isDebugEnabled()) {
    
    
            LOGGER.debug("AbstractSpringCache##get(Object) KEY = {}", key);
        }
        Object cacheValue = fleaCache.get(key.toString());
        if (ObjectUtils.isNotEmpty(cacheValue)) {
    
    
            if (LOGGER.isDebugEnabled()) {
    
    
                LOGGER.debug("AbstractSpringCache##get(Object) VALUE = {}", cacheValue);
            }
            wrapper = new SimpleValueWrapper(cacheValue);
        }
        return wrapper;
    }

    @Override
    public void put(Object key, Object value) {
    
    
        fleaCache.put(key.toString(), value);
    }

    @Override
    public void evict(Object key) {
    
    
        fleaCache.delete(key.toString());
    }

    @Override
    public void clear() {
    
    
        fleaCache.clear();
    }

    @Override
    @SuppressWarnings(value = "unchecked")
    public <T> T get(Object key, Class<T> type) {
    
    
        if (LOGGER.isDebugEnabled()) {
    
    
            LOGGER.debug("AbstractSpringCache##get(Object) KEY = {}", key);
        }
        Object cacheValue = fleaCache.get(key.toString());
        if (ObjectUtils.isNotEmpty(type) && !type.isInstance(cacheValue)) {
    
    
            if (LOGGER.isDebugEnabled()) {
    
    
                LOGGER.debug("AbstractSpringCache##get(Object, Class<T>) Cached value is not of required type [{}]: {}", type.getName(), cacheValue);
            }
            return null;
        }
        if (LOGGER.isDebugEnabled()) {
    
    
            LOGGER.debug("AbstractSpringCache##get(Object, Class<T>) VALUE = {}", cacheValue);
        }
        return (T) cacheValue;
    }

    @Override
    public ValueWrapper putIfAbsent(Object key, Object value) {
    
    
        ValueWrapper wrapper = null;
        Object cacheValue = fleaCache.get(key.toString());
        if (ObjectUtils.isEmpty(cacheValue)) {
    
    
            fleaCache.put(key.toString(), value);
        } else {
    
    
            if (LOGGER.isDebugEnabled()) {
    
    
                LOGGER.debug("AbstractSpringCache##putIfAbsent(Object, Object) VALUE = {}", cacheValue);
            }
            wrapper = new SimpleValueWrapper(cacheValue);
        }
        return wrapper;
    }

    @Override
    public <T> T get(Object key, Callable<T> valueLoader) {
    
    
        return null;
    }

    @Override
    public Object get(String key) {
    
    
        return fleaCache.get(key);
    }

    @Override
    public void put(String key, Object value) {
    
    
        fleaCache.put(key, value);
    }

    @Override
    public void delete(String key) {
    
    
        fleaCache.delete(key);
    }

    @Override
    public Set<String> getCacheKey() {
    
    
        return fleaCache.getCacheKey();
    }
}

2. 定义Memcached Spring缓存 MemCachedSpringCache

MemCachedSpringCache只定义构造方法,使用MemCachedFleaCache作为具体缓存实现

/**
 * <p> MemCached Spring Cache的实现(实现spring的Cache接口)</p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class MemCachedSpringCache extends AbstractSpringCache {
    
    

    /**
     * <p> 带参数的构造方法,初始化MemCached Spring缓存类 </p>
     *
     * @param name      缓存主关键字
     * @param fleaCache 具体缓存实现
     * @since 1.0.0
     */
    public MemCachedSpringCache(String name, IFleaCache fleaCache) {
    
    
        super(name, fleaCache);
    }

    /**
     * <p> 带参数的构造方法,初始化MemCached Spring缓存类 </p>
     *
     * @param name            缓存主关键字
     * @param expiry          失效时长
     * @param memCachedClient MemCached客户端
     * @since 1.0.0
     */
    public MemCachedSpringCache(String name, long expiry, MemCachedClient memCachedClient) {
    
    
        this(name, new MemCachedFleaCache(name, expiry, memCachedClient));
    }

}

3. 定义抽象Spring缓存管理类 AbstractSpringCacheManager

该类继承 AbstractTransactionSupportingCacheManager,用于对接Spring。

/**
 * <p> 抽象Spring缓存管理类 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public abstract class AbstractSpringCacheManager extends AbstractTransactionSupportingCacheManager {
    
    

    private static final ConcurrentMap<String, AbstractSpringCache> cacheMap = new ConcurrentHashMap<String, AbstractSpringCache>();

    private Map<String, Long> configMap = new HashMap<String, Long>();   // 各缓存的时间Map

    @Override
    protected Collection<? extends AbstractSpringCache> loadCaches() {
    
    
        return cacheMap.values();
    }

    @Override
    public AbstractSpringCache getCache(String name) {
    
    
        if(!cacheMap.containsKey(name)) {
    
    
            synchronized (cacheMap) {
    
    
                if (!cacheMap.containsKey(name)) {
    
    
                    Long expiry = configMap.get(name);
                    if (expiry == null) {
    
    
                        expiry = CommonConstants.NumeralConstants.ZERO; // 表示永久
                        configMap.put(name, expiry);
                    }
                    cacheMap.put(name, newCache(name, expiry));
                }
            }
        }
        return cacheMap.get(name);
    }

    /**
     * <p> 新创建一个缓存对象 </p>
     *
     * @param name   缓存名
     * @param expiry 失效时间(单位:秒  其中0:表示永久)
     * @return 新建的缓存对象
     * @since 1.0.0
     */
    protected abstract AbstractSpringCache newCache(String name, long expiry);

    /**
     * <p> 设置各缓存失效时间配置Map </p>
     *
     * @param configMap 失效时间配置Map
     * @since 1.0.0
     */
    public void setConfigMap(Map<String, Long> configMap) {
    
    
        this.configMap = configMap;
    }

}

4. 定义Memcached Spring缓存管理类 MemCachedSpringCacheManager

该类基本实现同 MemCachedFleaCacheManager,不同在于newCache方法返回一个 MemCachedSpringCache的对象

/**
 * <p> Memcached的Spring缓存管理类 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class MemCachedSpringCacheManager extends AbstractSpringCacheManager {
    
    

    private MemCachedClient memCachedClient;   // Memcached客户端类

    /**
     * <p> 新建一个MemCached Spring缓存管理类 </p>
     *
     * @since 1.0.0
     */
    public MemCachedSpringCacheManager() {
    
    
        memCachedClient = new MemCachedClient();
        initPool();
    }

    /**
     * <p> 新建一个MemCached Spring缓存管理类 </p>
     *
     * @param memCachedClient MemCached客户端
     */
    public MemCachedSpringCacheManager(MemCachedClient memCachedClient) {
    
    
        this.memCachedClient = memCachedClient;
        initPool();
    }

    /**
     * 初始化MemCached连接池
     *
     * @since 1.0.0
     */
    private void initPool() {
    
    
        MemCachedPool pool = MemCachedPool.getInstance();
        pool.initialize();
    }

    @Override
    protected AbstractSpringCache newCache(String name, long expiry) {
    
    
        return new MemCachedSpringCache(name, expiry, memCachedClient);
    }

}

5. spring配置

<!--
   配置缓存管理MemCachedSpringCacheManager
    配置缓存时间 configMap (key缓存对象名称 value缓存过期时间)
-->
<bean id="memCachedSpringCacheManager" class="com.huazie.frame.cache.memcached.MemCachedSpringCacheManager">
    <property name="configMap">
        <map>
            <entry key="fleaparadetail" value="86400"/>
        </map>
    </property>
</bean>

 <!-- 开启缓存, 此处定义表示由spring接入来管理缓存访问 -->
 <cache:annotation-driven cache-manager="memCachedSpringCacheManager" proxy-target-class="true"/>

6. 缓存自测

    private ApplicationContext applicationContext;

    @Before
    public void init() {
    
    
        applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        LOGGER.debug("ApplicationContext={}", applicationContext);
    }
    
    @Test
    public void testMemCachedSpringCache() {
    
    
        try {
    
    
            AbstractSpringCacheManager manager = (MemCachedSpringCacheManager) applicationContext.getBean("memCachedSpringCacheManager");
            LOGGER.debug("MemCachedCacheManager={}", manager);

            AbstractSpringCache cache = manager.getCache("fleaparadetail");
            LOGGER.debug("Cache={}", cache);

            Set<String> cacheKey = cache.getCacheKey();
            LOGGER.debug("CacheKey = {}", cacheKey);
            // 缓存清理
//            cache.clear();

            //#### 1.  简单字符串
//			cache.put("menu1", "huazie");
//            cache.get("menu1");
//            cache.get("menu1", String.class);

            //#### 2.  简单对象(要是可以序列化的对象)
//			String user = new String("huazie");
//			cache.put("user", user);
//			LOGGER.debug(cache.get("user", String.class));

            //#### 3.  List塞对象
//			List<String> userList = new ArrayList<String>();
//			userList.add("huazie");
//			userList.add("lgh");
//			cache.put("user_list", userList);

//			LOGGER.debug(cache.get("user_list",userList.getClass()).toString());

        } catch (Exception e) {
    
    
            LOGGER.error("Exception:", e);
        }
    }

7. 业务逻辑层接入缓存管理

@Cacheable使用,value为缓存名,也作缓存主关键字, key为具体的缓存键

@Cacheable(value = "fleaparadetail", key = "#paraType + '_' + #paraCode")
public FleaParaDetail getParaDetail(String paraType, String paraCode) throws Exception {
    
    

    List<FleaParaDetail> fleaParaDetails = fleaParaDetailDao.getParaDetail(paraType, paraCode);
    FleaParaDetail fleaParaDetailValue = null;

    if (CollectionUtils.isNotEmpty(fleaParaDetails)) {
    
    
        fleaParaDetailValue = fleaParaDetails.get(0);
    }

    return fleaParaDetailValue;
}

至此,Memcached的接入工作已经全部完成,下一篇笔者将讲解flea-frame-cache使用之Redis接入,敬请期待哦~

猜你喜欢

转载自blog.csdn.net/u012855229/article/details/99699769
今日推荐