这里我主要就介绍下ehcache如何集成mybatis和spring,还有一些简单的用法,已经自己简单的理解,比较网上面资料太多,而且有点杂,就自己总结下
因为之前我也没有过这家伙,马上要准备做电商系统了,所以要来研究研究
源码下载地址:http://darrenzhong.com/?p=1346
首先需要两个主要的包ehcache-core-2.4.6.jar 和 mybatis-ehcache-1.0.1.jar ehcache-core一定要1.3以上的版本 因为1.3之前好像不支持集群的
首先需要一个ehcache.xml 我放在src目录下面
<?xml version="1.0" encoding="utf-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="30" overflowToDisk="false"/>
<!--
配置自定义缓存
maxElementsInMemory:缓存中允许创建的最大对象数
eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。
timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前,
两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效,
如果该值是 0 就意味着元素可以停顿无穷长的时间。
timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值,
这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。
overflowToDisk:内存不足时,是否启用磁盘缓存。
memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。
-->
<cache name="testCache"
maxElementsInMemory="10000"
eternal="true"
overflowToDisk="false"
timeToIdleSeconds="0"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU" />
</ehcache>
上面的diskStor path 你可以指定某一个路径下,java.io.tmpdir 指的是你系统的缓存目录 可以百度下
然后一般这个xml都需要有一个defaultCache 就是默认的cache配置 里面有哪些参数自己可以网上查查api
然后下面我还配置了一个testCache 我找网上资料 没看到哪里明说 然后我自己测试 发现ehcache是可以生成多个cache的 每个cache可以根据不同的业务场景作用于不同的业务(即里面的参数配置不同),所以这样看似多配置了,其实是更加增加了灵活性
然后在spring的配置文件里面配置一段
<!-- 使用ehcache缓存 -->
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml" />
</bean>
不用说 这个就是把xml和spring整合起来
然后在mybatis.xml里面需要配置这样一句 默认是支持还是不支持忘记了 反正给个true就肯定支持了
<settings>
<!-- 全局映射器启用缓存 -->
<setting name="cacheEnabled" value="true" />
</settings>
然后在对应的mapper.xml 里面加上
<cache type="org.mybatis.caches.ehcache.LoggingEhcache" >
<property name="timeToIdleSeconds" value="3600"/><!--1 hour-->
<property name="timeToLiveSeconds" value="3600"/><!--1 hour-->
<property name="maxEntriesLocalHeap" value="1000"/>
<property name="maxEntriesLocalDisk" value="10000000"/>
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>
后面的参数配置不加也可以 都会有一个默认值 大家也可以查查一共有哪些配置 然后根据自己的需要来配置 然后这个配置是会带上cache执行的日志 如果不要带日志可以把LogginEhcache缓存EhcacheCache
在mapper.xml这样设置了默认是全部操作都会执行缓存策略 如果有某些sql不需要执行 可以把useCache设置为false
<select id="selectByExample" resultMap="BaseResultMap" parameterType="com.anenjoy.manage.entity.TblUserTempExample" useCache="false" >
其实经过这样的配置ehcache已经基本OK了
那么来测试下
我是写在Controller里面的
long begin = System.nanoTime();
tempService.selectAll();
long end = System.nanoTime() - begin;
System.out.println("count :" + end);
// the second time
begin = System.nanoTime();
try {
tempService.insertTblUserTemp("1", "1", "1", "1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
end = System.nanoTime() - begin;
System.out.println("count :" + end);
// the second time
begin = System.nanoTime();
tempService.selectAll();
end = System.nanoTime() - begin;
System.out.println("count :" + end);
// the third time
begin = System.nanoTime();
tempService.selectAll();
end = System.nanoTime() - begin;
System.out.println("count :" + end);
return "";
这里面有4条输出语句
首先是查询一次某表 执行了查询sql
然后给某表插入一条信息 执行了插入sql
然后再查询某表 执行了查询sql,这是正确的 因为你执行了非查询语句,这个时候需要重新访问数据库
然后再一次查询某表 没有执行查询sql 这代表缓存是有用的,他就没有访问数据库了,直接从内存或者磁盘里面获取了
也可以根据count来查看操作的时间
count :681719
-------------------------------------------------com.anenjoy.manage.mapper.TblUserTempMapper.insert
insert into TBLUSERTEMP (ACTIVECODE, PASSWORDMD5, PASSWORDRANDOMKEY,
PHONE, EMAIL, USERNAME,
AWARTAR, STATUS, CREATEDATE,
USERID, IMSI, CHECKCODE
)
values (?, ?, ?,
?, ?, ?,
?, ?, ?,
?, ?, ?
)
count :129557388
-------------------------------------------------com.anenjoy.manage.mapper.TblUserTempMapper.selectByExample
select
ACTIVECODE, PASSWORDMD5, PASSWORDRANDOMKEY, PHONE, EMAIL, USERNAME, AWARTAR, STATUS,
CREATEDATE, USERID, IMSI, CHECKCODE
from TBLUSERTEMP
count :333938203
count :560704
然后这些基本上OK了
再讲讲 ehcache 如果手动将数据放入缓存中
首先分享一个工具类
package com.anenjoy.manage.util;
import java.io.Serializable;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class EhcacheUtil {
final static Log log = LogFactory.getLog(EhcacheUtil.class);
private static final String appointPath="src/ehcache.xml";
private CacheManager cacheManager;
private static EhcacheUtil ehcacheUtil;
private EhcacheUtil(String appointPath){
cacheManager=CacheManager.create(appointPath);
}
public static EhcacheUtil getInstance(){
if(ehcacheUtil==null){
ehcacheUtil=new EhcacheUtil(appointPath);
}
return ehcacheUtil;
}
/**
* 从缓存中获取对象
* @param cache_name
* @param key
* @return
*/
public Serializable getObjectCached(String cache_name, Serializable key){
Cache cache = getCache(cache_name);
if(cache!=null){
try {
Element elem = cache.get(key);
if(elem!=null && !cache.isExpired(elem))
return elem.getValue();
} catch (Exception e) {
log.error("Get cache("+cache_name+") of "+key+" failed.", e);
}
}
return null;
}
/**
* 把对象放入缓存中
* @param cache_name
* @param key
* @param value
*/
public synchronized void put(String cache_name, Object key, Object value){
Cache cache = getCache(cache_name);
if(cache==null){
/**
* 2:允许内存中缓存对象的大小,这里是10000000
* 3:允许在内存达到最大后写入磁盘
* 4:表示永久保存
* 5:最后两个参数表示element存活时间无穷大
*/
cache= new Cache(cache_name, 1000000, true, true, 0, 0);
cacheManager.addCache(cache);
}else{
try {
cache.remove(key);
Element elem = new Element(key, value);
cache.put(elem);
} catch (Exception e) {
log.error("put cache("+cache_name+") of "+key+" failed.", e);
}
}
}
/**
* 获取指定名称的缓存
* @param arg0
* @return
* @throws IllegalStateException
*/
public Cache getCache(String arg0) throws IllegalStateException {
return cacheManager.getCache(arg0);
}
/**
* 获取缓冲中的信息
* @param cache
* @param key
* @return
* @throws IllegalStateException
* @throws CacheException
*/
public Element getElement(String cache, Object key){
Cache cCache = getCache(cache);
return cCache.get(key);
}
public void removeElement(String cacheName, Object key) {
Cache cache = cacheManager.getCache(cacheName);
if (cache != null) {
cache.remove(key);
}
}
public void removeCache(String cacheName) {
Cache cache = cacheManager.getCache(cacheName);
if (cache != null) {
cacheManager.removeCache(cacheName);
}
}
/**
* 停止缓存管理器
*/
public void shutdown(){
if(cacheManager!=null)
cacheManager.shutdown();
}
public static void main(String[] args) {
EhcacheUtil.getInstance().put("<span style="font-family: Arial, Helvetica, sans-serif;">testCache</span>", "user", "user");
System.out.println(EhcacheUtil.getInstance().getCache("testCache"));
System.out.println(EhcacheUtil.getInstance().getElement("testCache","user").getValue());
}
}
其实看了这个工具类 基本上就OK了,里面一些常用的方法已经写进去了
需要注意的是 在main方法里面 我put的第一个参数testCache 必须是ehcache.xml里面需要配置的 也就是我上面说了 不同的业务可能对于不同的缓存配置
因为我也是这两天才了解的这个,所以如果有什么说的不对的地方,还希望高手指点,上面所写仅仅是一个分享,只有是看网上资料太杂,当然有什么不懂的朋友也可以留言问我。