下载安装
官网下载地址
http://www.ehcache.org/downloads/选择你需要的版本,然后将JAR包及ehcache.xml导入到项目lib下编译
Maven配置
JAVA代码块
首先我们要想好要实现什么样的功能,我们需要拦截service层的增删改查接口然后以不同的动作对缓存进行不同的操作:查询、获取、列表等数据从缓存获取,删除、修改等数据删除已有缓存
只添加缓存和读取缓存
创建JAVA类MethodPutCacheInterceptor(缓存拦截器)该类只对针对get、load、list、search接口做缓存和读取数据
public class MethodPutCacheInterceptor {
private Cache ehCache;
//通过spring注入方式实例化ehcache
public void setCache(Cache cache) {
this.ehCache = cache;
}
//构造函数
public MethodPutCacheInterceptor() {
super();
}
//spring AOP 方法被调用时被拦截
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
//获取类名
String targetName = pjp.getTarget().getClass().getName();
//获取方法名
String methodName = pjp.getSignature().getName();
//获取参数
Object[] atguments = pjp.getArgs();
Object result;
//获取cache key值
String cacheKey = getCacheKey(targetName, methodName, atguments);
//通过key获取缓存value
Element element = ehCache.get(cacheKey);
if (element == null) {
logger.info("从DB读取数据!");
//执行连接点里面的方法
result = pjp.proceed();
//将连接点方法返回的数据添加到缓存里
element = new Element(cacheKey, (Serializable) result);
ehCache.put(element);
} else {
logger.info("从缓存读取数据!");
}
//最终返回缓存数据
return element.getObjectValue();
}
//spring aop 错误返回
public void doThrowing(JoinPoint jp, Throwable ex) {
System.out.println("method " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName() + " throw exception");
System.out.println(ex.getMessage());
}
/**
* 获得cache key的方法,cache key是Cache中一个Element的唯一识
* cache key包括 包名+类名+方法名
* @param targetName 类名
* @param methodName 方法名
* @param arguments 参数名
* @return String
*/
private String getCacheKey(String targetName, String methodName, Object[] arguments) {
StringBuffer sb = new StringBuffer();
sb.append(targetName).append(".").append(methodName);
if ((arguments != null) && (arguments.length != 0)) {
for (Object object : arguments) {
sb.append(".").append(object);
}
}
return sb.toString();
}
}
- 创建JAVA类MethodRemoveCacheInterceptor(缓存拦截器)该类只对针对delete、remove、update接口做缓存数据清除
public class MethodRemoveCacheInterceptor{
private Cache ehCache;
//通过spring注入方式实例化ehcache
public void setCache(Cache cache) {
this.ehCache = cache;
}
//构造函数
public MethodPutCacheInterceptor() {
super();
}
public void doAfter(JoinPoint jp) {
//获取类名
String targetName = jp.getTarget().getClass().getName();
//获取缓存key集合
List list = ehCache.getKeys();
for (Object key : list) {
String cacheKey = String.valueOf(key);
//判断key中是否含有该类名
if (cacheKey.startsWith(targetName)) {
//存在则删除该缓存
ehCache.remove(cacheKey);
}
}
}
public void doThrowing(JoinPoint jp, Throwable ex) {
//获取错误信息
System.out.println("method " +jp.getTarget().getClass().getName() + "." + jp.getSignature().getName() + " throw exception");
System.out.println(ex.getMessage());
}
}
applicationContext.xml配置
<!--注入EhCacheManagerFactoryBean-->
<bean id="defaultCacheManager"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<!--获取ehcache.xml文件-->
<property name="configLocation">
<value>classpath:cache/ehcache.xml</value>
</property>
</bean>
<!--注入EhCacheFactoryBean-->
<bean id="ehCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<!--指定父类cacheManager的bean-->
<property name="cacheManager" ref="defaultCacheManager" />
<!--指定ehcache.xml缓存名为userCache的缓存配置,没找到则默认为defaultCache-->
<property name="cacheName">
<value>userCache</value>
</property>
</bean>
<!--将EhCacheFactoryBean注入到类MethodPutCacheInterceptor中cache对象中-->
<bean id="methodPutCacheInterceptor" class="dome.core.tools.ehcache.MethodPutCacheInterceptor">
<property name="cache" ref="ehCache" />
</bean>
<!--Spring AOP 实现配置-->
<!--实现service层中get、list、find接口拦截-->
<aop:config>
<aop:aspect id="MethodPutCacheInterceptor" ref="methodPutCacheInterceptor">
<aop:pointcut id="methodPutCacheService"
expression="execution(* dome.core.*.service.*.get*(..)) or
execution(* dome.core.*.service.*.list*(..)) or
execution(* dome.core.*.service.*.find*(..)))"></aop:pointcut>
<aop:around pointcut-ref="methodPutCacheService" method="doAround" />
<aop:after-throwing pointcut-ref="methodPutCacheService" method="doThrowing" throwing="ex" />
</aop:aspect>
</aop:config>
<!--实现service层中delete、remove、update接口拦截-->
<bean id="methodRemoveCacheInterceptor" class="dome.core.tools.ehcache.MethodRemoveCacheInterceptor">
<property name="cache" ref="ehCache" />
</bean>
<aop:config>
<aop:aspect id="MethodRemoveCacheInterceptor" ref="methodRemoveCacheInterceptor">
<aop:pointcut id="methodRemoveCacheService"
expression="execution(* dome.core.*.service.*.delete*(..)) or
execution(* dome.core.*.service.*.remove*(..)) or
execution(* dome.core.*.service.*.update*(..)))"></aop:pointcut>
<aop:after pointcut-ref="methodRemoveCacheService" method="doAfter" />
<aop:after-throwing pointcut-ref="methodRemoveCacheService" method="doThrowing" throwing="ex" />
</aop:aspect>
</aop:config>
ehcache.xml配置
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
monitoring="autodetect" dynamicConfig="true">
<diskStore path="java.io.tmpdir" />
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false" />
<cache name="userCache"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="300000"
timeToLiveSeconds="600000"
memoryStoreEvictionPolicy="LFU">
</cache>
</ehcache>
每当程序调用service层接口时,就会判断接口名是否以get、list、find开头,如果是则进入spring aop拦截中判断该方法是否在缓存中,如果存在则直接从缓存获取返回值,如果不存在则直接运行连接点方法(业务类或者dao层)然后将返回值放入缓存并返回缓存中的数据。
如果调用serivce层delete、update、remove开头的接口,则进入拦截器判断是否存在该缓存,如果存在则删除缓存。