转载:http://blog.csdn.net/l1028386804/article/details/48464111
在前面的几篇博文中,我们记录了Memcached整合Spring的一些方法,现在我们就基于这些方法实现一个Memcached整合Spring的完整示例,好了不多说了,我们直接上代码吧。
一、配置
1、MemcachedCacheManager
- package com.cdsmartlink.framework.cache.memcached;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.ConcurrentMap;
- import org.springframework.cache.Cache;
- import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;
- import com.danga.MemCached.MemCachedClient;
- /**
- * Spring Cache整合Memcached实现
- * @author liuyazhuang
- */
- 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; //memcached的客户端
- 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;
- }
- }
2、MemcachedCache
- package com.cdsmartlink.framework.cache.memcached;
- import org.springframework.cache.Cache;
- import org.springframework.cache.support.SimpleValueWrapper;
- import com.danga.MemCached.MemCachedClient;
- /**
- * MemcachedCache的实现,主要实现spring的cache接口
- * @author liuyazhuang
- *
- */
- 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;
- }
- }
3、MemCache
- package com.cdsmartlink.framework.cache.memcached;
- import java.util.HashSet;
- import java.util.Set;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import com.danga.MemCached.MemCachedClient;
- /**
- * Memcached的封装类
- * @author liuyazhuang
- *
- */
- 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 (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, value, expire);
- 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;
- }
- }
4、applicationContext-memcached.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: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-3.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.0.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
- http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
- http://www.springframework.org/schema/cache
- http://www.springframework.org/schema/cache/spring-cache-3.2.xsd">
- <!-- 扫描项目包的根路径 -->
- <context:component-scan base-package="com.cdsmartlink" />
- <context:component-scan base-package="com.cdsmartlink.utils.dao.base.impl"/>
- <!-- =================================== 配置Memcached =============================== -->
- <!-- 开启缓存 -->
- <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true" />
- <!-- 导入外部properties -->
- <context:property-placeholder location="classpath:memcached.properties"/>
- <bean id="memcachedPool" class="com.danga.MemCached.SockIOPool"
- factory-method="getInstance" init-method="initialize" destroy-method="shutDown">
- <constructor-arg>
- <value>neeaMemcachedPool</value>
- </constructor-arg>
- <property name="servers">
- <list>
- <value>${memcache.server}</value>
- </list>
- </property>
- <property name="initConn">
- <value>${memcache.initConn}</value>
- </property>
- <property name="minConn">
- <value>${memcache.minConn}</value>
- </property>
- <property name="maxConn">
- <value>${memcache.maxConn}</value>
- </property>
- <property name="maintSleep">
- <value>${memcache.maintSleep}</value>
- </property>
- <property name="nagle">
- <value>${memcache.nagle}</value>
- </property>
- <property name="socketTO">
- <value>${memcache.socketTO}</value>
- </property>
- </bean>
- <!-- 配置MemcachedClient -->
- <bean id="memcachedClient" class="com.danga.MemCached.MemCachedClient">
- <constructor-arg>
- <value>neeaMemcachedPool</value>
- </constructor-arg>
- </bean>
- <!-- 配置缓存管理 -->
- <bean id="cacheManager" class="com.cdsmartlink.framework.cache.memcached.MemcachedCacheManager">
- <property name="memcachedClient" ref="memcachedClient"/>
- <!-- 配置缓存时间 -->
- <property name="configMap">
- <map>
- <!-- key缓存对象名称 value缓存过期时间 -->
- <entry key="systemCache" value="3600"/>
- </map>
- </property>
- </bean>
- <!-- 导入调度任务 -->
- <!-- <import resource="spring-quartz.xml" /> -->
- </beans>
5、memcached.properties
- #Memcached基本配置
- memcache.server=192.168.254.120:12000
- memcache.initConn=20
- memcache.minConn=10
- memcache.maxConn=50
- memcache.maintSleep=3000
- memcache.nagle=false
- memcache.socketTO=3000
6、web.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
- id="WebApp_ID" version="3.0">
- <display-name>Smartlink</display-name>
- <!-- 配置spring监听器 -->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <!-- 配置初始化监听 -->
- <listener>
- <listener-class>com.cdsmartlink.utils.listener.WebServerStartListener</listener-class>
- </listener>
- <!-- 加载配置文件路径 -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath*:applicationContext*.xml</param-value>
- </context-param>
- <!-- springmvc配置 -->
- <servlet>
- <servlet-name>smartlink</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>smartlink</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
- <!-- 配置OpenSessionInView -->
- <filter>
- <filter-name>hibernateFilter</filter-name>
- <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
- <!-- singleSession默认为true,若设为false则等于没用OpenSessionInView -->
- <init-param>
- <param-name>singleSession</param-name>
- <param-value>true</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>hibernateFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <!-- 字符编码过滤器 -->
- <filter>
- <filter-name>CharacterEncodingFilter</filter-name>
- <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
- <init-param>
- <param-name>encoding</param-name>
- <param-value>UTF-8</param-value>
- </init-param>
- <init-param>
- <param-name>forceEncoding</param-name>
- <param-value>true</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>CharacterEncodingFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <welcome-file-list>
- <welcome-file>index.html</welcome-file>
- <welcome-file>index.htm</welcome-file>
- <welcome-file>index.jsp</welcome-file>
- <welcome-file>default.html</welcome-file>
- <welcome-file>default.htm</welcome-file>
- <welcome-file>default.jsp</welcome-file>
- </welcome-file-list>
- <error-page>
- <error-code>404</error-code>
- <location>/static/html/page_404/404.html</location>
- </error-page>
- </web-app>
二、使用示例
1、CacheBaseService
- package com.cdsmartlink.utils.service;
- import java.io.Serializable;
- /**
- * 带有缓存的service
- * @author liuyazhuang
- *
- * @param <T>
- */
- public interface CacheBaseService<T> extends SinglePKBaseService<T>{
- T get(Serializable id);
- void save(T[] entity) ;
- void save(T entity) ;
- Serializable saveObj(T entity);
- void update(T entity) ;
- void delete(T entity) ;
- public int delete(Serializable id) ;
- public void delete(Serializable... id) ;
- }
2、CacheBaseServiceImpl
- package com.cdsmartlink.utils.service.impl;
- import java.io.Serializable;
- import org.springframework.cache.annotation.CacheEvict;
- import org.springframework.cache.annotation.CachePut;
- import com.cdsmartlink.utils.service.CacheBaseService;
- public abstract class CacheBaseServiceImpl<T> extends SinglePKBaseServiceImpl<T> implements CacheBaseService<T>{
- @Override
- @CachePut(value="systemCache")
- public T get(Serializable id){
- return super.get(id);
- }
- @Override
- @CacheEvict(value="systemCache", allEntries = true, beforeInvocation = true)
- public void save(T[] entity) {
- super.save(entity);
- }
- @Override
- @CacheEvict(value="systemCache", allEntries = true, beforeInvocation = true)
- public void save(T entity){
- super.save(entity);
- }
- @Override
- @CacheEvict(value="systemCache", allEntries = true, beforeInvocation = true)
- public Serializable saveObj(T entity){
- return super.saveObj(entity);
- }
- @Override
- @CacheEvict(value="systemCache", allEntries = true, beforeInvocation = true)
- public void update(T entity){
- super.update(entity);
- }
- @Override
- @CacheEvict(value="systemCache", allEntries = true, beforeInvocation = true)
- public void delete(T entity){
- super.delete(entity);
- }
- @Override
- @CacheEvict(value="systemCache", beforeInvocation = true)
- public int delete(Serializable id){
- return super.delete(id);
- }
- @Override
- @CacheEvict(value="systemCache", allEntries = true, beforeInvocation = true)
- public void delete(Serializable... id){
- super.delete(id);
- }
- }
3、StoreAdvertmentService
- package com.cdsmartlink.system.store.service;
- import java.util.List;
- import com.cdsmartlink.system.store.entity.StoreAdvertment;
- import com.cdsmartlink.utils.service.CacheBaseService;
- /**
- * 商家广告service
- * @author liuyazhuang
- *
- */
- public interface StoreAdvertmentService extends CacheBaseService<StoreAdvertment> {
- /**
- * 缓存key的前缀
- */
- String STORE_AD = "store_ad_";
- /**
- * 获取广告图
- * @param storeId
- * @param type
- * @param limit
- * @return
- */
- List<StoreAdvertment> getStoreAdvertments(Long storeId, Integer type, int limit);
- }
4、StoreAdvertmentServiceImpl
- package com.cdsmartlink.system.store.service.impl;
- import java.util.List;
- import javax.annotation.Resource;
- import org.springframework.cache.annotation.Cacheable;
- import org.springframework.stereotype.Service;
- import com.cdsmartlink.system.store.dao.StoreAdvertmentDao;
- import com.cdsmartlink.system.store.entity.StoreAdvertment;
- import com.cdsmartlink.system.store.service.StoreAdvertmentService;
- import com.cdsmartlink.utils.dao.QueryMode;
- import com.cdsmartlink.utils.dao.QueryParse;
- import com.cdsmartlink.utils.dao.base.BaseDao;
- import com.cdsmartlink.utils.service.impl.CacheBaseServiceImpl;
- @Service
- public class StoreAdvertmentServiceImpl extends CacheBaseServiceImpl<StoreAdvertment> implements
- StoreAdvertmentService {
- @Resource
- private StoreAdvertmentDao storeAdvertmentDao;
- @Override
- protected BaseDao<StoreAdvertment> getDao() {
- return storeAdvertmentDao;
- }
- @Override
- protected void setQueryParse(QueryParse<StoreAdvertment> qp,
- QueryMode queryMode) {
- }
- @Override
- @Cacheable(value=SYSTEM_CACHE, key="'store_ad_'+ #storeId")//store_ad_为key的自定义字符串前缀,这个前缀可以根据具体业务设定,以免和其他缓存数据冲突,注意,这个字符串前缀要用单引号''括起来,否则会报错
- public List<StoreAdvertment> getStoreAdvertments(Long storeId, Integer type, int limit) {
- return storeAdvertmentDao.getStoreAdvertments(storeId, type, limit);
- }
- }