评论

收藏

[NoSQL] Memcached之——整合Spring完整示例

数据库 数据库 发布于:2021-07-01 10:36 | 阅读数:349 | 评论:0

转载请注明出处: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);
}
}
  
关注下面的标签,发现更多相似文章