1.所需jar包:
ehcache-core-2.6.0.jar
ehcache-terracotta-2.6.0.jar (与terracotta集成)
2.EhcacheCacheManagerProxy代码如下:
package cache.ehcache;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Status;
import net.sf.ehcache.cluster.CacheCluster;
import net.sf.ehcache.cluster.ClusterNode;
import net.sf.ehcache.cluster.ClusterScheme;
import net.sf.ehcache.cluster.ClusterTopologyListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.ehcache.EhCacheCache;
import org.springframework.cache.support.AbstractCacheManager;
import org.springframework.cache.support.NoOpCacheManager;
import org.springframework.util.Assert;
public class EhcacheCacheManagerProxy extends AbstractCacheManager {
private static final Logger LOGGER = LoggerFactory.getLogger(EhcacheCacheManagerProxy.class);
private CacheManager cacheManager;
private NoOpCacheManager noOpCacheManager = new NoOpCacheManager();
private List<ClusterTopologyListener> listenerList;
private boolean globalFlag = true; //外部标志位
private boolean innerFlag = true; //内部标志位
/**
* Returns the backing Ehcache {@link net.sf.ehcache.CacheManager}.
* @return
*/
public CacheManager getCacheManager() {
return cacheManager;
}
/**
* Sets the backing EhCache {@link net.sf.ehcache.CacheManager}.
*/
public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
/**
*
* @param globalFlag
*/
public void setGlobalFlag(boolean globalFlag) {
this.globalFlag = globalFlag;
}
public void setListenerList(List<ClusterTopologyListener> listenerList) {
this.listenerList = listenerList;
}
@Override
protected Collection<Cache> loadCaches() {
Assert.notNull(this.cacheManager, "A backing EhCache CacheManager is required");
Status status = this.cacheManager.getStatus();
Assert.isTrue(Status.STATUS_ALIVE.equals(status),
"An 'alive' EhCache CacheManager is required - current cache is " + status.toString());
String[] names = this.cacheManager.getCacheNames();
Collection<Cache> caches = new LinkedHashSet<Cache>(names.length);
for (String name : names) {
caches.add(new EhCacheCache(this.cacheManager.getEhcache(name)));
}
//add cluster listener
addClusterListener();
return caches;
}
@Override
public Cache getCache(String name) {
if(!globalFlag || !innerFlag){
return noOpCacheManager.getCache(name);
}
Cache cache = super.getCache(name);
if (cache == null) {
// check the EhCache cache again
// (in case the cache was added at runtime)
Ehcache ehcache = this.cacheManager.getEhcache(name);
if (ehcache != null) {
cache = new EhCacheCache(ehcache);
addCache(cache);
}
}
return cache;
}
private void addClusterListener(){
if(listenerList == null){
listenerList = new ArrayList<ClusterTopologyListener>();
}
listenerList.add(new ClusterTopologyListener(){
@Override
public void nodeLeft(ClusterNode node) {
LOGGER.error("cluster nodeLeft,nodeIp=" + (node == null ? "null" : node.getIp()));
innerFlag = true;
}
@Override
public void nodeJoined(ClusterNode node) {
LOGGER.error("cluster nodeJoined,nodeIp=" + (node == null ? "null" : node.getIp()));
innerFlag = true;
}
@Override
public void clusterRejoined(ClusterNode oldNode, ClusterNode newNode) {
LOGGER.error("cluster clusterRejoined,oldNodeIp=" + (oldNode == null ? "null" : oldNode.getIp()) + ",newNodeIp=" + (newNode == null ? "null" : newNode.getIp()));
innerFlag = true;
}
@Override
public void clusterOnline(ClusterNode node) {
LOGGER.error("cluster clusterOnline,nodeIp=" + (node == null ? "null" : node.getIp()));
innerFlag = true;
}
@Override
public void clusterOffline(ClusterNode node) {
LOGGER.error("cluster clusterOffline,nodeIp=" + (node == null ? "null" : node.getIp()));
innerFlag = false;
}
});
CacheCluster cluster = cacheManager.getCluster(ClusterScheme.TERRACOTTA);
for(ClusterTopologyListener listener : listenerList){
if(listener == null){
continue;
}
cluster.addTopologyListener(listener);
}
}
}
3.两个配置文件如下:
spring-cache.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:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd">
<!-- 指定ehcache.xml的位置 -->
<bean id="cacheManagerFactory"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="classpath:/demo/resouce/spring/cache/ehcache.xml" p:shared="true" />
<!-- 声明缓存Manager -->
<bean id="ehcacheManager" class="cache.ehcache.EhcacheCacheManagerProxy"
p:cacheManager-ref="cacheManagerFactory"
p:globalFlag="true">
</bean>
</beans>
ehcache.xml(cache 配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="false" monitoring="autodetect"
dynamicConfig="true" name="test">
<cacheManagerEventListenerFactory class="" properties=""/>
<terracottaConfig url="ip1:端口,ip2:端口" rejoin="true"/> <!--terracotta服务器配置 -->
<defaultCache
maxEntriesLocalHeap="10000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="5"
timeToLiveSeconds="5"
memoryStoreEvictionPolicy="LRU"
maxElementsInMemory="100000"
maxElementsOnDisk="100000"
copyOnRead="true">
<terracotta clustered="true"> 开启集群
<nonstop immediateTimeout="false" timeoutMillis="3000">
<timeoutBehavior type="noop" />
</nonstop>
</terracotta>
</defaultCache>
<cache name="test1"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="600"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"
maxElementsInMemory="100000"
maxElementsOnDisk="100000"
copyOnRead="true">
<terracotta clustered="true">
<nonstop immediateTimeout="false" timeoutMillis="3000">
<timeoutBehavior type="noop" />
</nonstop>
</terracotta>
</cache>
</ehcache>
spring-cache-test.xml (AOP配置文件)
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang" 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.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang-3.1.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-3.1.xsd">
<!-- 用户缓存配置 -->
<aop:config>
<aop:advisor advice-ref="testAdvice" pointcut="execution(* com.demo.impl.TestImpl.*(..))"/>
</aop:config>
<cache:advice id="testAdvice" cache-manager="ehcacheManager">
<cache:caching cache="test1">
<cache:cacheable method="getTest" key="'${test}:key'"/>
</cache:caching>
</cache:advice>
</beans>