一 所需jar包
<dependency>
<groupId>com.danga.MemCached</groupId>
<artifactId>memcached-client</artifactId>
<version>2.6.6</version>
</dependency>
<!-- 及spring相关 jar包 -->
dependency>
<groupId>com.danga.MemCached</groupId>
<artifactId>memcached-client</artifactId>
<version>2.6.6</version>
</dependency>
<!-- 及spring相关 jar包 -->
二 spring-memcached.xml 配置文件
version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- =================================== 配置Memcached =============================== -->
<!-- 开启缓存 -->
<cache:annotation-driven cache-manager="cacheManager" />
<bean id="memcachedClientBuilder" class="net.rubyeye.xmemcached.XMemcachedClientBuilder">
<constructor-arg>
<list>
<bean class="java.net.InetSocketAddress">
<constructor-arg value="localhost"/>
<constructor-arg value="11211"/>
</bean>
</list>
</constructor-arg>
<property name="connectionPoolSize" value="5"/>
<property name="commandFactory">
<bean class="net.rubyeye.xmemcached.command.BinaryCommandFactory"/>
</property>
<property name="transcoder">
<bean class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />
</property>
</bean>
<bean id="memcachedClient" factory-bean="memcachedClientBuilder" factory-method="build" destroy-method="shutdown"/>
<!-- 配置缓存管理 -->
<bean id="cacheManager" class="com.wutongyu.cache.memcache.MemcachedCacheManager">
<property name="memcachedClient" ref="memcachedClient"/>
<!-- 配置缓存时间 -->
<property name="configMap">
<map>
<!-- key缓存对象名称 value缓存过期时间 表示存储一个月-->
<entry key="siemCache" value="0"/>
</map>
</property>
</bean>
</beans>
三 缓存管理类 MemcachedCacheManager及相关
package com.wutongyu.cache.memcache;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeoutException;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;
import org.springframework.cache.Cache;
import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;
public class MemcachedCacheManager extends AbstractTransactionSupportingCacheManager {
private ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<String, Cache>();
private Map<String, Integer> expireMap = new HashMap<String, Integer>(); // 缓存的时间
private MemcachedClient memcachedClient; // xmemcached的客户端
public MemcachedCacheManager() {
}
@Override
protected Collection<? extends Cache> loadCaches() {
Collection<Cache> values = cacheMap.values();
return values;
}
@Override
public Cache getCache(String name) {
Cache cache = cacheMap.get(name);
if (cache == null) {
Integer expire = expireMap.get(name);
if (expire == null) {
expire = 0;
expireMap.put(name, expire);
}
cache = new MemcachedCache(name, expire.intValue(), memcachedClient);
cacheMap.put(name, cache);
}
return cache;
}
/**
* 通过memcachedClient更新缓存
* @param key
* @param value
* @throws InterruptedException
* @throws MemcachedException
* @throws TimeoutException
*/
public void put(String key,Object value) throws InterruptedException, MemcachedException, TimeoutException {
this.memcachedClient.set(key,0,value);
}
/**
* 通过memcachedClient获取缓存
* @param key
* @return
* @throws InterruptedException
* @throws MemcachedException
* @throws TimeoutException
*/
public Object get(String key) throws InterruptedException, MemcachedException, TimeoutException {
return this.memcachedClient.get( key);
}
public void setMemcachedClient(MemcachedClient memcachedClient) {
this.memcachedClient = memcachedClient;
//关闭心跳
memcachedClient.setEnableHeartBeat(false);
}
public void setConfigMap(Map<String, Integer> configMap) {
this.expireMap = configMap;
}
}
package com.wutongyu.cache.memcache;
import net.rubyeye.xmemcached.MemcachedClient;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
public class MemcachedCache implements Cache {
private final String name;
private final MemCache memCache;
public MemcachedCache(String name, int expire,MemcachedClient memcachedClient) {
this.name = name;
this.memCache = new MemCache(name, expire, memcachedClient);
}
@Override
public void clear() {
memCache.clear();
}
@Override
public void evict(Object key) {
memCache.delete(key.toString());
}
@Override
public ValueWrapper get(Object key) {
ValueWrapper wrapper = null;
Object value = memCache.get(key.toString());
if (value != null) {
wrapper = new SimpleValueWrapper(value);
}
return wrapper;
}
@Override
public String getName() {
return this.name;
}
@Override
public MemCache getNativeCache() {
return this.memCache;
}
@Override
public void put(Object key, Object value) {
memCache.put(key.toString(), value);
}
@Override
@SuppressWarnings("unchecked")
public <T> T get(Object key, Class<T> type) {
Object cacheValue = this.memCache.get(key.toString());
Object value = (cacheValue != null ? cacheValue : null);
if (type != null && !type.isInstance(value)) {
throw new IllegalStateException("Cached value is not of required type [" + type.getName()+ "]: " + value);
}
return (T) value;
}
@Override
public ValueWrapper putIfAbsent( Object key, Object value ) {
// TODO Auto-generated method stub
return null;
}
}
package com.wutongyu.cache.memcache;
import java.util.HashSet;
import java.util.Set;
import net.rubyeye.xmemcached.MemcachedClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MemCache {
private static Logger log = LoggerFactory.getLogger(MemCache.class);
private Set<String> keySet = new HashSet<String>();
private final String name;
private final int expire;
private final MemcachedClient memcachedClient;
public MemCache(String name, int expire, MemcachedClient memcachedClient) {
this.name = name;
this.expire = expire;
this.memcachedClient = memcachedClient;
}
public Object get(String key) {
Object value = null;
try {
key = this.getKey(key);
value = memcachedClient.get(key,10000);
} catch (Exception e) {
log.warn("获取 Memcached 缓存超时", e);
}
return value;
}
public void put(String key, Object value) {
if (value == null)
return;
try {
key = this.getKey(key);
memcachedClient.set(key,expire, value,10000);
keySet.add(key);
}catch (Exception e) {
log.warn("更新 Memcached 缓存错误", e);
}
}
public void clear() {
for (String key : keySet) {
try {
memcachedClient.delete(this.getKey(key));
}catch (Exception e) {
log.warn("删除 Memcached 缓存错误", e);
}
}
}
public void delete(String key) {
try {
key = this.getKey(key);
memcachedClient.delete(key);
} catch (Exception e) {
log.warn("删除 Memcached 缓存被中断", e);
}
}
private String getKey(String key) {
return name + "_" + key;
}
}
com.wutongyu.cache.memcache;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeoutException;
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.exception.MemcachedException;
import org.springframework.cache.Cache;
import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;
public class MemcachedCacheManager extends AbstractTransactionSupportingCacheManager {
private ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<String, Cache>();
private Map<String, Integer> expireMap = new HashMap<String, Integer>(); // 缓存的时间
private MemcachedClient memcachedClient; // xmemcached的客户端
public MemcachedCacheManager() {
}
@Override
protected Collection<? extends Cache> loadCaches() {
Collection<Cache> values = cacheMap.values();
return values;
}
@Override
public Cache getCache(String name) {
Cache cache = cacheMap.get(name);
if (cache == null) {
Integer expire = expireMap.get(name);
if (expire == null) {
expire = 0;
expireMap.put(name, expire);
}
cache = new MemcachedCache(name, expire.intValue(), memcachedClient);
cacheMap.put(name, cache);
}
return cache;
}
/**
* 通过memcachedClient更新缓存
* @param key
* @param value
* @throws InterruptedException
* @throws MemcachedException
* @throws TimeoutException
*/
public void put(String key,Object value) throws InterruptedException, MemcachedException, TimeoutException {
this.memcachedClient.set(key,0,value);
}
/**
* 通过memcachedClient获取缓存
* @param key
* @return
* @throws InterruptedException
* @throws MemcachedException
* @throws TimeoutException
*/
public Object get(String key) throws InterruptedException, MemcachedException, TimeoutException {
return this.memcachedClient.get( key);
}
public void setMemcachedClient(MemcachedClient memcachedClient) {
this.memcachedClient = memcachedClient;
//关闭心跳
memcachedClient.setEnableHeartBeat(false);
}
public void setConfigMap(Map<String, Integer> configMap) {
this.expireMap = configMap;
}
}
package com.wutongyu.cache.memcache;
import net.rubyeye.xmemcached.MemcachedClient;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
public class MemcachedCache implements Cache {
private final String name;
private final MemCache memCache;
public MemcachedCache(String name, int expire,MemcachedClient memcachedClient) {
this.name = name;
this.memCache = new MemCache(name, expire, memcachedClient);
}
@Override
public void clear() {
memCache.clear();
}
@Override
public void evict(Object key) {
memCache.delete(key.toString());
}
@Override
public ValueWrapper get(Object key) {
ValueWrapper wrapper = null;
Object value = memCache.get(key.toString());
if (value != null) {
wrapper = new SimpleValueWrapper(value);
}
return wrapper;
}
@Override
public String getName() {
return this.name;
}
@Override
public MemCache getNativeCache() {
return this.memCache;
}
@Override
public void put(Object key, Object value) {
memCache.put(key.toString(), value);
}
@Override
@SuppressWarnings("unchecked")
public <T> T get(Object key, Class<T> type) {
Object cacheValue = this.memCache.get(key.toString());
Object value = (cacheValue != null ? cacheValue : null);
if (type != null && !type.isInstance(value)) {
throw new IllegalStateException("Cached value is not of required type [" + type.getName()+ "]: " + value);
}
return (T) value;
}
@Override
public ValueWrapper putIfAbsent( Object key, Object value ) {
// TODO Auto-generated method stub
return null;
}
}
package com.wutongyu.cache.memcache;
import java.util.HashSet;
import java.util.Set;
import net.rubyeye.xmemcached.MemcachedClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MemCache {
private static Logger log = LoggerFactory.getLogger(MemCache.class);
private Set<String> keySet = new HashSet<String>();
private final String name;
private final int expire;
private final MemcachedClient memcachedClient;
public MemCache(String name, int expire, MemcachedClient memcachedClient) {
this.name = name;
this.expire = expire;
this.memcachedClient = memcachedClient;
}
public Object get(String key) {
Object value = null;
try {
key = this.getKey(key);
value = memcachedClient.get(key,10000);
} catch (Exception e) {
log.warn("获取 Memcached 缓存超时", e);
}
return value;
}
public void put(String key, Object value) {
if (value == null)
return;
try {
key = this.getKey(key);
memcachedClient.set(key,expire, value,10000);
keySet.add(key);
}catch (Exception e) {
log.warn("更新 Memcached 缓存错误", e);
}
}
public void clear() {
for (String key : keySet) {
try {
memcachedClient.delete(this.getKey(key));
}catch (Exception e) {
log.warn("删除 Memcached 缓存错误", e);
}
}
}
public void delete(String key) {
try {
key = this.getKey(key);
memcachedClient.delete(key);
} catch (Exception e) {
log.warn("删除 Memcached 缓存被中断", e);
}
}
private String getKey(String key) {
return name + "_" + key;
}
}
四 spring.xml 调用spring-memcached.xml 连接memcache
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- 引入属性文件 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:rabbitmq.properties</value>
</list>
</property>
</bean>
<import resource="spring-mybatis.xml" />
<import resource="spring-security.xml" />
<import resource="spring-memcached.xml" />
</beans>
version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- 引入属性文件 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:rabbitmq.properties</value>
</list>
</property>
</bean>
<import resource="spring-mybatis.xml" />
<import resource="spring-security.xml" />
<import resource="spring-memcached.xml" />
</beans>
五 java使用方式
//key-value的方式插入缓存
@Override
@Cacheable( value = "siemCache", key = "'getStrategyInfoByLogSourceUuid_'+#logSourceUuid" )
public List<StrategyInfo> getStrategyInfoByLogSourceUuid(String logSourceUuid){
List<StrategyInfo> strategyInfos=new ArrayList<>();
List<StrategyLogSourceRel> strategyLogSourceRels=strategyLogSourceRelService.getStrategyLogSourceRelByLogSourceUuid(logSourceUuid);
if(CollectionUtils.isNotEmpty(strategyLogSourceRels)){
List<String> uuidList=new ArrayList<>();
strategyLogSourceRels.forEach(strategyLogSourceRel->{
uuidList.add(strategyLogSourceRel.getStrategyUuid());
});
strategyInfos = strategyInfodao.getStrategyInfoByUuidList(uuidList);
}
return strategyInfos;
}
//删除缓存
@Override
@CacheEvict( value = "siemCache", key = "'getStrategyInfoByLogSourceUuid_'+#logSourceUuid" )
public void deleteCache(String logSourceUuid){
}
@Override
@Cacheable( value = "siemCache", key = "'getStrategyInfoByLogSourceUuid_'+#logSourceUuid" )
public List<StrategyInfo> getStrategyInfoByLogSourceUuid(String logSourceUuid){
List<StrategyInfo> strategyInfos=new ArrayList<>();
List<StrategyLogSourceRel> strategyLogSourceRels=strategyLogSourceRelService.getStrategyLogSourceRelByLogSourceUuid(logSourceUuid);
if(CollectionUtils.isNotEmpty(strategyLogSourceRels)){
List<String> uuidList=new ArrayList<>();
strategyLogSourceRels.forEach(strategyLogSourceRel->{
uuidList.add(strategyLogSourceRel.getStrategyUuid());
});
strategyInfos = strategyInfodao.getStrategyInfoByUuidList(uuidList);
}
return strategyInfos;
}
//删除缓存
@Override
@CacheEvict( value = "siemCache", key = "'getStrategyInfoByLogSourceUuid_'+#logSourceUuid" )
public void deleteCache(String logSourceUuid){
}
注意:后台根据key值查看memcache缓存内容
(1)telnet进入11211端口: telnet 127.0.0.1 11211
(2)根据key找到对应的缓存: get key
示例:上面例子中 拼出的key值为 siemCache_getStrategyInfoByLogSourceUuid_32位uuid
get siemCache_getStrategyInfoByLogSourceUuid_32位uuid
(3)列出所有的连接池信息: stats items
(4)通过如上连接池信息获取 key 的值,再根据具体的key值找到缓存: stats cachedump 7 0
1)telnet进入11211端口: telnet 127.0.0.1 11211
(2)根据key找到对应的缓存: get key
示例:上面例子中 拼出的key值为 siemCache_getStrategyInfoByLogSourceUuid_32位uuid
get siemCache_getStrategyInfoByLogSourceUuid_32位uuid
(3)列出所有的连接池信息: stats items
(4)通过如上连接池信息获取 key 的值,再根据具体的key值找到缓存: stats cachedump 7 0