在《Spring集成memcache(二)xmemcache》的基础之上扩展支持注解形式,使开发更加简洁。
参考资料如下:
http://zj0121.iteye.com/blog/1852270
需要注意的是扩展支持注解需要Spring AOP的支持,需要导入相应的jar包:
1.aopalliance-1.0.jar
2.aopalliance-alpha1.jar
3.slf4j-api-1.7.5.jar
其中slf4j-api-1.7.5.jar提供的是日志的接口规范,如果工程目录下使用的是log4j,则slf4j-api-1.7.5.jar会绑定调用log4j.jar。
具体说明可以访问http://blog.csdn.net/tengdazhang770960436/article/details/18006127。
从头开始进行配置,步骤如下:
1.添加xmemcache.jar包至工程中;
- aopalliance-1.0.jar
- aopalliance-alpha1.jar
- slf4j-api-1.7.5.jar
- xmemcached-1.3.8.jar
2.在web.xml文件中添加配置
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/conf/spring/*-beans.xml </param-value> </context-param>
3.在属性文件中添加如下配置:
#memcache配置 memcache.ip=127.0.0.1 memcache.port=11211 memcache.pool.size=5
4.在/WEB-INF/conf/spring/目录下添加配置文件memcache-beans.xml
<?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:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.2.xsd" default-autowire="byName"> <bean id="memcachedClientBuilder" class="net.rubyeye.xmemcached.XMemcachedClientBuilder"> <constructor-arg> <list> <bean class="java.net.InetSocketAddress"> <constructor-arg value="${memcache.ip}" /> <constructor-arg value="${memcache.port}" /> </bean> </list> </constructor-arg> <property name="connectionPoolSize" value="${memcache.pool.size}" /> <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.iaccount.framework.cache.memcache.MemcachedCacheManager"> <property name="memcachedClient" ref="memcachedClient" /> <property name="configMap"> <map> <!-- key:@Cacheable、@CachePut、@CacheEvict等的value属性。value:缓存过期时间(单位:秒),默认值:0 --> <entry key="defaultCache" value="0" /><!-- 默认缓存区 不过期 --> <entry key="inTimeCache" value="3600" /><!-- 实时缓存区 一小时过期 --> </map> </property> </bean> <cache:annotation-driven cache-manager="cacheManager" /> </beans>
5.参考了EHCacheCacheManager的源码,写了一个基于XMemcached的MemcachedCacheManager
a.memcache缓存连接类 MemCache.java
import java.util.HashSet; import java.util.Set; import java.util.concurrent.TimeoutException; import net.rubyeye.xmemcached.MemcachedClient; import net.rubyeye.xmemcached.exception.MemcachedException; 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); } catch (TimeoutException e) { log.warn("获取 Memcached 缓存超时", e); } catch (InterruptedException e) { log.warn("获取 Memcached 缓存被中断", e); } catch (MemcachedException e) { log.warn("获取 Memcached 缓存错误", e); } return value; } public void put(String key, Object value) { if (value == null) return; try{ key = this.getKey(key); memcachedClient.setWithNoReply(key, expire, value); keySet.add(key); }catch (InterruptedException e){ log.warn("更新 Memcached 缓存被中断", e); }catch (MemcachedException e){ log.warn("更新 Memcached 缓存错误", e); } } public void clear(){ for (String key : keySet){ try{ memcachedClient.deleteWithNoReply(this.getKey(key)); }catch (InterruptedException e){ log.warn("删除 Memcached 缓存被中断", e); }catch (MemcachedException e){ log.warn("删除 Memcached 缓存错误", e); } } } public void delete(String key){ try{ key = this.getKey(key); memcachedClient.deleteWithNoReply(key); }catch (InterruptedException e){ log.warn("删除 Memcached 缓存被中断", e); }catch (MemcachedException e){ log.warn("删除 Memcached 缓存错误", e); } } private String getKey(String key){ return name + "_" + key; } }
b.缓存类 MemcachedCache.java
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 MemcachedClient memcachedClient; private final MemCache memCache; public MemcachedCache(String name, int expire, MemcachedClient memcachedClient){ this.name = name; this.memcachedClient = memcachedClient; 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 MemcachedClient getNativeCache(){ return this.memcachedClient; } @Override public void put(Object key, Object value){ memCache.put(key.toString(), value); } }
c.缓存管理类 MemcachedCacheManager.java
import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import net.rubyeye.xmemcached.MemcachedClient; 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; 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; } public void setMemcachedClient(MemcachedClient memcachedClient){ this.memcachedClient = memcachedClient; } public void setConfigMap(Map<String, Integer> configMap){ this.expireMap = configMap; } }
6.数据操作类
@Cacheable(value="defaultCache") public List<FmSupplier> getEnableSuppliers(){ FmSupplierQuery query = new FmSupplierQuery(); query.setIsDeleted(YesNoType.NO.getCode()); query.setSupplierStatus(SupplierStatus.ENABLE.getCode()); return fmSupplierMapper.selectListByQuery(query); } @Cacheable(value="defaultCache", key="#id") public FmSupplier selectByPrimaryKey(Long id){ return fmSupplierMapper.selectByPrimaryKey(id); }
1.在缓存区defaultCache中获取数据,第一次请求时无数据,则会从数据库中获取并放至缓存中;
2.第二次请求时则直接从缓存中获取;